makewhatis version 1.1 (later to become part of the manpack archive)

This commit is contained in:
gdr 1996-01-28 00:33:14 +00:00
parent 39f4efc5b8
commit 8ae768d073
7 changed files with 553 additions and 150 deletions

View File

@ -1,14 +1,71 @@
--------------------------------------------
Name: makewhatis
Version: 1.0
Version: 1.1
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.
===========
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.
============
Copy makewhatis to /usr/sbin and makewhatis.1 to $(USRMAN)/man1.
Alternately, you can type "dmake install" from this directory.
============
Distribution:
============
Makewhatis is freeware. You may distribute this anywhere provided
that the archive remains intact.
=======
Changes:
=======
v1.1: (29 May 94)
Makewhatis will now ignore any man page starting with ".so", in
order to eliminate multiple files. The resultant blank lines in
the whatis database have therefore been eliminated.
Changed -v flag to {-v1|-v2} for differing stages of verbosity.
Only error output will be logged with the -l flag.
Manual page was updated, to include a correction to the -o flag usage
and the modification to the -v flag. Descriptions of bugs unlikely
to be fixed were added. Date and version were changed.
Fixed bug where input buffer wasn't properly terminated, and added
checks for buffer overflows.
Makewhatis will now display all commands about which the manual page
is written. For example, if foo.1 described both foo(1) and bar(1),
and bar.1 was an .so (or .l) link to foo.1, then the database entry
will have changed from
foo (1) - extract and add thingys from the bork stream
to
foo, bar (1) - extract and add thingys from the bork stream
Makewhatis used to pick up the first NAME string in the file as a reference
point. Now, any NAME is ignored in any line starting with .\" or .TH
Filename chapter numbers will now be correctly extracted regardless of the
existence of .Z, .z, .F, or .f suffixes, or of the existence of '.' within
the base file name.
Makewhatis is now linked with Soenke's gnulib for the getopt() function,
rather than using the libc version.
Stack usage was reduced to 1k. Be aware, though, that a fair amount
of global storage is used, including three 1k buffers.
v1.0: (15 May 94)
Initial release.

View File

@ -7,8 +7,28 @@
#include <ctype.h>
#include "makewhatis.h"
char buffer[BUFFERSIZE];
static char buffer2[BUFFERSIZE];
#define NAME1 "NAME"
#define NAME2 "N\bNA\bAM\bME\bE"
#define NAME3 "N\bN\bN\bNA\bA\bA\bAM\bM\bM\bME\bE\bE\bE"
#define SYNOPSIS1 "SYNOPSIS"
#define SYNOPSIS2 "S\bSY\bYN\bNO\bOP\bPS\bSI\bIS\bS"
#define SYNOPSIS3 "S\bS\bS\bSY\bY\bY\bYN\bN\bN\bNO\bO\bO\bOP\bP\bP\bPS\bS\bS\bSI\bI\bI\bIS\bS\bS\bS"
#define DESCRIPTION1 "DESCRIPTION"
#define DESCRIPTION2 "D\bDE\bES\bSC\bCR\bRI\bIP\bPT\bTI\bIO\bON\bN"
#define DESCRIPTION3 "D\bD\bD\bDE\bE\bE\bES\bS\bS\bSC\bC\bC\bCR\bR\bR\bRI\bI\bI\bIP\bP\bP\bPT\bT\bT\bTI\bI\bI\bIO\bO\bO\bON\bN\bN\bN"
char buffer[BUFFERSIZE]; /* contains the command description */
char titlebuf[BUFFERSIZE]; /* contains the command name */
static char buffer2[BUFFERSIZE]; /* used for chars read from man page */
#ifdef TEST_FILLBUFFER
short v_flag=2;
# define output_fp stdout
# define error_fp stderr
#else
extern FILE *output_fp; /* output file descriptor -- may be stdout */
extern FILE *error_fp; /* error file descriptor -- may be stderr */
#endif
/* void fillbuffer (char *filename);
*
@ -19,10 +39,19 @@ static char buffer2[BUFFERSIZE];
*
* 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.
* "SYNOPSIS", or "DESCRIPTION", whichever comes first. <titlebuf>
* will contain all printable text starting with the first printable
* non-whitespace character following "NAME" and ending with the
* last printable character before the first '-' following "NAME".
*
* If an error occurs, <buffer> will be an empty string (ie:
* buffer[0] == '\0')
*
* Warning: This routine was written to be fast at the expense of code
* size. It also has a lot of "special case"ing since it could
* be fed nroff source, aroff'd output, or text files that may
* include formatting control codes. If you're looking for some
* nice neat code, you're not going to find it here.
*/
void fillbuffer (char *filename) {
@ -35,6 +64,18 @@ void fillbuffer (char *filename) {
short in_comment;
short in_format_BR;
short in_format_f;
short foo;
/*
* Set p4 and p5 to the ends of buffer and titlebuf, respectively.
* These are used for error checking, so that we don't overflow the
* buffers. Using pointers will speed things up a bit at the cost
* of four bytes of local storage. They are not global for the sake
* of speed.
*/
char *p4 = buffer + BUFFERSIZE;
char *p5 = titlebuf + BUFFERSIZE;
/*
* open the file
@ -42,59 +83,233 @@ void fillbuffer (char *filename) {
if ((fp = fopen(filename,"rb")) == NULL) {
buffer[0] = '\0';
if (v_flag) fprintf (error_fp,"Open failed for file \"%s\"\n",filename);
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.
* see if it includes another man page
*/
if ((fgets(buffer2,4,fp) == NULL) || (strncmp(buffer2,".so",3)==0)) {
buffer[0] = '\0';
titlebuf[0] = '\0';
fclose(fp);
return;
}
fseek(fp,0L,SEEK_SET);
/*
* Make fp point to the first newline following NAME so that the
* next block read will pick it up as the first character. This is
* needed for the next section of code following this one.
*/
for(;;) {
count = fread(buffer2,sizeof(char),BUFFERSIZE-1,fp);
if (count == 0) {
/*
* read in buffer2 in a line-oriented fashion at first so that we
* can more easily ignore .\" and .TH lines
*/
if (fgets(buffer2,BUFFERSIZE,fp)==NULL) {
/*
* eof or error, and we haven't found "NAME" yet ... return
* an empty string
*/
buffer[0] = '\0';
titlebuf[0] = '\0';
fclose(fp);
if (v_flag) fprintf (error_fp,
"EOF or error on %s, NAME not found.\n",filename);
return;
}
buffer2[count] = '\0';
p1 = strstr(buffer2,"NAME");
if (p1 != NULL) break;
}
/* ignore comment lines and any .TH line(s) */
if ((strncmp(buffer2,".\\\"",3)==0) || (strncmp(buffer2,".TH",3)==0))
continue;
/* check the various versions of "NAME" */
if (strstr(buffer2,NAME1) != NULL) break;
if (strstr(buffer2,NAME2) != NULL) break;
if (strstr(buffer2,NAME3) != NULL) break;
}
/* we need the previous newline for the next algorithm to work */
fseek(fp,-1L,SEEK_CUR);
/*
* 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.
*
* Also copy selected chars to titlebuf until the first '-' is found.
*/
for(;;) {
p2 = strchr(p1,'-');
if (p2 != NULL) {
p2++;
break;
}
p3 = titlebuf;
found = 0; /* set this when we find '-' */
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 */
foo = 0; /* haven't found the printable character after NAME */
for(;;) {
/* read another block into buffer2. */
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;
/* eof or error; empty buffer and titlebuf then return */
buffer[0] = '\0';
titlebuf[0] = '\0';
fclose(fp);
if (v_flag) fprintf (error_fp,
"EOF or error on %s, command name not found.\n",filename);
return;
}
buffer2[count] = '\0';
p1 = buffer2;
}
p1 = p2;
p1 = buffer2;
/* mark the "end" of buffer2 with p2 */
if ((p2 = strchr(p1,'-')) != 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 key words, p2
* to either the end of the key words or the end of buffer2,
* and p3 into the spot in titlebuf where the next character should
* be put.
*
* Copy *p1 to *p3 while p1<p2 (not at end of titlebuf or key words),
* 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;
continue;
}
/* skip .BR-type formatting */
if ((p1<p2) && (*p1=='\r') && (*(p1+1)=='.')) {
p1++;
while ((p1<p2) && !isspace(*p1)) p1++;
if (p1==p2) in_format_BR = 1;
else --p1;
continue;
}
/* 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;
}
continue;
}
/*
* skip whitespace if we haven't got the beginning of the
* description yet.
*/
#ifdef ISGRAPH_FIX
if (isgraph(*p1) && (*p1!=' ')) foo=1;
if (!foo) {
while ((p1<p2) && !(isgraph(*p1) && (*p1!=' '))) p1++;
if ((*p1=='.') && (*(p1-1)=='\r')) p1 -=2;
else --p1;
continue;
}
#else
if (isgraph(*p1)) foo=1;
if (!foo) {
while ((p1<p2) && !isgraph(*p1)) p1++;
if ((*p1=='.') && (*(p1-1)=='\r')) p1 -=2;
else --p1;
continue;
}
#endif
/*
* at this point, *p1 is either a control char or something that
* we want in titlebuf, assuming that p1<p2.
*/
if ((p1<p2) && !iscntrl(*p1)) {
/*
* The conditional below means:
* Copy it so that: 1. There is only one space between words; and
* 2. The buffer doesn't begin with a space.
*/
if ( !((p3>titlebuf) && (*p1 == ' ') && (*(p3-1) == ' ')) &&
!((p3==titlebuf) && (*p3 == ' '))
) {
/* don't let a space precede a comma */
if ((*p1==',') && (*(p3-1)==' ')) {
*(p3-1) = ',';
continue;
} else *p3++ = *p1;
if (p3>=p5) { /* titlebuf overflow? */
if (v_flag)
fprintf(error_fp,"command name buffer overflow on %s\n",
filename);
buffer[0] = '\0';
titlebuf[0] = '\0';
fclose(fp);
return;
}
}
}
}
if (found) { /* we've got all of the key words */
p3--; /* p3 now points to last char, not terminator */
if (*p3=='\\') p3--;
while(isspace(*p3)) p3--;
*(p3+1) = '\0';
break;
}
}
p1 = p2 + 1;
#ifdef ISGRAPH_FIX
while ( (p1 < buffer2 + BUFFERSIZE) &&!(isgraph(*p1) && (*p1 != ' '))) p1++;
#else
while ((p1 < buffer2 + BUFFERSIZE) && !isgraph(*p1)) p1++;
#endif
/*
* now copy selected chars to buffer until the next subheading is found
*/
@ -108,8 +323,12 @@ void fillbuffer (char *filename) {
/* mark the "end" of buffer2 with p2 */
if ( ((p2 = strstr(p1,".SH")) != NULL) ||
((p2 = strstr(p1,"SYNOPSIS")) != NULL) ||
((p2 = strstr(p1,"DESCRIPTION")) != NULL)
((p2 = strstr(p1,SYNOPSIS1)) != NULL) ||
((p2 = strstr(p1,SYNOPSIS2)) != NULL) ||
((p2 = strstr(p1,SYNOPSIS3)) != NULL) ||
((p2 = strstr(p1,DESCRIPTION1)) != NULL) ||
((p2 = strstr(p1,DESCRIPTION2)) != NULL) ||
((p2 = strstr(p1,DESCRIPTION3)) != NULL)
) {
found = 1;
} else {
@ -156,6 +375,7 @@ void fillbuffer (char *filename) {
/* skip .BR-type formatting */
if ((p1<p2) && (*p1=='\r') && (*(p1+1)=='.')) {
p1++;
while ((p1<p2) && !isspace(*p1)) p1++;
if (p1==p2) in_format_BR = 1;
}
@ -175,7 +395,29 @@ void fillbuffer (char *filename) {
* we want in buffer, assuming that p1<p2.
*/
if ((p1<p2) && !iscntrl(*p1)) *p3++ = *p1;
if ((p1<p2) && !iscntrl(*p1)) {
/*
* The conditional below means:
* Copy it so that: 1. There is only one space between words; and
* 2. The buffer doesn't begin with a space.
*/
if ( !((p3>buffer) && (*p1 == ' ') && (*(p3-1) == ' ')) &&
!((p3==buffer) && (*p3 == ' '))
) {
*p3++ = *p1;
if (p3>=p4) { /* buffer overflow? */
if (v_flag)
fprintf(error_fp,"command description buffer overflow on %s\n",
filename);
buffer[0] = '\0';
titlebuf[0] = '\0';
fclose(fp);
return;
}
}
}
}
if (found) { /* we've got the entire description */
@ -191,14 +433,17 @@ void fillbuffer (char *filename) {
count = fread(buffer2,sizeof(char),BUFFERSIZE-1,fp);
if (count == 0) {
/* eof or error; terminate buffer and return */
*p3 = '\0';
fclose(fp);
return;
*p3 = '\0';
fclose(fp);
if (v_flag) fprintf (error_fp,
"EOF or error on %s, description not found.\n",filename);
return;
}
buffer2[count] = '\0';
p1 = buffer2;
}
/*
* close the file
*/
@ -214,18 +459,28 @@ void fillbuffer (char *filename) {
int main(int argc, char **argv) {
if (argc != 2) {
printf("Usage: %s <man_page_file_name>\n\n",argv[0]);
fprintf(stderr,"Usage: %s <man_page_file_name>\n\n",argv[0]);
return -1;
}
fillbuffer(argv[1]);
if (strlen(titlebuf) == 0) {
printf("title buffer empty\n");
} else {
printf("main: title buffer is %lu chars long\n%s\n",
strlen(titlebuf),titlebuf);
}
if (strlen(buffer) == 0) {
printf("buffer empty\n");
} else {
printf("main: buffer is %u chars long\n%s\n",strlen(buffer),buffer);
printf("main: buffer is %lu chars long\n%s\n",strlen(buffer),buffer);
}
return 0;
}

View File

@ -13,12 +13,19 @@ MANDIR = /usr/man
#
# Nothing past this point should have to be changed
#
# -DISGRAPH_FIX should come out when Orca/C's isgraph() function is fixed.
#
# -DTEST_PROCESS is for debugging process(). Use "dmake process".
# -DDEBUG will give stack usage.
#
CFLAGS = -w -O -v -DISGRAPH_FIX -s1024
CFLAGS = -w -O -v
OBJS = makewhatis.o fillbuffer.o process.o
LDLIBS = -l/usr/lib/gnulib -l/usr/lib/stack
makewhatis: $(OBJS)
$(CC) $(OBJS) -o makewhatis
$(CC) $(OBJS) $(LDLIBS) -o makewhatis
makewhatis.o: makewhatis.c makewhatis.h
$(CC) -c $(CFLAGS) makewhatis.c

View File

@ -1,4 +1,4 @@
.TH MAKEWHATIS 1 "Commands and Applications" "15 May 1994" "Version 1.0"
.TH MAKEWHATIS 1 "Commands and Applications" "29 May 1994" "Version 1.1"
.SH NAME
.B makewhatis
\- generate the whatis database file
@ -9,13 +9,17 @@
|
.I -C
] [
.I -ovV
] [
.I "-f outfile"
] [
.I "-l logfile"
] [
.I "-o dbfile"
] [
.I "-p path"
] [
.I "-v n"
] [
.I "-V"
]
.SH DESCRIPTION
.B makewhatis
@ -82,17 +86,31 @@ man/catX sub-directories, not man/manX sub-directories.
.I "-f outfile"
causes the
.B makewhatis
status output to be placed in \fIoutfile\fR.
status output to be placed in \fIoutfile\fR. Invoking
.I "-f"
without
.I "-v2"
produces no output.
.LP
.I "-l logfile"
will cause any error messages to be printed to \fIlogfile\fR.
will cause any error messages to be printed to \fIlogfile\fR. Invoking
.I "-l"
without either
.I "-v1"
or
.I "-v2"
produces no output.
.LP
.I "-o dbfile"
will make
.B makewhatis
use
.I dbfile
as the name for the generated whatis databases.
as the name for the generated whatis databases. While it is possible to
use a full pathname for
.I dbfile
, this will result in that file being overwritten for each space-delimited
entry in \fIMANPATH\fR.
.LP
.I "-p path"
overrides the environment variables
@ -100,8 +118,10 @@ overrides the environment variables
et al for determining for which manual page hierarchies the databases must
be generated.
.LP
.I -v
creates verbose status messages during execution.
.I "-v n"
creates verbose status messages during execution. For n=1 only error
messages are printed out. For n=2, both error and status messages are
printed.
.LP
.I -V
will show version and usage information, then exit.
@ -121,6 +141,14 @@ and
.I .
being part of these paths, it will not correctly handle \fI..\fR.
.SH CAVEATS
.B Makewhatis
assumes that the programs
.BR aroff ,
.BR compress ", and"
.BR freeze
are available to the executing shell via the \fIsystem\fR(2) call.
Nroff is not used and need not be available.
.LP
Because
.B makewhatis
looks for the string
@ -130,12 +158,13 @@ and one of \fI.SH\fR, \fISYNOPSIS\fR, or
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.
is underlined by repeated backspace-_ sequences, then the generated
description for that particular man page is unpredictable,
though usually blank. When parsing man pages,
.B makewhatis
will understand the common double- and quadruple-boldfaced
subheadings, provided
that the backspace character (control-H) is used to achieve this effect.
.LP
Similarily,
.B makewhatis
@ -148,34 +177,29 @@ to be in the format:
.fi
If this is not so (ignoring whitespace), then the output is unpredictable.
.LP
Man pages must be CR-deliminated.
.LP
If aroff source is compressed or frozen, the database entry for that
page 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.
.LP
Any text appearing after
.I NAME
on the NAME header line will be ignored.
.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
.B Makewhatis
reads files in blocks of 1024 characters.
If formatting information is split by the end
of the input buffer, you may see formatting infomation such as
.I .BR
in the output. This was not fixed due to the overhead of having to
check for such a condition.
.SH FILES
.nf
/usr/sbin/makewhatis -- whatis database generator
@ -183,8 +207,12 @@ man/whatis -- the whatis database
.fi
.SH SEE ALSO
.BR apropos (1),
.BR aroff (1),
.BR catman (1),
.BR compress (1),
.BR freeze (1),
.BR man (1),
.BR whatis (1),
.BR nroff (1),
.BR whatis (1)
.SH AUTHOR
Written by Devin Reade <glyn@cs.ualberta.ca> for the Apple IIgs and Gno.

View File

@ -9,10 +9,16 @@
#include <string.h>
#include <dirent.h>
#include <unistd.h>
#include "getopt.h"
#include <libc.h>
#include "makewhatis.h"
#ifdef DEBUG
extern void begin_stack_check(void);
extern int end_stack_check(void);
#endif
/*
* Options:
*
@ -23,7 +29,7 @@
* -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{1|2} verbose
* -V show version and usage info and exit
*/
@ -41,18 +47,6 @@ char *man_subdir[] = {
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.
@ -72,6 +66,18 @@ char *cat_subdir[] = {
NULL /* _must_ be NULL terminated! */
};
/* 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 */
FILE *output_fp;
FILE *error_fp;
@ -98,6 +104,10 @@ int main (int argc, char **argv) {
return 1;
}
#ifdef DEBUG
begin_stack_check();
#endif
/*
* set the defaults
*/
@ -113,7 +123,7 @@ int main (int argc, char **argv) {
* parse the command line
*/
while((i = getopt(argc,argv,"cCf:l:o:p:vV")) != EOF)
while((i = getopt(argc,argv,"cCf:l:o:p:v:V")) != EOF)
switch(i) {
case 'c':
if (C_flag) errflag++;
@ -148,11 +158,12 @@ int main (int argc, char **argv) {
p = optarg;
break;
case 'v':
v_flag++;
v_flag = (short) atoi(optarg);
if ((v_flag!=1) && (v_flag!=2)) errflag++;
break;
case 'V':
fprintf(stderr,
"%s -- Create the %s database.\n\tVersion %s by Devin Reade\n\n",
"%s --\n\tCreate the %s database.\n\tVersion %s by Devin Reade\n\n",
argv[0],WHATIS,VERSIONSTRING);
errflag++;
break;
@ -162,15 +173,17 @@ int main (int argc, char **argv) {
}
if (errflag) {
fprintf(error_fp,
"Usage: %s [-c|-C] [-ovV] [-f outfile] [-l logfile] [-p path]\n\n\
"Usage:\n%s\t[-c|-C] [-f outfile] [-l logfile] [-o dbfile] [-p path]\n\
\t\t[-v 1|2] [-V]\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);
-v n\t\t<n>=1: Verbose, only displaying major errors.\n\
\t\t<n>=2: Very verbose, displaying processing information.\n\
-V\t\tShow version and usage information, then exit.\n",argv[0]);
return -1;
}
@ -192,7 +205,8 @@ environment variables\n$MANPATH, $USRMAN, or $MANDIR, or use the -p flag.\n\n");
/* 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);
if (v_flag) fprintf(error_fp,
"malloc failed while making copy of \"%s\"\nAborted.\n",p);
return -1;
}
strcpy(manpath,p);
@ -221,7 +235,8 @@ environment variables\n$MANPATH, $USRMAN, or $MANDIR, or use the -p flag.\n\n");
whatis_fp = fopen(dbfile,"w");
if (whatis_fp == NULL) {
fprintf (error_fp,
"Could not create whatis database file %s in directory %s.\n",
"Could not create whatis database file %s in directory %s.\n\
Aborted.\n",
dbfile,path);
exit(-1);
}
@ -235,7 +250,7 @@ environment variables\n$MANPATH, $USRMAN, or $MANDIR, or use the -p flag.\n\n");
if (subdir != NULL) {
/* print status */
if (v_flag) fprintf(output_fp,
if (v_flag>=2) fprintf(output_fp,
"Now working on directory %s\t%s ...\n",path,man_subdir[i]);
/* no need to error check because of opendir() */
@ -247,7 +262,7 @@ environment variables\n$MANPATH, $USRMAN, or $MANDIR, or use the -p flag.\n\n");
}
closedir(subdir);
} else {
if (v_flag) fprintf(output_fp,
if (v_flag>=2) fprintf(output_fp,
"Could not access files in %s\t%s ...\n",path,man_subdir[i]);
}
chdir(path);
@ -263,7 +278,7 @@ environment variables\n$MANPATH, $USRMAN, or $MANDIR, or use the -p flag.\n\n");
if (subdir != NULL) {
/* print status */
if (v_flag) fprintf(output_fp,
if (v_flag>=2) fprintf(output_fp,
"Now working on directory %s\t%s ...\n",path,cat_subdir[i]);
/* no need to error check because of opendir() */
@ -284,7 +299,7 @@ environment variables\n$MANPATH, $USRMAN, or $MANDIR, or use the -p flag.\n\n");
}
closedir(subdir);
} else {
if (v_flag) fprintf(output_fp,
if (v_flag>=2) fprintf(output_fp,
"Could not access files in %s\t%s ...\n",path,cat_subdir[i]);
}
chdir(path);
@ -303,5 +318,10 @@ environment variables\n$MANPATH, $USRMAN, or $MANDIR, or use the -p flag.\n\n");
unlink(tmp_file);
if (output_fp != stdout) fclose(output_fp);
if (error_fp != stderr) fclose(error_fp);
#ifdef DEBUG
fprintf(stderr,"Makewhatis stack usage: %d bytes\n",end_stack_check());
#endif
return 0;
}

View File

@ -1,4 +1,4 @@
#define VERSIONSTRING "1.0"
#define VERSIONSTRING "1.1, 29 May 1994"
/* The size of the IO buffers */
#define BUFFERSIZE 1024
@ -15,11 +15,4 @@ 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;

View File

@ -12,14 +12,23 @@
#include "makewhatis.h"
/* These are the compression types */
#define NO_COMPRESS 0
#define Z_COMPRESS 1
#define F_COMPRESS 2
#ifdef TEST_PROCESS
short v_flag = 1;
short v_flag = 1;
FILE *output_fp;
FILE *error_fp;
#else
extern FILE *output_fp;
extern FILE *error_fp;
#endif
extern GSString255Ptr __C2GSMALLOC (char *s);
extern char buffer[];
extern FILE *output_fp;
extern FILE *error_fp;
extern char titlebuf[];
/*
* void process (char *filename, char *tmp_file, FILE *whatis_fp);
@ -40,12 +49,12 @@ void process (char *filename, char *tmp_file, FILE *whatis_fp) {
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 */
short compression; /* the compression type (if nec) */
if (v_flag) fprintf(output_fp,"Working on file %s ...\n",filename);
if (v_flag>=2) fprintf(output_fp,"Working on file %s ...\n",filename);
/*
* get the file basename and suffix
* get the file basename
*/
if ((name = malloc (strlen(filename)+1)) == NULL) {
@ -55,28 +64,58 @@ void process (char *filename, char *tmp_file, FILE *whatis_fp) {
return;
}
strcpy(name,filename);
if ((suffix = strchr(name,'.')) == NULL) {
/*
* check for a compression suffix like ".Z" or ".F"
*/
p1 = name + strlen(name) -1; /* p1 points to last char of name */
while ((p1>=name) && (*p1!='.')) --p1;
if (p1<=name) { /* <= because we don't want a name beginning with '.' */
if (v_flag)
fprintf(error_fp,"%s has no suffix -- file skipped\n",
filename);
return;
}
*suffix = '\0';
suffix++;
sufflen = strlen(suffix);
if ((strcmp(p1,".Z")==0) || (strcmp(p1,".z")==0)) {
compression = Z_COMPRESS;
} else if ((strcmp(p1,".F")==0) || (strcmp(p1,".f")==0)) {
compression = F_COMPRESS;
} else compression = NO_COMPRESS;
*p1 = '\0';
/*
* define the suffix
*/
if (compression == NO_COMPRESS) {
suffix = p1 + 1;
} else {
while ((p1>=name) && (*p1!='.')) --p1;
if (p1<=name) { /* <= because we don't want a name beginning with '.' */
if (v_flag)
fprintf(error_fp,"%s has deformed file name -- file skipped\n",
filename);
return;
}
*p1 = '\0';
suffix = p1 + 1;
}
/*
* 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;
if (compression == NO_COMPRESS) {
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;
}
}
/*
@ -84,37 +123,30 @@ void process (char *filename, char *tmp_file, FILE *whatis_fp) {
* The digested result is placed in buffer.
*/
if ((info_record.fileType == 0x50u) && (info_record.auxType == 0x8010u)) {
if ((compression == NO_COMPRESS) &&
(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)=='.')) {
} else if (compression == Z_COMPRESS) {
/* 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)=='.')) {
} else if (compression == F_COMPRESS) {
/* 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. */
@ -126,6 +158,13 @@ void process (char *filename, char *tmp_file, FILE *whatis_fp) {
fillbuffer(filename);
}
/*
* If there was an error, or it is an .so reference to another man
* page, then return without writing anything to the database
*/
if ((buffer[0] == '\0') || (titlebuf[0] == '\0')) return;
/*
* 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
@ -134,27 +173,31 @@ void process (char *filename, char *tmp_file, FILE *whatis_fp) {
p1 = buffer;
while (isspace(*p1)) p1++;
namelength = strlen(name) + strlen(suffix) + 4;
namelength = strlen(titlebuf) + strlen(suffix) + 4;
if (namelength > (TABLENGTH * 3)) {
fprintf(whatis_fp,"%s (%s) - %s\n", name, suffix, p1);
fprintf(whatis_fp,"%s (%s) - %s\n", titlebuf, suffix, p1);
} else if (namelength > (TABLENGTH * 2)) {
fprintf(whatis_fp,"%s (%s)\t- %s\n", name, suffix, p1);
fprintf(whatis_fp,"%s (%s)\t- %s\n", titlebuf, suffix, p1);
} else if (namelength > TABLENGTH ) {
fprintf(whatis_fp,"%s (%s)\t\t- %s\n", name, suffix, p1);
fprintf(whatis_fp,"%s (%s)\t\t- %s\n", titlebuf, suffix, p1);
} else {
fprintf(whatis_fp,"%s (%s)\t\t\t- %s\n", name, suffix, p1);
fprintf(whatis_fp,"%s (%s)\t\t\t- %s\n", titlebuf, suffix, p1);
}
return;
}
#ifdef TEST_PROCESS
int main (int argc, char **argv) {
output_fp = stdout;
error_fp = stderr;
if (argc != 2) {
printf("Usage: %s <man_page_file_name>\n",argv[0]);
fprintf(stderr,"Usage: %s <man_page_file_name>\n",argv[0]);
return -1;
}