xref: /freebsd/usr.bin/soelim/soelim.c (revision 0330f102a01419425222549e73eb624f3ae08835)
1363da138SBaptiste Daroussin /*-
2363da138SBaptiste Daroussin  * Copyright (c) 2014 Baptiste Daroussin <bapt@FreeBSD.org>
3363da138SBaptiste Daroussin  * All rights reserved.
4363da138SBaptiste Daroussin  *
5363da138SBaptiste Daroussin  * Redistribution and use in source and binary forms, with or without
6363da138SBaptiste Daroussin  * modification, are permitted provided that the following conditions
7363da138SBaptiste Daroussin  * are met:
8363da138SBaptiste Daroussin  * 1. Redistributions of source code must retain the above copyright
9363da138SBaptiste Daroussin  *    notice, this list of conditions and the following disclaimer
10363da138SBaptiste Daroussin  *    in this position and unchanged.
11363da138SBaptiste Daroussin  * 2. Redistributions in binary form must reproduce the above copyright
12363da138SBaptiste Daroussin  *    notice, this list of conditions and the following disclaimer in the
13363da138SBaptiste Daroussin  *    documentation and/or other materials provided with the distribution.
14363da138SBaptiste Daroussin  *
15363da138SBaptiste Daroussin  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
16363da138SBaptiste Daroussin  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17363da138SBaptiste Daroussin  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18363da138SBaptiste Daroussin  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
19363da138SBaptiste Daroussin  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20363da138SBaptiste Daroussin  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21363da138SBaptiste Daroussin  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22363da138SBaptiste Daroussin  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23363da138SBaptiste Daroussin  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24363da138SBaptiste Daroussin  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25363da138SBaptiste Daroussin  */
26363da138SBaptiste Daroussin 
27363da138SBaptiste Daroussin #include <sys/cdefs.h>
28363da138SBaptiste Daroussin __FBSDID("$FreeBSD$");
29363da138SBaptiste Daroussin 
30363da138SBaptiste Daroussin #include <sys/param.h>
31363da138SBaptiste Daroussin 
32*0330f102SBaptiste Daroussin #include <ctype.h>
33*0330f102SBaptiste Daroussin #include <err.h>
34*0330f102SBaptiste Daroussin #include <stdbool.h>
35363da138SBaptiste Daroussin #define _WITH_GETLINE
36363da138SBaptiste Daroussin #include <stdio.h>
37363da138SBaptiste Daroussin #include <stdlib.h>
38363da138SBaptiste Daroussin #include <string.h>
39363da138SBaptiste Daroussin #include <stringlist.h>
40*0330f102SBaptiste Daroussin #include <unistd.h>
41363da138SBaptiste Daroussin 
42b4a0618cSBaptiste Daroussin #define C_OPTION 0x1
43b4a0618cSBaptiste Daroussin 
44363da138SBaptiste Daroussin static StringList *includes;
45363da138SBaptiste Daroussin 
46363da138SBaptiste Daroussin static void
47363da138SBaptiste Daroussin usage(void)
48363da138SBaptiste Daroussin {
49363da138SBaptiste Daroussin 
50363da138SBaptiste Daroussin 	fprintf(stderr, "usage: soelim [-Crtv] [-I dir] [files]\n");
51363da138SBaptiste Daroussin 
52363da138SBaptiste Daroussin 	exit(EXIT_FAILURE);
53363da138SBaptiste Daroussin }
54363da138SBaptiste Daroussin 
55363da138SBaptiste Daroussin static FILE *
56363da138SBaptiste Daroussin soelim_fopen(const char *name)
57363da138SBaptiste Daroussin {
58363da138SBaptiste Daroussin 	FILE *f;
59363da138SBaptiste Daroussin 	char path[MAXPATHLEN];
60363da138SBaptiste Daroussin 	size_t i;
61363da138SBaptiste Daroussin 
626f32f49cSXin LI 	if (strcmp(name, "-") == 0)
636f32f49cSXin LI 		return (stdin);
646f32f49cSXin LI 
65363da138SBaptiste Daroussin 	if ((f = fopen(name, "r")) != NULL)
66363da138SBaptiste Daroussin 		return (f);
67363da138SBaptiste Daroussin 
68363da138SBaptiste Daroussin 	if (*name == '/') {
69363da138SBaptiste Daroussin 		warn("can't open '%s'", name);
70363da138SBaptiste Daroussin 		return (NULL);
71363da138SBaptiste Daroussin 	}
72363da138SBaptiste Daroussin 
73363da138SBaptiste Daroussin 	for (i = 0; i < includes->sl_cur; i++) {
74363da138SBaptiste Daroussin 		snprintf(path, sizeof(path), "%s/%s", includes->sl_str[i],
75363da138SBaptiste Daroussin 		    name);
76363da138SBaptiste Daroussin 		if ((f = fopen(path, "r")) != NULL)
77363da138SBaptiste Daroussin 			return (f);
78363da138SBaptiste Daroussin 	}
79363da138SBaptiste Daroussin 
80363da138SBaptiste Daroussin 	warn("can't open '%s'", name);
81363da138SBaptiste Daroussin 
82363da138SBaptiste Daroussin 	return (f);
83363da138SBaptiste Daroussin }
84363da138SBaptiste Daroussin 
85363da138SBaptiste Daroussin static int
86b4a0618cSBaptiste Daroussin soelim_file(FILE *f, int flag)
87363da138SBaptiste Daroussin {
88363da138SBaptiste Daroussin 	char *line = NULL;
89b4a0618cSBaptiste Daroussin 	char *walk, *cp;
90363da138SBaptiste Daroussin 	size_t linecap = 0;
91363da138SBaptiste Daroussin 	ssize_t linelen;
92363da138SBaptiste Daroussin 
93363da138SBaptiste Daroussin 	if (f == NULL)
94363da138SBaptiste Daroussin 		return (1);
95363da138SBaptiste Daroussin 
96363da138SBaptiste Daroussin 	while ((linelen = getline(&line, &linecap, f)) > 0) {
97363da138SBaptiste Daroussin 		if (strncmp(line, ".so", 3) != 0) {
98363da138SBaptiste Daroussin 			printf("%s", line);
99363da138SBaptiste Daroussin 			continue;
100363da138SBaptiste Daroussin 		}
101b4a0618cSBaptiste Daroussin 
102363da138SBaptiste Daroussin 		walk = line + 3;
103b4a0618cSBaptiste Daroussin 		if (!isspace(*walk) && ((flag & C_OPTION) == 0)) {
104b4a0618cSBaptiste Daroussin 			printf("%s", line);
105b4a0618cSBaptiste Daroussin 			continue;
106b4a0618cSBaptiste Daroussin 		}
107b4a0618cSBaptiste Daroussin 
108363da138SBaptiste Daroussin 		while (isspace(*walk))
109363da138SBaptiste Daroussin 			walk++;
110363da138SBaptiste Daroussin 
1112b30fb26SBaptiste Daroussin 		cp = walk;
1122b30fb26SBaptiste Daroussin 		while (*cp != '\0' && !isspace(*cp))
1132b30fb26SBaptiste Daroussin 			cp++;
114b4a0618cSBaptiste Daroussin 		*cp = 0;
1152b30fb26SBaptiste Daroussin 		if (cp < line + linelen)
1162b30fb26SBaptiste Daroussin 			cp++;
117b4a0618cSBaptiste Daroussin 
118b4a0618cSBaptiste Daroussin 		if (*walk == '\0') {
119b4a0618cSBaptiste Daroussin 			printf("%s", line);
120b4a0618cSBaptiste Daroussin 			continue;
121b4a0618cSBaptiste Daroussin 		}
122b4a0618cSBaptiste Daroussin 		if (soelim_file(soelim_fopen(walk), flag) == 1) {
123363da138SBaptiste Daroussin 			free(line);
124363da138SBaptiste Daroussin 			return (1);
125363da138SBaptiste Daroussin 		}
1262b30fb26SBaptiste Daroussin 		if (*cp != '\0')
1272b30fb26SBaptiste Daroussin 			printf("%s", cp);
128363da138SBaptiste Daroussin 	}
129363da138SBaptiste Daroussin 
130363da138SBaptiste Daroussin 	free(line);
131363da138SBaptiste Daroussin 	fclose(f);
132363da138SBaptiste Daroussin 
133363da138SBaptiste Daroussin 	return (0);
134363da138SBaptiste Daroussin }
135363da138SBaptiste Daroussin 
136363da138SBaptiste Daroussin int
137363da138SBaptiste Daroussin main(int argc, char **argv)
138363da138SBaptiste Daroussin {
139363da138SBaptiste Daroussin 	int ch, i;
140363da138SBaptiste Daroussin 	int ret = 0;
141b4a0618cSBaptiste Daroussin 	int flags = 0;
142363da138SBaptiste Daroussin 
143363da138SBaptiste Daroussin 	includes = sl_init();
144363da138SBaptiste Daroussin 	if (includes == NULL)
145363da138SBaptiste Daroussin 		err(EXIT_FAILURE, "sl_init()");
146363da138SBaptiste Daroussin 
147363da138SBaptiste Daroussin 	while ((ch = getopt(argc, argv, "CrtvI:")) != -1) {
148363da138SBaptiste Daroussin 		switch (ch) {
149363da138SBaptiste Daroussin 		case 'C':
150b4a0618cSBaptiste Daroussin 			flags |= C_OPTION;
151b4a0618cSBaptiste Daroussin 			break;
152363da138SBaptiste Daroussin 		case 'r':
153363da138SBaptiste Daroussin 		case 'v':
154363da138SBaptiste Daroussin 		case 't':
155363da138SBaptiste Daroussin 			/* stub compatibility with groff's soelim */
156363da138SBaptiste Daroussin 			break;
157363da138SBaptiste Daroussin 		case 'I':
158363da138SBaptiste Daroussin 			sl_add(includes, optarg);
159363da138SBaptiste Daroussin 			break;
160363da138SBaptiste Daroussin 		default:
161363da138SBaptiste Daroussin 			sl_free(includes, 0);
162363da138SBaptiste Daroussin 			usage();
163363da138SBaptiste Daroussin 		}
164363da138SBaptiste Daroussin 	}
165363da138SBaptiste Daroussin 
166363da138SBaptiste Daroussin 	argc -= optind;
167363da138SBaptiste Daroussin 	argv += optind;
168363da138SBaptiste Daroussin 
169363da138SBaptiste Daroussin 	if (argc == 0)
170b4a0618cSBaptiste Daroussin 		ret = soelim_file(stdin, flags);
171363da138SBaptiste Daroussin 
172363da138SBaptiste Daroussin 	for (i = 0; i < argc; i++)
173b4a0618cSBaptiste Daroussin 		ret = soelim_file(soelim_fopen(argv[i]), flags);
174363da138SBaptiste Daroussin 
175363da138SBaptiste Daroussin 	sl_free(includes, 0);
176363da138SBaptiste Daroussin 
177363da138SBaptiste Daroussin 	return (ret);
178363da138SBaptiste Daroussin }
179