mirror of
https://github.com/GnoConsortium/gno.git
synced 2024-12-22 14:30:29 +00:00
73ce022151
original makewhatis repository. Earlier versions of man, apropos, and whatis were by other authors (these are written from scratch). Catman is new.
335 lines
9.2 KiB
C
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;
|
|
}
|