1 /* $NetBSD: soelim.c,v 1.15 2016/09/05 00:40:29 sevan Exp $ */ 2 3 /* 4 * Copyright (c) 1980, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 #ifndef lint 34 __COPYRIGHT("@(#) Copyright (c) 1980, 1993\ 35 The Regents of the University of California. All rights reserved."); 36 #endif /* not lint */ 37 38 #ifndef lint 39 #if 0 40 static char sccsid[] = "@(#)soelim.c 8.1 (Berkeley) 6/6/93"; 41 #endif 42 __RCSID("$NetBSD: soelim.c,v 1.15 2016/09/05 00:40:29 sevan Exp $"); 43 #endif /* not lint */ 44 45 /* 46 * soelim - a filter to process n/troff input eliminating .so's 47 * 48 * Author: Bill Joy UCB July 8, 1977 49 * 50 * This program eliminates .so's from a n/troff input stream. 51 * It can be used to prepare safe input for submission to the 52 * phototypesetter since the software supporting the operator 53 * doesn't let him do chdir. 54 * 55 * This is a kludge and the operator should be given the 56 * ability to do chdir. 57 * 58 * This program is more generally useful, it turns out, because 59 * the program tbl doesn't understand ".so" directives. 60 */ 61 #include <sys/param.h> 62 #include <err.h> 63 #include <stdio.h> 64 #include <stdlib.h> 65 #include <string.h> 66 #include <unistd.h> 67 68 #define STDIN_NAME "-" 69 70 struct path { 71 char **list; 72 size_t n, c; 73 }; 74 75 static int process(struct path *, const char *); 76 static void initpath(struct path *); 77 static void addpath(struct path *, const char *); 78 static FILE *openpath(struct path *, const char *, const char *); 79 80 81 static void 82 initpath(struct path *p) 83 { 84 p->list = NULL; 85 p->n = p->c = 0; 86 } 87 88 static void 89 addpath(struct path *p, const char *dir) 90 { 91 char **n; 92 93 if (p->list == NULL || p->n <= p->c - 2) { 94 n = realloc(p->list, (p->n + 10) * sizeof(p->list[0])); 95 if (n == NULL) 96 err(1, NULL); 97 p->list = n; 98 p->n += 10; 99 } 100 101 if ((p->list[p->c++] = strdup(dir)) == NULL) 102 err(1, NULL); 103 104 p->list[p->c] = NULL; 105 } 106 107 static FILE * 108 openpath(struct path *p, const char *name, const char *parm) 109 { 110 char filename[MAXPATHLEN]; 111 const char *f; 112 FILE *fp; 113 size_t i; 114 115 if (*name == '/' || p->c == 0) 116 return fopen(name, parm); 117 118 for (i = 0; i < p->c; i++) { 119 if (p->list[i][0] == '\0') 120 f = name; 121 else { 122 (void)snprintf(filename, sizeof(filename), "%s/%s", 123 p->list[i], name); 124 f = filename; 125 } 126 if ((fp = fopen(f, parm)) != NULL) 127 return fp; 128 } 129 return NULL; 130 } 131 132 int 133 main(int argc, char *argv[]) 134 { 135 struct path p; 136 int c; 137 138 initpath(&p); 139 addpath(&p, "."); 140 141 while ((c = getopt(argc, argv, "I:")) != -1) 142 switch (c) { 143 case 'I': 144 addpath(&p, optarg); 145 break; 146 default: 147 (void)fprintf(stderr, 148 "usage: %s [-I<dir>] [files...]\n", 149 getprogname()); 150 exit(1); 151 } 152 153 argc -= optind; 154 argv += optind; 155 156 if (argc == 0) { 157 (void)process(&p, STDIN_NAME); 158 exit(0); 159 } 160 do { 161 (void)process(&p, argv[0]); 162 argv++; 163 argc--; 164 } while (argc > 0); 165 exit(0); 166 } 167 168 int 169 process(struct path *p, const char *file) 170 { 171 char *cp; 172 int c; 173 char fname[BUFSIZ]; 174 FILE *soee; 175 int isfile; 176 177 if (!strcmp(file, STDIN_NAME)) { 178 soee = stdin; 179 } else { 180 soee = openpath(p, file, "r"); 181 if (soee == NULL) { 182 warn("Cannot open `%s'", file); 183 return(-1); 184 } 185 } 186 for (;;) { 187 c = getc(soee); 188 if (c == EOF) 189 break; 190 if (c != '.') 191 goto simple; 192 c = getc(soee); 193 if (c != 's') { 194 putchar('.'); 195 goto simple; 196 } 197 c = getc(soee); 198 if (c != 'o') { 199 printf(".s"); 200 goto simple; 201 } 202 do 203 c = getc(soee); 204 while (c == ' ' || c == '\t'); 205 cp = fname; 206 isfile = 0; 207 for (;;) { 208 switch (c) { 209 210 case ' ': 211 case '\t': 212 case '\n': 213 case EOF: 214 goto donename; 215 216 default: 217 *cp++ = c; 218 c = getc(soee); 219 isfile++; 220 continue; 221 } 222 } 223 donename: 224 if (cp == fname) { 225 printf(".so"); 226 goto simple; 227 } 228 *cp = 0; 229 if (process(p, fname) < 0) 230 if (isfile) 231 printf(".so %s\n", fname); 232 continue; 233 simple: 234 if (c == EOF) 235 break; 236 putchar(c); 237 if (c != '\n') { 238 c = getc(soee); 239 goto simple; 240 } 241 } 242 if (soee != stdin) { 243 fclose(soee); 244 } 245 return(0); 246 } 247