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