Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/builtin/strings.c
1808 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1992-2012 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* Glenn Fowler <[email protected]> *
18
* David Korn <[email protected]> *
19
* *
20
***********************************************************************/
21
#pragma prototyped
22
/*
23
* David Korn
24
* AT&T Research
25
*
26
* strings
27
*/
28
29
static const char usage[] =
30
"[-?\n@(#)$Id: strings (AT&T Research) 2000-04-01 $\n]"
31
USAGE_LICENSE
32
"[+NAME?strings - find and display printable strings in files]"
33
"[+DESCRIPTION?\bstrings\b searches for printable strings in regular files"
34
" and writes those strings to the standard output. A printable string"
35
" is any sequence of four (by default) or more printable characters"
36
" terminated by a newline or NUL character.]"
37
38
"[a:all?Scan the entire file. Always enabled in this implementation.]"
39
"[l:long-strings?Ignore \anewline\a characters as string terminators and"
40
" display strings using C character escape sequences. These strings"
41
" are suitably escaped for placement inside C \"...\" and"
42
" \bksh\b(1) $'...' string literals.]"
43
"[m:multi-byte?Scan for multibyte strings.]"
44
"[n:length|bytes?Set the minimum matched string length to \alength\a. For"
45
" compatibility -\anumber\a is equivalent to"
46
" \b--length\b=\anumber\a.]#[number:=4]"
47
"[t:radix|format?Write each string preceded by its byte offset from the"
48
" start of the file. The offset radix is determined by:]:[format]{"
49
" [+d?decimal]"
50
" [+o?octal]"
51
" [+x?hexadecimal]"
52
"}"
53
"[o:octal?Equivalent to \b--radix=o\b.]"
54
55
"\n"
56
"\n[ file ... ]\n"
57
"\n"
58
59
"[+SEE ALSO?\bgrep\b(1), \bnm\b(1), \bwhat\b(1)]"
60
;
61
62
#include <cmd.h>
63
#include <ctype.h>
64
65
#define MULTIBYTE 0x01 /* must be 1 */
66
#define MULTILINE 0x02
67
68
#define WIDTH 4
69
70
#define special(c) (isspace(c) || (c) == '\a' || (c) == '\b')
71
72
static int
73
mapchar(register int c)
74
{
75
switch (c)
76
{
77
case '\a':
78
return('a');
79
case '\b':
80
return('b');
81
case '\f':
82
return('f');
83
case '\n':
84
return('n');
85
case '\r':
86
return('r');
87
case '\t':
88
return('t');
89
case '\v':
90
return('v');
91
case '"':
92
return('"');
93
case '\'':
94
return('\'');
95
case '\\':
96
return('\\');
97
}
98
return 0;
99
}
100
101
static int
102
outstring(Sfio_t* out, char* cp, int nbytes, register int flags)
103
{
104
register int c;
105
register int d;
106
register int n = nbytes;
107
108
while (n-- > 0)
109
{
110
c = *cp;
111
if (flags & MULTIBYTE)
112
cp += 2;
113
else
114
cp++;
115
if ((flags & MULTILINE) && (d = mapchar(c)))
116
{
117
sfputc(out, '\\');
118
nbytes++;
119
c = d;
120
}
121
sfputc(out, c);
122
}
123
sfputc(out, '\n');
124
return nbytes + 1;
125
}
126
127
static int
128
strings(Sfio_t* in, Sfio_t* out, register int width, char* format, register int flags)
129
{
130
register int n = 0;
131
register int c;
132
register unsigned char* inp;
133
register unsigned char* inend;
134
register int state = 0;
135
int sep;
136
off_t offset;
137
138
char fmt[64];
139
140
if (format)
141
{
142
c = strlen(format) - 1;
143
if (flags & MULTIBYTE)
144
sfsprintf(fmt, sizeof(fmt), "%%%.*sI*%c", c, format, format[c]);
145
else
146
sfsprintf(fmt, sizeof(fmt), "%%%.*sI*%c %%.*s\n", c, format, format[c]);
147
if ((offset = sfseek(in, (off_t)0, SEEK_CUR)) < 0)
148
offset = 0;
149
offset--;
150
}
151
sep = (flags & MULTILINE) ? 0 : '\n';
152
while ((inp = (unsigned char*)sfgetr(in, sep, 0)) || (inp = (unsigned char*)sfgetr(in, sep, -1)))
153
{
154
c = sfvalue(in);
155
inend = inp+c;
156
offset += c;
157
for (;;)
158
{
159
if (inp >= inend || !(c = *inp++) || !isprint(c) && (!(flags & MULTILINE) || !special(c)))
160
{
161
if (n >= width && !state)
162
{
163
if (format)
164
{
165
if (flags & (MULTIBYTE|MULTILINE))
166
{
167
if (sfprintf(out, fmt, sizeof(offset), offset - (inend - inp) - n) < 0)
168
return 0;
169
n = outstring(out, (char*)inp - ((flags & MULTIBYTE) + 1) * n - 1, n, flags);
170
}
171
else
172
n = sfprintf(out, fmt, sizeof(offset), offset - (inend - inp) - n, n, inp - n - 1);
173
}
174
else if (flags & (MULTIBYTE|MULTILINE))
175
n = outstring(out, (char*)inp - ((flags & MULTIBYTE) + 1) * n - 1, n, flags);
176
else
177
n = sfprintf(out, "%.*s\n", n, inp - n - 1);
178
if (n < 0)
179
return 0;
180
}
181
if (c || !state)
182
n = 0;
183
else
184
state = 0;
185
if (inp >= inend)
186
break;
187
}
188
else if (state)
189
n = 0;
190
else
191
{
192
if (flags & MULTIBYTE)
193
state = 1;
194
n++;
195
}
196
}
197
}
198
return 1;
199
}
200
201
int
202
b_strings(int argc, char** argv, Shbltin_t* context)
203
{
204
register int n;
205
register int width = WIDTH;
206
register int flags = 0;
207
register Sfio_t* fp;
208
register char* cp;
209
register char* format = 0;
210
211
cmdinit(argc, argv, context, ERROR_CATALOG, 0);
212
if (argv[1] && streq(argv[1], "-"))
213
argv++;
214
for (;;)
215
{
216
switch (optget(argv, usage))
217
{
218
case 'a':
219
/* ignore this */
220
continue;
221
case 'l':
222
flags |= MULTILINE;
223
continue;
224
case 'm':
225
flags |= MULTIBYTE;
226
continue;
227
case 'n':
228
if ((width = opt_info.num) <= 0)
229
error(2, "%d: width must be positive", opt_info.num);
230
continue;
231
case 'o':
232
format = "07d";
233
continue;
234
case 't':
235
for (cp = opt_info.arg; (n = *cp) == '+' || n == '-' || n == '.' || isdigit(n); cp++);
236
if (!*(cp + 1) && ((n = *cp) == 'd' || n == 'o' || n == 'x'))
237
format = opt_info.arg;
238
else
239
error(2, "%d: format must be d, o, or x", opt_info.arg);
240
continue;
241
case ':':
242
error(2, "%s", opt_info.arg);
243
continue;
244
case '?':
245
error(ERROR_usage(2), "%s", opt_info.arg);
246
continue;
247
}
248
break;
249
}
250
argv += opt_info.index;
251
if (error_info.errors)
252
error(ERROR_usage(2), "%s", optusage(NiL));
253
if (cp = *argv)
254
argv++;
255
do
256
{
257
if (!cp || streq(cp, "-"))
258
fp = sfstdin;
259
else if (!(fp = sfopen(NiL, cp, "r")))
260
{
261
error(ERROR_system(0), "%s: cannot open", cp);
262
error_info.errors = 1;
263
continue;
264
}
265
if (!strings(fp, sfstdout, width, format, flags))
266
{
267
error(ERROR_system(0), "%s: failed", cp);
268
error_info.errors = 1;
269
}
270
if (fp != sfstdin)
271
sfclose(fp);
272
} while (cp = *argv++);
273
return error_info.errors;
274
}
275
276
277