xref: /freebsd/usr.bin/soelim/soelim.c (revision 5e3934b15a2741b2de6b217e77dc9d798d740804)
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 
27b704d1f2SBaptiste Daroussin #include <sys/types.h>
28b704d1f2SBaptiste Daroussin 
290330f102SBaptiste Daroussin #include <ctype.h>
300330f102SBaptiste Daroussin #include <err.h>
3146cc6349SBaptiste Daroussin #include <limits.h>
32363da138SBaptiste Daroussin #include <stdio.h>
33363da138SBaptiste Daroussin #include <stdlib.h>
34363da138SBaptiste Daroussin #include <string.h>
35363da138SBaptiste Daroussin #include <stringlist.h>
360330f102SBaptiste Daroussin #include <unistd.h>
37363da138SBaptiste Daroussin 
38b4a0618cSBaptiste Daroussin #define C_OPTION 0x1
39b4a0618cSBaptiste Daroussin 
40363da138SBaptiste Daroussin static StringList *includes;
41363da138SBaptiste Daroussin 
42363da138SBaptiste Daroussin static void
usage(void)43363da138SBaptiste Daroussin usage(void)
44363da138SBaptiste Daroussin {
45363da138SBaptiste Daroussin 
46363da138SBaptiste Daroussin 	fprintf(stderr, "usage: soelim [-Crtv] [-I dir] [files]\n");
47363da138SBaptiste Daroussin 
48363da138SBaptiste Daroussin 	exit(EXIT_FAILURE);
49363da138SBaptiste Daroussin }
50363da138SBaptiste Daroussin 
51224d9e3eSBaptiste Daroussin static FILE *
soelim_fopen(const char * name)52*3ba0c990SBaptiste Daroussin soelim_fopen(const char *name)
53224d9e3eSBaptiste Daroussin {
54*3ba0c990SBaptiste Daroussin 	FILE *f;
5546cc6349SBaptiste Daroussin 	char path[PATH_MAX];
56363da138SBaptiste Daroussin 	size_t i;
57363da138SBaptiste Daroussin 
586f32f49cSXin LI 	if (strcmp(name, "-") == 0)
596f32f49cSXin LI 		return (stdin);
606f32f49cSXin LI 
61*3ba0c990SBaptiste Daroussin 	if ((f = fopen(name, "r")) != NULL)
62*3ba0c990SBaptiste Daroussin 		return (f);
63363da138SBaptiste Daroussin 
64363da138SBaptiste Daroussin 	if (*name == '/') {
65363da138SBaptiste Daroussin 		warn("can't open '%s'", name);
66363da138SBaptiste Daroussin 		return (NULL);
67363da138SBaptiste Daroussin 	}
68363da138SBaptiste Daroussin 
69363da138SBaptiste Daroussin 	for (i = 0; i < includes->sl_cur; i++) {
70363da138SBaptiste Daroussin 		snprintf(path, sizeof(path), "%s/%s", includes->sl_str[i],
71363da138SBaptiste Daroussin 		    name);
72*3ba0c990SBaptiste Daroussin 		if ((f = fopen(path, "r")) != NULL)
73*3ba0c990SBaptiste Daroussin 			return (f);
74363da138SBaptiste Daroussin 	}
75363da138SBaptiste Daroussin 
76363da138SBaptiste Daroussin 	warn("can't open '%s'", name);
77363da138SBaptiste Daroussin 
78160af931SBaptiste Daroussin 	return (f);
79363da138SBaptiste Daroussin }
80363da138SBaptiste Daroussin 
81363da138SBaptiste Daroussin static int
soelim_file(FILE * f,int flag)82*3ba0c990SBaptiste Daroussin soelim_file(FILE *f, int flag)
83363da138SBaptiste Daroussin {
84363da138SBaptiste Daroussin 	char *line = NULL;
85b4a0618cSBaptiste Daroussin 	char *walk, *cp;
86363da138SBaptiste Daroussin 	size_t linecap = 0;
87363da138SBaptiste Daroussin 	ssize_t linelen;
88363da138SBaptiste Daroussin 
89363da138SBaptiste Daroussin 	if (f == NULL)
90363da138SBaptiste Daroussin 		return (1);
91363da138SBaptiste Daroussin 
92363da138SBaptiste Daroussin 	while ((linelen = getline(&line, &linecap, f)) > 0) {
93363da138SBaptiste Daroussin 		if (strncmp(line, ".so", 3) != 0) {
94363da138SBaptiste Daroussin 			printf("%s", line);
95363da138SBaptiste Daroussin 			continue;
96363da138SBaptiste Daroussin 		}
97b4a0618cSBaptiste Daroussin 
98363da138SBaptiste Daroussin 		walk = line + 3;
99b4a0618cSBaptiste Daroussin 		if (!isspace(*walk) && ((flag & C_OPTION) == 0)) {
100b4a0618cSBaptiste Daroussin 			printf("%s", line);
101b4a0618cSBaptiste Daroussin 			continue;
102b4a0618cSBaptiste Daroussin 		}
103b4a0618cSBaptiste Daroussin 
104363da138SBaptiste Daroussin 		while (isspace(*walk))
105363da138SBaptiste Daroussin 			walk++;
106363da138SBaptiste Daroussin 
1072b30fb26SBaptiste Daroussin 		cp = walk;
1082b30fb26SBaptiste Daroussin 		while (*cp != '\0' && !isspace(*cp))
1092b30fb26SBaptiste Daroussin 			cp++;
110b4a0618cSBaptiste Daroussin 		*cp = 0;
1112b30fb26SBaptiste Daroussin 		if (cp < line + linelen)
1122b30fb26SBaptiste Daroussin 			cp++;
113b4a0618cSBaptiste Daroussin 
114b4a0618cSBaptiste Daroussin 		if (*walk == '\0') {
115b4a0618cSBaptiste Daroussin 			printf("%s", line);
116b4a0618cSBaptiste Daroussin 			continue;
117b4a0618cSBaptiste Daroussin 		}
118*3ba0c990SBaptiste Daroussin 		if (soelim_file(soelim_fopen(walk), flag) == 1) {
119363da138SBaptiste Daroussin 			free(line);
120363da138SBaptiste Daroussin 			return (1);
121363da138SBaptiste Daroussin 		}
1222b30fb26SBaptiste Daroussin 		if (*cp != '\0')
1232b30fb26SBaptiste Daroussin 			printf("%s", cp);
124363da138SBaptiste Daroussin 	}
125363da138SBaptiste Daroussin 
126363da138SBaptiste Daroussin 	free(line);
127363da138SBaptiste Daroussin 	fclose(f);
128363da138SBaptiste Daroussin 
129363da138SBaptiste Daroussin 	return (0);
130363da138SBaptiste Daroussin }
131363da138SBaptiste Daroussin 
132363da138SBaptiste Daroussin int
main(int argc,char ** argv)133363da138SBaptiste Daroussin main(int argc, char **argv)
134363da138SBaptiste Daroussin {
135*3ba0c990SBaptiste Daroussin 	int ch, i;
136363da138SBaptiste Daroussin 	int ret = 0;
137b4a0618cSBaptiste Daroussin 	int flags = 0;
138363da138SBaptiste Daroussin 
139363da138SBaptiste Daroussin 	includes = sl_init();
140363da138SBaptiste Daroussin 	if (includes == NULL)
141363da138SBaptiste Daroussin 		err(EXIT_FAILURE, "sl_init()");
142363da138SBaptiste Daroussin 
143363da138SBaptiste Daroussin 	while ((ch = getopt(argc, argv, "CrtvI:")) != -1) {
144363da138SBaptiste Daroussin 		switch (ch) {
145363da138SBaptiste Daroussin 		case 'C':
146b4a0618cSBaptiste Daroussin 			flags |= C_OPTION;
147b4a0618cSBaptiste Daroussin 			break;
148363da138SBaptiste Daroussin 		case 'r':
149363da138SBaptiste Daroussin 		case 'v':
150363da138SBaptiste Daroussin 		case 't':
151363da138SBaptiste Daroussin 			/* stub compatibility with groff's soelim */
152363da138SBaptiste Daroussin 			break;
153363da138SBaptiste Daroussin 		case 'I':
154363da138SBaptiste Daroussin 			sl_add(includes, optarg);
155363da138SBaptiste Daroussin 			break;
156363da138SBaptiste Daroussin 		default:
157363da138SBaptiste Daroussin 			sl_free(includes, 0);
158363da138SBaptiste Daroussin 			usage();
159363da138SBaptiste Daroussin 		}
160363da138SBaptiste Daroussin 	}
161363da138SBaptiste Daroussin 
162363da138SBaptiste Daroussin 	argc -= optind;
163363da138SBaptiste Daroussin 	argv += optind;
164363da138SBaptiste Daroussin 
165363da138SBaptiste Daroussin 	if (argc == 0)
166*3ba0c990SBaptiste Daroussin 		ret = soelim_file(stdin, flags);
167363da138SBaptiste Daroussin 
168363da138SBaptiste Daroussin 	for (i = 0; i < argc; i++)
169*3ba0c990SBaptiste Daroussin 		ret = soelim_file(soelim_fopen(argv[i]), flags);
170363da138SBaptiste Daroussin 
171363da138SBaptiste Daroussin 	sl_free(includes, 0);
172363da138SBaptiste Daroussin 
173363da138SBaptiste Daroussin 	return (ret);
174363da138SBaptiste Daroussin }
175