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