From 8ae768d07301ffddb91b5a43166208df0a3c828a Mon Sep 17 00:00:00 2001 From: gdr Date: Sun, 28 Jan 1996 00:33:14 +0000 Subject: [PATCH] makewhatis version 1.1 (later to become part of the manpack archive) --- usr.bin/man/README | 67 +++++++- usr.bin/man/fillbuffer.c | 329 ++++++++++++++++++++++++++++++++++----- usr.bin/man/makefile.mk | 11 +- usr.bin/man/makewhatis.8 | 100 +++++++----- usr.bin/man/makewhatis.c | 70 ++++++--- usr.bin/man/makewhatis.h | 9 +- usr.bin/man/process.c | 117 +++++++++----- 7 files changed, 553 insertions(+), 150 deletions(-) diff --git a/usr.bin/man/README b/usr.bin/man/README index de67a90..7fce5c8 100644 --- a/usr.bin/man/README +++ b/usr.bin/man/README @@ -1,14 +1,71 @@ -------------------------------------------- Name: makewhatis -Version: 1.0 +Version: 1.1 Author: Devin Reade 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. diff --git a/usr.bin/man/fillbuffer.c b/usr.bin/man/fillbuffer.c index c9fdbd6..72392ce 100644 --- a/usr.bin/man/fillbuffer.c +++ b/usr.bin/man/fillbuffer.c @@ -7,8 +7,28 @@ #include #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: 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. + * 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, 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((p1titlebuf) && (*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 ((p1buffer) && (*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 \n\n",argv[0]); + fprintf(stderr,"Usage: %s \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; } diff --git a/usr.bin/man/makefile.mk b/usr.bin/man/makefile.mk index 6f75da5..223e857 100644 --- a/usr.bin/man/makefile.mk +++ b/usr.bin/man/makefile.mk @@ -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 diff --git a/usr.bin/man/makewhatis.8 b/usr.bin/man/makewhatis.8 index 3b932e9..50d34e3 100644 --- a/usr.bin/man/makewhatis.8 +++ b/usr.bin/man/makewhatis.8 @@ -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 for the Apple IIgs and Gno. diff --git a/usr.bin/man/makewhatis.c b/usr.bin/man/makewhatis.c index 7ea6cac..4033d86 100644 --- a/usr.bin/man/makewhatis.c +++ b/usr.bin/man/makewhatis.c @@ -9,10 +9,16 @@ #include #include #include +#include "getopt.h" #include #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 * -p path use the 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 .\n\ -l logfile\tLog errors to .\n\ -o dbfile\tforce whatis database output to .\n\ -p path\t\tUse the 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=1: Verbose, only displaying major errors.\n\ +\t\t=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; } diff --git a/usr.bin/man/makewhatis.h b/usr.bin/man/makewhatis.h index 23af980..e44c7e5 100644 --- a/usr.bin/man/makewhatis.h +++ b/usr.bin/man/makewhatis.h @@ -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; diff --git a/usr.bin/man/process.c b/usr.bin/man/process.c index 63034d2..151e9e6 100644 --- a/usr.bin/man/process.c +++ b/usr.bin/man/process.c @@ -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 \n",argv[0]); + fprintf(stderr,"Usage: %s \n",argv[0]); return -1; }