Home | History | Annotate | Line # | Download | only in catman
catman.c revision 1.7
      1 /*
      2  * Copyright (c) 1993 Winning Strategies, Inc.
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  * 1. Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  * 2. Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in the
     12  *    documentation and/or other materials provided with the distribution.
     13  * 3. All advertising materials mentioning features or use of this software
     14  *    must display the following acknowledgement:
     15  *      This product includes software developed by Winning Strategies, Inc.
     16  * 4. The name of the author may not be used to endorse or promote products
     17  *    derived from this software without specific prior written permission
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #include <sys/cdefs.h>
     32 #ifndef lint
     33 __RCSID("$Id: catman.c,v 1.7 1997/10/18 04:11:02 lukem Exp $");
     34 #endif /* not lint */
     35 
     36 #include <sys/types.h>
     37 #include <sys/stat.h>
     38 #include <sys/wait.h>
     39 #include <dirent.h>
     40 #include <err.h>
     41 #include <errno.h>
     42 #include <limits.h>
     43 #include <stdio.h>
     44 #include <stdlib.h>
     45 #include <string.h>
     46 #include <unistd.h>
     47 #include <paths.h>
     48 
     49 #include "pathnames.h"
     50 
     51 int f_nowhatis;
     52 int f_noaction;
     53 int f_noformat;
     54 int f_ignerr;
     55 int f_noprint;
     56 
     57 int dowhatis;
     58 
     59 char *mp = _PATH_MAN;
     60 char *sp = _MAN_SECTIONS;
     61 
     62 void	catman __P((const char *, char *));
     63 int	main __P((int, char **));
     64 void	makewhatis __P((const char *));
     65 void	dosystem __P((const char *));
     66 void	usage __P((void));
     67 
     68 int
     69 main(argc, argv)
     70 	int argc;
     71 	char **argv;
     72 {
     73 	int c;
     74 
     75 	while ((c = getopt(argc, argv, "knpswM:")) != -1) {
     76 		switch (c) {
     77 		case 'k':
     78 			f_ignerr = 1;
     79 			break;
     80 		case 'n':
     81 			f_nowhatis = 1;
     82 			break;
     83 		case 'p':
     84 			f_noaction = 1;
     85 			break;
     86 		case 's':
     87 			f_noprint = 1;
     88 			break;
     89 		case 'w':
     90 			f_noformat = 1;
     91 			break;
     92 		case 'M':
     93 			mp = optarg;
     94 			break;
     95 
     96 		case '?':
     97 		default:
     98 			usage();
     99 		}
    100 	}
    101 
    102 	argc -= optind;
    103 	argv += optind;
    104 
    105 	if (f_noprint && f_noaction)
    106 		f_noprint = 0;
    107 
    108 	if (argc > 1)
    109 		usage();
    110 	if (argc == 1)
    111 		sp = *argv;
    112 
    113 	if (f_noformat == 0 || f_nowhatis == 0)
    114 		catman(mp, sp);
    115 	if (f_nowhatis == 0 && dowhatis)
    116 		makewhatis(mp);
    117 
    118 	exit(0);
    119 }
    120 
    121 
    122 void
    123 catman(path, section)
    124 	const char *path;
    125 	char *section;
    126 {
    127 	char mandir[PATH_MAX];
    128 	char catdir[PATH_MAX];
    129 	char manpage[PATH_MAX];
    130 	char catpage[PATH_MAX];
    131 	char sysbuf[1024];
    132 	struct stat manstat;
    133 	struct stat catstat;
    134 	struct dirent *dp;
    135 	DIR *dirp;
    136 	char *s, *tmp;
    137 	int sectlen, error;
    138 
    139 	for (s = section; *s; s += sectlen) {
    140 #ifdef notdef
    141 		tmp = s;
    142 		sectlen = 0;
    143 		if (isdigit(*tmp)) {
    144 			sectlen++;
    145 			tmp++;
    146 			while (*tmp && isdigit(*tmp) == 0) {
    147 				sectlen++;
    148 				tmp++;
    149 			}
    150 		}
    151 #else
    152 		sectlen = 1;
    153 #endif
    154 		if (sectlen == 0)
    155 			errx(1, "malformed section string");
    156 
    157 		sprintf(mandir, "%s/%s%.*s", path, _PATH_MANPAGES, sectlen, s);
    158 		sprintf(catdir, "%s/%s%.*s", path, _PATH_CATPAGES, sectlen, s);
    159 
    160 		if ((dirp = opendir(mandir)) == 0) {
    161 			warn("can't open %s", mandir);
    162 			continue;
    163 		}
    164 
    165 		if (stat(catdir, &catstat) < 0) {
    166 			if (errno != ENOENT) {
    167 				warn("can't stat %s", catdir);
    168 				closedir(dirp);
    169 				continue;
    170 			}
    171 			if (f_noprint == 0)
    172 				printf("mkdir %s\n", catdir);
    173 			if (f_noaction == 0 && mkdir(catdir, 0755) < 0) {
    174 				warn("can't create %s", catdir);
    175 				closedir(dirp);
    176 				return;
    177 			}
    178 
    179 		}
    180 
    181 		while ((dp = readdir(dirp)) != NULL) {
    182 			if (strcmp(dp->d_name, ".") == 0 ||
    183 			    strcmp(dp->d_name, "..") == 0)
    184 				continue;
    185 
    186 			sprintf(manpage, "%s/%s", mandir, dp->d_name);
    187 			sprintf(catpage, "%s/%s", catdir, dp->d_name);
    188 			if ((tmp = strrchr(catpage, '.')) != NULL)
    189 				strcpy(tmp, ".0");
    190 			else
    191 				continue;
    192 
    193 			if (stat(manpage, &manstat) < 0) {
    194 				warn("can't stat %s", manpage);
    195 				continue;
    196 			}
    197 
    198 			if (!S_ISREG(manstat.st_mode)) {
    199 				warnx("not a regular file %s", manpage);
    200 				continue;
    201 			}
    202 			if ((error = stat(catpage, &catstat)) &&
    203 			    errno != ENOENT) {
    204 				warn("can't stat %s", catpage);
    205 				continue;
    206 			}
    207 
    208 			if ((error && errno == ENOENT) ||
    209 			    manstat.st_mtime >= catstat.st_mtime) {
    210 				if (f_noformat)
    211 					dowhatis = 1;
    212 				else {
    213 					/*
    214 					 * manpage is out of date,
    215 					 * reformat
    216 					 */
    217 					sprintf(sysbuf, "nroff -mandoc %s > %s",
    218 					    manpage, catpage);
    219 					if (f_noprint == 0)
    220 						printf("%s\n", sysbuf);
    221 					if (f_noaction == 0)
    222 						dosystem(sysbuf);
    223 					dowhatis = 1;
    224 				}
    225 			}
    226 		}
    227 		closedir(dirp);
    228 	}
    229 }
    230 
    231 void
    232 makewhatis(path)
    233 	const char *path;
    234 {
    235 	char sysbuf[1024];
    236 
    237 	sprintf(sysbuf, "%s %s", _PATH_MAKEWHATIS, path);
    238 	if (f_noprint == 0)
    239 		printf("%s\n", sysbuf);
    240 	if (f_noaction == 0)
    241 		dosystem(sysbuf);
    242 }
    243 
    244 void
    245 dosystem(cmd)
    246 	const char *cmd;
    247 {
    248 	int status;
    249 
    250 	if ((status = system(cmd)) == 0)
    251 		return;
    252 
    253 	if (status == -1)
    254 		err(1, "cannot execute action");
    255 	if (WIFSIGNALED(status))
    256 		errx(1, "child was signaled to quit. aborting");
    257 	if (WIFSTOPPED(status))
    258 		errx(1, "child was stopped. aborting");
    259 	if (f_ignerr == 0)
    260 		errx(1, "*** Exited %d", status);
    261 	warnx("*** Exited %d (continuing)", status);
    262 }
    263 
    264 void
    265 usage()
    266 {
    267 	(void)fprintf(stderr,
    268 	    "usage: catman [-knpsw] [-M manpath] [sections]\n");
    269 	exit(1);
    270 }
    271