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