1 /* $NetBSD: soelim.c,v 1.14 2008/07/21 14:19:26 lukem 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.14 2008/07/21 14:19:26 lukem 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 int main(int, char **); 81 82 83 static void 84 initpath(struct path *p) 85 { 86 p->list = NULL; 87 p->n = p->c = 0; 88 } 89 90 static void 91 addpath(struct path *p, const char *dir) 92 { 93 char **n; 94 95 if (p->list == NULL || p->n <= p->c - 2) { 96 n = realloc(p->list, (p->n + 10) * sizeof(p->list[0])); 97 if (n == NULL) 98 err(1, NULL); 99 p->list = n; 100 p->n += 10; 101 } 102 103 if ((p->list[p->c++] = strdup(dir)) == NULL) 104 err(1, NULL); 105 106 p->list[p->c] = NULL; 107 } 108 109 static FILE * 110 openpath(struct path *p, const char *name, const char *parm) 111 { 112 char filename[MAXPATHLEN]; 113 const char *f; 114 FILE *fp; 115 size_t i; 116 117 if (*name == '/' || p->c == 0) 118 return fopen(name, parm); 119 120 for (i = 0; i < p->c; i++) { 121 if (p->list[i][0] == '\0') 122 f = name; 123 else { 124 (void)snprintf(filename, sizeof(filename), "%s/%s", 125 p->list[i], name); 126 f = filename; 127 } 128 if ((fp = fopen(f, parm)) != NULL) 129 return fp; 130 } 131 return NULL; 132 } 133 134 int 135 main(int argc, char *argv[]) 136 { 137 struct path p; 138 int c; 139 140 initpath(&p); 141 addpath(&p, "."); 142 143 while ((c = getopt(argc, argv, "I:")) != -1) 144 switch (c) { 145 case 'I': 146 addpath(&p, optarg); 147 break; 148 default: 149 (void)fprintf(stderr, 150 "usage: %s [-I<dir>] [files...]\n", 151 getprogname()); 152 exit(1); 153 } 154 155 argc -= optind; 156 argv += optind; 157 158 if (argc == 0) { 159 (void)process(&p, STDIN_NAME); 160 exit(0); 161 } 162 do { 163 (void)process(&p, argv[0]); 164 argv++; 165 argc--; 166 } while (argc > 0); 167 exit(0); 168 } 169 170 int 171 process(struct path *p, const char *file) 172 { 173 char *cp; 174 int c; 175 char fname[BUFSIZ]; 176 FILE *soee; 177 int isfile; 178 179 if (!strcmp(file, STDIN_NAME)) { 180 soee = stdin; 181 } else { 182 soee = openpath(p, file, "r"); 183 if (soee == NULL) { 184 warn("Cannot open `%s'", file); 185 return(-1); 186 } 187 } 188 for (;;) { 189 c = getc(soee); 190 if (c == EOF) 191 break; 192 if (c != '.') 193 goto simple; 194 c = getc(soee); 195 if (c != 's') { 196 putchar('.'); 197 goto simple; 198 } 199 c = getc(soee); 200 if (c != 'o') { 201 printf(".s"); 202 goto simple; 203 } 204 do 205 c = getc(soee); 206 while (c == ' ' || c == '\t'); 207 cp = fname; 208 isfile = 0; 209 for (;;) { 210 switch (c) { 211 212 case ' ': 213 case '\t': 214 case '\n': 215 case EOF: 216 goto donename; 217 218 default: 219 *cp++ = c; 220 c = getc(soee); 221 isfile++; 222 continue; 223 } 224 } 225 donename: 226 if (cp == fname) { 227 printf(".so"); 228 goto simple; 229 } 230 *cp = 0; 231 if (process(p, fname) < 0) 232 if (isfile) 233 printf(".so %s\n", fname); 234 continue; 235 simple: 236 if (c == EOF) 237 break; 238 putchar(c); 239 if (c != '\n') { 240 c = getc(soee); 241 goto simple; 242 } 243 } 244 if (soee != stdin) { 245 fclose(soee); 246 } 247 return(0); 248 } 249