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