1/*	$Id: soelim.c,v 1.5 2015/11/07 14:22:29 schwarze Exp $	*/
2/*
3 * Copyright (c) 2014 Baptiste Daroussin <bapt@FreeBSD.org>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer
11 *    in this position and unchanged.
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 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27#include "config.h"
28
29#include <sys/types.h>
30
31#include <ctype.h>
32#if HAVE_ERR
33#include <err.h>
34#endif
35#include <limits.h>
36#include <stdio.h>
37#include <stdlib.h>
38#include <string.h>
39#if HAVE_STRINGLIST
40#include <stringlist.h>
41#else
42#include "compat_stringlist.h"
43#endif
44#include <unistd.h>
45
46#define C_OPTION 0x1
47
48static StringList *includes;
49
50static void
51usage(void)
52{
53
54	fprintf(stderr, "usage: soelim [-Crtv] [-I dir] [files]\n");
55
56	exit(EXIT_FAILURE);
57}
58
59static FILE *
60soelim_fopen(const char *name)
61{
62	FILE *f;
63	char path[PATH_MAX];
64	size_t i;
65
66	if (strcmp(name, "-") == 0)
67		return (stdin);
68
69	if ((f = fopen(name, "r")) != NULL)
70		return (f);
71
72	if (*name == '/') {
73		warn("can't open '%s'", name);
74		return (NULL);
75	}
76
77	for (i = 0; i < includes->sl_cur; i++) {
78		snprintf(path, sizeof(path), "%s/%s", includes->sl_str[i],
79		    name);
80		if ((f = fopen(path, "r")) != NULL)
81			return (f);
82	}
83
84	warn("can't open '%s'", name);
85
86	return (f);
87}
88
89static int
90soelim_file(FILE *f, int flag)
91{
92	char *line = NULL;
93	char *walk, *cp;
94	size_t linecap = 0;
95	ssize_t linelen;
96
97	if (f == NULL)
98		return (1);
99
100	while ((linelen = getline(&line, &linecap, f)) > 0) {
101		if (strncmp(line, ".so", 3) != 0) {
102			printf("%s", line);
103			continue;
104		}
105
106		walk = line + 3;
107		if (!isspace(*walk) && ((flag & C_OPTION) == 0)) {
108			printf("%s", line);
109			continue;
110		}
111
112		while (isspace(*walk))
113			walk++;
114
115		cp = walk;
116		while (*cp != '\0' && !isspace(*cp))
117			cp++;
118		*cp = 0;
119		if (cp < line + linelen)
120			cp++;
121
122		if (*walk == '\0') {
123			printf("%s", line);
124			continue;
125		}
126		if (soelim_file(soelim_fopen(walk), flag) == 1) {
127			free(line);
128			return (1);
129		}
130		if (*cp != '\0')
131			printf("%s", cp);
132	}
133
134	free(line);
135	fclose(f);
136
137	return (0);
138}
139
140int
141main(int argc, char **argv)
142{
143	int ch, i;
144	int ret = 0;
145	int flags = 0;
146
147	includes = sl_init();
148	if (includes == NULL)
149		err(EXIT_FAILURE, "sl_init()");
150
151	while ((ch = getopt(argc, argv, "CrtvI:")) != -1) {
152		switch (ch) {
153		case 'C':
154			flags |= C_OPTION;
155			break;
156		case 'r':
157		case 'v':
158		case 't':
159			/* stub compatibility with groff's soelim */
160			break;
161		case 'I':
162			sl_add(includes, optarg);
163			break;
164		default:
165			sl_free(includes, 0);
166			usage();
167		}
168	}
169
170	argc -= optind;
171	argv += optind;
172
173	if (argc == 0)
174		ret = soelim_file(stdin, flags);
175
176	for (i = 0; i < argc; i++)
177		ret = soelim_file(soelim_fopen(argv[i]), flags);
178
179	sl_free(includes, 0);
180
181	return (ret);
182}
183