xref: /netbsd-src/external/bsd/less/dist/lessecho.c (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
1 /*	$NetBSD: lessecho.c,v 1.4 2013/09/04 19:44:21 tron Exp $	*/
2 
3 /*
4  * Copyright (C) 1984-2012  Mark Nudelman
5  *
6  * You may distribute under the terms of either the GNU General Public
7  * License or the Less License, as specified in the README file.
8  *
9  * For more information, see the README file.
10  */
11 
12 
13 /*
14  * lessecho [-ox] [-cx] [-pn] [-dn] [-a] file ...
15  * Simply echos its filename arguments on standard output.
16  * But any argument containing spaces is enclosed in quotes.
17  *
18  * -ox	Specifies "x" to be the open quote character.
19  * -cx	Specifies "x" to be the close quote character.
20  * -pn	Specifies "n" to be the open quote character, as an integer.
21  * -dn	Specifies "n" to be the close quote character, as an integer.
22  * -mx  Specifies "x" to be a metachar.
23  * -nn  Specifies "n" to be a metachar, as an integer.
24  * -ex  Specifies "x" to be the escape char for metachars.
25  * -fn  Specifies "x" to be the escape char for metachars, as an integer.
26  * -a	Specifies that all arguments are to be quoted.
27  *	The default is that only arguments containing spaces are quoted.
28  */
29 
30 #include "less.h"
31 
32 static char *version = "Revision: 1.3";
33 
34 static int quote_all = 0;
35 static char openquote = '"';
36 static char closequote = '"';
37 static char *meta_escape = "\\";
38 static char meta_escape_buf[2];
39 static char metachars[64] = "";
40 static int num_metachars = 0;
41 
42 static void pr_usage __P((void));
43 static void pr_version __P((void));
44 static void pr_error __P((char *));
45 static long lstrtol __P((char *, int, char **));
46 
47 	static void
48 pr_usage()
49 {
50 	fprintf(stderr,
51 		"usage: lessecho [-ox] [-cx] [-pn] [-dn] [-mx] [-nn] [-ex] [-fn] [-a] file ...\n");
52 }
53 
54 	static void
55 pr_version()
56 {
57 	char *p;
58 	char buf[10];
59 	char *pbuf = buf;
60 
61 	for (p = version;  *p != ' ';  p++)
62 		if (*p == '\0')
63 			return;
64 	for (p++;  *p != '$' && *p != ' ' && *p != '\0';  p++)
65 		*pbuf++ = *p;
66 	*pbuf = '\0';
67 	printf("%s\n", buf);
68 }
69 
70 	static void
71 pr_error(s)
72 	char *s;
73 {
74 	fprintf(stderr, "%s\n", s);
75 	exit(1);
76 }
77 
78 	static long
79 lstrtol(s, radix, pend)
80 	char *s;
81 	int radix;
82 	char **pend;
83 {
84 	int v;
85 	int neg = 0;
86 	long n = 0;
87 
88 	/* Skip leading white space. */
89 	while (*s == ' ' || *s == '\t')
90 		s++;
91 
92 	/* Check for a leading + or -. */
93 	if (*s == '-')
94 	{
95 		neg = 1;
96 		s++;
97 	} else if (*s == '+')
98 	{
99 		s++;
100 	}
101 
102 	/* Determine radix if caller does not specify. */
103 	if (radix == 0)
104 	{
105 		radix = 10;
106 		if (*s == '0')
107 		{
108 			switch (*++s)
109 			{
110 			case 'x':
111 				radix = 16;
112 				s++;
113 				break;
114 			default:
115 				radix = 8;
116 				break;
117 			}
118 		}
119 	}
120 
121 	/* Parse the digits of the number. */
122 	for (;;)
123 	{
124 		if (*s >= '0' && *s <= '9')
125 			v = *s - '0';
126 		else if (*s >= 'a' && *s <= 'f')
127 			v = *s - 'a' + 10;
128 		else if (*s >= 'A' && *s <= 'F')
129 			v = *s - 'A' + 10;
130 		else
131 			break;
132 		if (v >= radix)
133 			break;
134 		n = n * radix + v;
135 		s++;
136 	}
137 
138 	if (pend != NULL)
139 	{
140 		/* Skip trailing white space. */
141 		while (*s == ' ' || *s == '\t')
142 			s++;
143 		*pend = s;
144 	}
145 	if (neg)
146 		return (-n);
147 	return (n);
148 }
149 
150 
151 #if !HAVE_STRCHR
152 	char *
153 strchr(s, c)
154 	char *s;
155 	int c;
156 {
157 	for ( ;  *s != '\0';  s++)
158 		if (*s == c)
159 			return (s);
160 	if (c == '\0')
161 		return (s);
162 	return (NULL);
163 }
164 #endif
165 
166 	int
167 main(argc, argv)
168 	int argc;
169 	char *argv[];
170 {
171 	char *arg;
172 	char *s;
173 	int no_more_options;
174 
175 	no_more_options = 0;
176 	while (--argc > 0)
177 	{
178 		arg = *++argv;
179 		if (*arg != '-' || no_more_options)
180 			break;
181 		switch (*++arg)
182 		{
183 		case 'a':
184 			quote_all = 1;
185 			break;
186 		case 'c':
187 			closequote = *++arg;
188 			break;
189 		case 'd':
190 			closequote = lstrtol(++arg, 0, &s);
191 			if (s == arg)
192 				pr_error("Missing number after -d");
193 			break;
194 		case 'e':
195 			if (strcmp(++arg, "-") == 0)
196 				meta_escape = "";
197 			else
198 				meta_escape = arg;
199 			break;
200 		case 'f':
201 			meta_escape_buf[0] = lstrtol(++arg, 0, &s);
202 			meta_escape = meta_escape_buf;
203 			if (s == arg)
204 				pr_error("Missing number after -f");
205 			break;
206 		case 'o':
207 			openquote = *++arg;
208 			break;
209 		case 'p':
210 			openquote = lstrtol(++arg, 0, &s);
211 			if (s == arg)
212 				pr_error("Missing number after -p");
213 			break;
214 		case 'm':
215 			metachars[num_metachars++] = *++arg;
216 			metachars[num_metachars] = '\0';
217 			break;
218 		case 'n':
219 			metachars[num_metachars++] = lstrtol(++arg, 0, &s);
220 			if (s == arg)
221 				pr_error("Missing number after -n");
222 			metachars[num_metachars] = '\0';
223 			break;
224 		case '?':
225 			pr_usage();
226 			return (0);
227 		case '-':
228 			if (*++arg == '\0')
229 			{
230 				no_more_options = 1;
231 				break;
232 			}
233 			if (strcmp(arg, "version") == 0)
234 			{
235 				pr_version();
236 				return (0);
237 			}
238 			if (strcmp(arg, "help") == 0)
239 			{
240 				pr_usage();
241 				return (0);
242 			}
243 			pr_error("Invalid option after --");
244 		default:
245 			pr_error("Invalid option letter");
246 		}
247 	}
248 
249 	while (argc-- > 0)
250 	{
251 		int has_meta = 0;
252 		arg = *argv++;
253 		for (s = arg;  *s != '\0';  s++)
254 		{
255 			if (strchr(metachars, *s) != NULL)
256 			{
257 				has_meta = 1;
258 				break;
259 			}
260 		}
261 		if (quote_all || (has_meta && strlen(meta_escape) == 0))
262 			printf("%c%s%c", openquote, arg, closequote);
263 		else
264 		{
265 			for (s = arg;  *s != '\0';  s++)
266 			{
267 				if (strchr(metachars, *s) != NULL)
268 					printf("%s", meta_escape);
269 				printf("%c", *s);
270 			}
271 		}
272 		if (argc > 0)
273 			printf(" ");
274 		else
275 			printf("\n");
276 	}
277 	return (0);
278 }
279