1*39bbc68aSsevan /* $NetBSD: soelim.c,v 1.15 2016/09/05 00:40:29 sevan Exp $ */
25233fb40Sjtc
361f28255Scgd /*
45233fb40Sjtc * Copyright (c) 1980, 1993
55233fb40Sjtc * The Regents of the University of California. All rights reserved.
661f28255Scgd *
761f28255Scgd * Redistribution and use in source and binary forms, with or without
861f28255Scgd * modification, are permitted provided that the following conditions
961f28255Scgd * are met:
1061f28255Scgd * 1. Redistributions of source code must retain the above copyright
1161f28255Scgd * notice, this list of conditions and the following disclaimer.
1261f28255Scgd * 2. Redistributions in binary form must reproduce the above copyright
1361f28255Scgd * notice, this list of conditions and the following disclaimer in the
1461f28255Scgd * documentation and/or other materials provided with the distribution.
1589aaa1bbSagc * 3. Neither the name of the University nor the names of its contributors
1661f28255Scgd * may be used to endorse or promote products derived from this software
1761f28255Scgd * without specific prior written permission.
1861f28255Scgd *
1961f28255Scgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2061f28255Scgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2161f28255Scgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2261f28255Scgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2361f28255Scgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2461f28255Scgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2561f28255Scgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2661f28255Scgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2761f28255Scgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2861f28255Scgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2961f28255Scgd * SUCH DAMAGE.
3061f28255Scgd */
3161f28255Scgd
328976f097Slukem #include <sys/cdefs.h>
3361f28255Scgd #ifndef lint
3498e5374cSlukem __COPYRIGHT("@(#) Copyright (c) 1980, 1993\
3598e5374cSlukem The Regents of the University of California. All rights reserved.");
3661f28255Scgd #endif /* not lint */
3761f28255Scgd
3861f28255Scgd #ifndef lint
395233fb40Sjtc #if 0
405233fb40Sjtc static char sccsid[] = "@(#)soelim.c 8.1 (Berkeley) 6/6/93";
415233fb40Sjtc #endif
42*39bbc68aSsevan __RCSID("$NetBSD: soelim.c,v 1.15 2016/09/05 00:40:29 sevan Exp $");
4361f28255Scgd #endif /* not lint */
4461f28255Scgd
4561f28255Scgd /*
4661f28255Scgd * soelim - a filter to process n/troff input eliminating .so's
4761f28255Scgd *
4861f28255Scgd * Author: Bill Joy UCB July 8, 1977
4961f28255Scgd *
5061f28255Scgd * This program eliminates .so's from a n/troff input stream.
5161f28255Scgd * It can be used to prepare safe input for submission to the
5261f28255Scgd * phototypesetter since the software supporting the operator
5361f28255Scgd * doesn't let him do chdir.
5461f28255Scgd *
5561f28255Scgd * This is a kludge and the operator should be given the
5661f28255Scgd * ability to do chdir.
5761f28255Scgd *
5861f28255Scgd * This program is more generally useful, it turns out, because
5961f28255Scgd * the program tbl doesn't understand ".so" directives.
6061f28255Scgd */
61b1d0822bSchristos #include <sys/param.h>
62b1d0822bSchristos #include <err.h>
63db49a933Sperry #include <stdio.h>
64db49a933Sperry #include <stdlib.h>
65db49a933Sperry #include <string.h>
66db49a933Sperry #include <unistd.h>
67b1d0822bSchristos
6861f28255Scgd #define STDIN_NAME "-"
6961f28255Scgd
70b1d0822bSchristos struct path {
71b1d0822bSchristos char **list;
72b1d0822bSchristos size_t n, c;
73b1d0822bSchristos };
74b1d0822bSchristos
75c6a94bbfSwiz static int process(struct path *, const char *);
760d526c6dSwiz static void initpath(struct path *);
770d526c6dSwiz static void addpath(struct path *, const char *);
780d526c6dSwiz static FILE *openpath(struct path *, const char *, const char *);
79b1d0822bSchristos
80b1d0822bSchristos
81b1d0822bSchristos static void
initpath(struct path * p)820d526c6dSwiz initpath(struct path *p)
83b1d0822bSchristos {
84b1d0822bSchristos p->list = NULL;
85b1d0822bSchristos p->n = p->c = 0;
86b1d0822bSchristos }
87b1d0822bSchristos
88b1d0822bSchristos static void
addpath(struct path * p,const char * dir)890d526c6dSwiz addpath(struct path *p, const char *dir)
90b1d0822bSchristos {
91d5250e4eSitojun char **n;
92d5250e4eSitojun
93b1d0822bSchristos if (p->list == NULL || p->n <= p->c - 2) {
94d5250e4eSitojun n = realloc(p->list, (p->n + 10) * sizeof(p->list[0]));
95d5250e4eSitojun if (n == NULL)
9685cbf55dSdrochner err(1, NULL);
97d5250e4eSitojun p->list = n;
98d5250e4eSitojun p->n += 10;
99b1d0822bSchristos }
100b1d0822bSchristos
101b1d0822bSchristos if ((p->list[p->c++] = strdup(dir)) == NULL)
10285cbf55dSdrochner err(1, NULL);
103b1d0822bSchristos
104b1d0822bSchristos p->list[p->c] = NULL;
105b1d0822bSchristos }
106b1d0822bSchristos
107b1d0822bSchristos static FILE *
openpath(struct path * p,const char * name,const char * parm)1080d526c6dSwiz openpath(struct path *p, const char *name, const char *parm)
109b1d0822bSchristos {
110b1d0822bSchristos char filename[MAXPATHLEN];
111b1d0822bSchristos const char *f;
112b1d0822bSchristos FILE *fp;
113b1d0822bSchristos size_t i;
114b1d0822bSchristos
115b1d0822bSchristos if (*name == '/' || p->c == 0)
116b1d0822bSchristos return fopen(name, parm);
117b1d0822bSchristos
118b1d0822bSchristos for (i = 0; i < p->c; i++) {
119b1d0822bSchristos if (p->list[i][0] == '\0')
120b1d0822bSchristos f = name;
121b1d0822bSchristos else {
122b1d0822bSchristos (void)snprintf(filename, sizeof(filename), "%s/%s",
123b1d0822bSchristos p->list[i], name);
124b1d0822bSchristos f = filename;
125b1d0822bSchristos }
126b1d0822bSchristos if ((fp = fopen(f, parm)) != NULL)
127b1d0822bSchristos return fp;
128b1d0822bSchristos }
129b1d0822bSchristos return NULL;
130b1d0822bSchristos }
1318976f097Slukem
1328976f097Slukem int
main(int argc,char * argv[])1330d526c6dSwiz main(int argc, char *argv[])
13461f28255Scgd {
135b1d0822bSchristos struct path p;
136b1d0822bSchristos int c;
13761f28255Scgd
138b1d0822bSchristos initpath(&p);
139b1d0822bSchristos addpath(&p, ".");
140b1d0822bSchristos
141b1d0822bSchristos while ((c = getopt(argc, argv, "I:")) != -1)
142b1d0822bSchristos switch (c) {
143b1d0822bSchristos case 'I':
144b1d0822bSchristos addpath(&p, optarg);
145b1d0822bSchristos break;
146b1d0822bSchristos default:
147b1d0822bSchristos (void)fprintf(stderr,
148b635f565Sjmmv "usage: %s [-I<dir>] [files...]\n",
149a8ec668dScgd getprogname());
150b1d0822bSchristos exit(1);
151b1d0822bSchristos }
152b1d0822bSchristos
153b1d0822bSchristos argc -= optind;
154b1d0822bSchristos argv += optind;
155b1d0822bSchristos
15661f28255Scgd if (argc == 0) {
157b1d0822bSchristos (void)process(&p, STDIN_NAME);
15861f28255Scgd exit(0);
15961f28255Scgd }
16061f28255Scgd do {
161b1d0822bSchristos (void)process(&p, argv[0]);
16261f28255Scgd argv++;
16361f28255Scgd argc--;
16461f28255Scgd } while (argc > 0);
16561f28255Scgd exit(0);
16661f28255Scgd }
16761f28255Scgd
1688976f097Slukem int
process(struct path * p,const char * file)169c6a94bbfSwiz process(struct path *p, const char *file)
17061f28255Scgd {
1718976f097Slukem char *cp;
1728976f097Slukem int c;
17361f28255Scgd char fname[BUFSIZ];
17461f28255Scgd FILE *soee;
17561f28255Scgd int isfile;
17661f28255Scgd
17761f28255Scgd if (!strcmp(file, STDIN_NAME)) {
17861f28255Scgd soee = stdin;
17961f28255Scgd } else {
180b1d0822bSchristos soee = openpath(p, file, "r");
18161f28255Scgd if (soee == NULL) {
182b1d0822bSchristos warn("Cannot open `%s'", file);
18361f28255Scgd return(-1);
18461f28255Scgd }
18561f28255Scgd }
18661f28255Scgd for (;;) {
18761f28255Scgd c = getc(soee);
18861f28255Scgd if (c == EOF)
18961f28255Scgd break;
19061f28255Scgd if (c != '.')
19161f28255Scgd goto simple;
19261f28255Scgd c = getc(soee);
19361f28255Scgd if (c != 's') {
19461f28255Scgd putchar('.');
19561f28255Scgd goto simple;
19661f28255Scgd }
19761f28255Scgd c = getc(soee);
19861f28255Scgd if (c != 'o') {
19961f28255Scgd printf(".s");
20061f28255Scgd goto simple;
20161f28255Scgd }
20261f28255Scgd do
20361f28255Scgd c = getc(soee);
20461f28255Scgd while (c == ' ' || c == '\t');
20561f28255Scgd cp = fname;
20661f28255Scgd isfile = 0;
20761f28255Scgd for (;;) {
20861f28255Scgd switch (c) {
20961f28255Scgd
21061f28255Scgd case ' ':
21161f28255Scgd case '\t':
21261f28255Scgd case '\n':
21361f28255Scgd case EOF:
21461f28255Scgd goto donename;
21561f28255Scgd
21661f28255Scgd default:
21761f28255Scgd *cp++ = c;
21861f28255Scgd c = getc(soee);
21961f28255Scgd isfile++;
22061f28255Scgd continue;
22161f28255Scgd }
22261f28255Scgd }
22361f28255Scgd donename:
22461f28255Scgd if (cp == fname) {
22561f28255Scgd printf(".so");
22661f28255Scgd goto simple;
22761f28255Scgd }
22861f28255Scgd *cp = 0;
229b1d0822bSchristos if (process(p, fname) < 0)
23061f28255Scgd if (isfile)
23161f28255Scgd printf(".so %s\n", fname);
23261f28255Scgd continue;
23361f28255Scgd simple:
23461f28255Scgd if (c == EOF)
23561f28255Scgd break;
23661f28255Scgd putchar(c);
23761f28255Scgd if (c != '\n') {
23861f28255Scgd c = getc(soee);
23961f28255Scgd goto simple;
24061f28255Scgd }
24161f28255Scgd }
24261f28255Scgd if (soee != stdin) {
24361f28255Scgd fclose(soee);
24461f28255Scgd }
24561f28255Scgd return(0);
24661f28255Scgd }
247