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("$NetBSD: catman.c,v 1.9 1997/10/24 01:31:35 mrg 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 snprintf(mandir, sizeof mandir, "%s/%s%.*s", path, 158 _PATH_MANPAGES, sectlen, s); 159 snprintf(catdir, sizeof catdir, "%s/%s%.*s", path, 160 _PATH_CATPAGES, sectlen, s); 161 162 if ((dirp = opendir(mandir)) == 0) { 163 warn("can't open %s", mandir); 164 continue; 165 } 166 167 if (stat(catdir, &catstat) < 0) { 168 if (errno != ENOENT) { 169 warn("can't stat %s", catdir); 170 closedir(dirp); 171 continue; 172 } 173 if (f_noprint == 0) 174 printf("mkdir %s\n", catdir); 175 if (f_noaction == 0 && mkdir(catdir, 0755) < 0) { 176 warn("can't create %s", catdir); 177 closedir(dirp); 178 return; 179 } 180 181 } 182 183 while ((dp = readdir(dirp)) != NULL) { 184 if (strcmp(dp->d_name, ".") == 0 || 185 strcmp(dp->d_name, "..") == 0) 186 continue; 187 188 sprintf(manpage, "%s/%s", mandir, dp->d_name); 189 sprintf(catpage, "%s/%s", catdir, dp->d_name); 190 if ((tmp = strrchr(catpage, '.')) != NULL) 191 strcpy(tmp, ".0"); 192 else 193 continue; 194 195 if (stat(manpage, &manstat) < 0) { 196 warn("can't stat %s", manpage); 197 continue; 198 } 199 200 if (!S_ISREG(manstat.st_mode)) { 201 warnx("not a regular file %s", manpage); 202 continue; 203 } 204 if ((error = stat(catpage, &catstat)) && 205 errno != ENOENT) { 206 warn("can't stat %s", catpage); 207 continue; 208 } 209 210 if ((error && errno == ENOENT) || 211 manstat.st_mtime >= catstat.st_mtime) { 212 if (f_noformat) 213 dowhatis = 1; 214 else { 215 /* 216 * manpage is out of date, 217 * reformat 218 */ 219 sprintf(sysbuf, "nroff -mandoc %s > %s", 220 manpage, catpage); 221 if (f_noprint == 0) 222 printf("%s\n", sysbuf); 223 if (f_noaction == 0) 224 dosystem(sysbuf); 225 dowhatis = 1; 226 } 227 } 228 } 229 closedir(dirp); 230 } 231 } 232 233 void 234 makewhatis(path) 235 const char *path; 236 { 237 char sysbuf[1024]; 238 239 sprintf(sysbuf, "%s %s", _PATH_MAKEWHATIS, path); 240 if (f_noprint == 0) 241 printf("%s\n", sysbuf); 242 if (f_noaction == 0) 243 dosystem(sysbuf); 244 } 245 246 void 247 dosystem(cmd) 248 const char *cmd; 249 { 250 int status; 251 252 if ((status = system(cmd)) == 0) 253 return; 254 255 if (status == -1) 256 err(1, "cannot execute action"); 257 if (WIFSIGNALED(status)) 258 errx(1, "child was signaled to quit. aborting"); 259 if (WIFSTOPPED(status)) 260 errx(1, "child was stopped. aborting"); 261 if (f_ignerr == 0) 262 errx(1, "*** Exited %d", status); 263 warnx("*** Exited %d (continuing)", status); 264 } 265 266 void 267 usage() 268 { 269 (void)fprintf(stderr, 270 "usage: catman [-knpsw] [-M manpath] [sections]\n"); 271 exit(1); 272 } 273