gno/usr.bin/man/makewhatis.c
gdr 73ce022151 Version 3.0 of the manpack archive. This moved on top of the
original makewhatis repository.  Earlier versions of man, apropos,
and whatis were by other authors (these are written from scratch).
Catman is new.
1996-01-28 00:41:22 +00:00

335 lines
9.2 KiB
C

/*
* Copyright 1995 by Devin Reade <gdr@myrias.com>. For distribution
* information see the README file that is part of the manpack archive,
* or contact the author, above.
*/
segment "makewhatis";
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <dirent.h>
#include <unistd.h>
#include "getopt.h"
#include <libc.h>
#include "makewhatis.h"
#ifdef STACK_CHECK
extern void begin_stack_check(void);
extern int end_stack_check(void);
#endif
/*
* 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{1|2|3} verbose
* -V show version and usage info and exit
*/
char *man_subdir[] = {
"man1",
"man2",
"man3",
"man3f",
"man4",
"man5",
"man6",
"man7",
"man8",
"mann",
"manl",
"manp",
"mano",
NULL
};
/*
* 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",
"cat3f",
"cat4",
"cat5",
"cat6",
"cat7",
"cat8",
"catn",
"catl",
"catp",
"cato",
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;
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;
}
#ifdef STACK_CHECK
begin_stack_check();
#endif
/*
* 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:v:V")) != 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 = (short) atoi(optarg);
if ((v_flag<1) && (v_flag>3)) errflag++;
break;
case 'V':
fprintf(stderr,
"%s --\n\tCreate 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:\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 n\t\t<n>=1: Slightly verbose, only displaying major errors.\n\
\t\t<n>=2: Verbose, displaying processed file names.\n\
\t\t<n>=3: Very verbose, displaying more processing info.\n\
-V\t\tShow version and usage information, then exit.\n",argv[0]);
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) p = DEFAULT_MANPATH;
/* 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,
"malloc failed while making copy of \"%s\"\nAborted.\n",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\
Aborted.\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>=3) 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,&man_subdir[i][3]);
}
closedir(subdir);
} else {
if (v_flag>=3) 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>=3) 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,
&man_subdir[i][3]);
}
closedir(subdir);
} else {
if (v_flag>=3) 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);
#ifdef STACK_CHECK
fprintf(stderr,"Makewhatis stack usage: %d bytes\n",end_stack_check());
#endif
return 0;
}