Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/dss/dss.c
1808 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 2002-2011 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
* *
19
***********************************************************************/
20
#pragma prototyped
21
/*
22
* data stream scan
23
*
24
* Glenn Fowler
25
* AT&T Research
26
*/
27
28
#include <ast.h>
29
#include <dsslib.h>
30
#include <ctype.h>
31
#include <error.h>
32
33
static const char usage[] =
34
"[-?\n@(#)$Id: dss (AT&T Research) 2011-09-11 $\n]"
35
USAGE_LICENSE
36
"[+NAME?dss - scan a data stream and apply a select expression to each "
37
"record]"
38
"[+DESCRIPTION?\bdss\b scans a record-oriented data stream, applies a "
39
"select \aexpression\a to each record, and writes the matching records "
40
"to the standard output. If \aexpression\a is \b-\b or empty then all "
41
"records match. If \aexpression\a begins with \b<\b then the remainder "
42
"of the expression is a file containing the expression. If \afile\a is "
43
"\b-\b or omitted then the standard input is read. If \afile\a begins "
44
"with \b<\b then the string with \b<\b removed is a file containing a "
45
"newline-separated list of files to process. If |{\bwrite\b \aformat\a}"
46
"is not specified then the output format is the same as the format of "
47
"the first input \afile\a.]"
48
"[+?Input files are \avczip\a(1), \agzip\a(1), \abzip2\a(1) or "
49
"\apzip\a(1) decompressed if necessary.]"
50
"[+EXPRESSIONS?Query expressions support C-style syntax. Strings may be "
51
"specified with '...', \"...\" or /.../ delimiters. \b=~\b and \b!~\b "
52
"operations on strings treat the right hand operand as a possibly "
53
"field-specific matching pattern. \bstring\b field matching patterns are "
54
"extended \bregex\b(3) regular expressions (\begrep\b(1) style.)]"
55
"[+?Types, queries and functions are brought into scope by \b--library\b "
56
"references on the command line, library references within schema "
57
"definitions, or by explicit \alib\a::\aidentifier\a binding within "
58
"expressions. Variables and function return values within expressions "
59
"and \b{print}\b formats may be cast to another type using C style casts "
60
"(\alib\a::\atype\a) and (\atype\a).]"
61
"[+?An expression of the form { \aquery\a [--\aoption\a...]] [\aarg\a...]] "
62
"[> \aoutput\a]] } accesses the compiled \aquery\a defined in a "
63
"\b--library\b dynamic library. { \aquery\a \b--man\b } lists the "
64
"documentation for \aquery\a.]"
65
"[+?Dynamic queries enclosed in {...} and interpreted queries enclosed "
66
"in (...) may be composed using the \b|\b, \b?:\b, and \b;\b operators. "
67
"\aA\a|\aB\a specifies that query \aB\a processes records selected by "
68
"query \aA\a. \aA\a?\aB\a:\aC\a specifies that query \aB\a processes the "
69
"records selected by query \aA\a and query \aC\a processes the records "
70
"not selected by query \aA\a; query \aB\a may be omitted. \aA\a;\aB\a "
71
"specifies that queries \aA\a and \aB\a process the same records.]"
72
"{\fformats and variables\f}"
73
"[a:append?Open output files in append mode. This disables file header "
74
"output.]"
75
"[d:debug?Enable debug tracing.]"
76
"[I:include?Add \adir\a to the list of directories searched for include "
77
"files. The default \b../lib/dss\b directories on \b$PATH\b are added to "
78
"this list.]:[dir]"
79
"[l:library?Load the dynamic library \aname\a. \bdss\b libraries may "
80
"define methods, types, maps, queries or functions.]:[name]"
81
"[m:map?Numeric field value map XML file. \b--method=dss,man\b describes "
82
"the \b<MAP>\b tag.]:[file]"
83
"[P:plugins?List plugin information for each \afile\a operand in "
84
"--\astyle\a on the standard error. The \aexpression\a operand is not "
85
"specified in this case. If no \afile\a operands are specified then the "
86
"first instance of each \bdss\b plugin installed on \b$PATH\b or a "
87
"sibling dir on \b$PATH\b is listed. The special \astyle\a \blist\b "
88
"lists a line on the standard output for each plugin with the name, a "
89
"tab character, and plugin specific command line options parameterized "
90
"by \b${style}\b (suitable for \beval\b'ing in "
91
"\bsh\b(1).)]:[style:=list|man|html|nroff|usage]"
92
"[q:quiet?Disable non-fatal warning messages.]"
93
"[v:verbose?Enable verbose status messages.]"
94
"[x:method?Set the record method. This option must be specified. The "
95
"method name may be followed by a , separated list of method specific "
96
"\a[no]]name[=value]]\a options and a schema following the first :. "
97
"Method specific usage may be listed by the \bman\b or \bhtml\b method "
98
"specific options. Each method is typically implemented in a separate "
99
"shared library. If the method shared library is not installed on "
100
"\b$PATH\b or a sibling dir on \b$PATH\b then \amethod\a must be the "
101
"full path name of the shared library. The methods, determined by "
102
"\b$PATH\b, are:]:[method[,option[=value]]...]][::schema]]]"
103
"{\fmethods\f} [T:test?Enable test code defined by \amask\a. Test code "
104
"is implementation specific.]#[mask]"
105
"{"
106
"[0x00f0?method specific tests]"
107
"[0x0f00?cx library specific tests]"
108
"[0x0100?enable cxeval() code trace]"
109
"[0xf000?dss library specific tests]"
110
"}"
111
"[c:count?Write the \amatched/total\a records on the standard output. "
112
"Deprecated: compose the expression with |{\bcount\b} instead.]"
113
"[f:format?Set the output method format. Deprecated: compose the "
114
"expression with |{\bwrite\b \aformat\a} instead.]:[format]"
115
"[n:nooutput?Disable all output. Deprecated: not required when the "
116
"expression contains a dynamic query.]"
117
"[p:print?Print selected records according to \aformat\a. Deprecated: "
118
"compose the expression with |{\bprint\b \aformat\a} instead.]:[format]"
119
"[+EXAMPLES]"
120
"{"
121
"[+dss -x dss '{stats --man}'?List the \bstats\b query manpage.]"
122
"[+dss -x bgp '{write --man}'?List the formats supported by the "
123
"\bbgp\b method.]"
124
"[+dss -x netflow \"{stats --group=prot bytes packets}\" *.gz?List "
125
"the stats for the \bnetflow\b method fields \bbytes\b and "
126
"\bpackets\b, grouped by values in the field \bprot\b.]"
127
"[+dss -x bgp {count} cisco.dat?Count the number of \bbgp\b "
128
"records in \bcisco.dat\b.]"
129
"[+dss -x bgp '(type==\"A\")??{write table > a}::{write cisco > "
130
"b}' mrt.dat?Write the announce records from \bmrt.dat\b to the "
131
"file \ba\b in the \btable\b format and all other records to the "
132
"file \bb\b in the \bcisco\b format.]"
133
"[+dss -x foo-txt '{flat foo-bin}|{compress}' foo.txt > foo.bin?Convert "
134
"the \bfoo-txt\b file \bfoo.txt\b to the \bfoo-bin\b \bflat\b "
135
"method format file \bfoo.bin\b using the preferred compression "
136
"method, where \bfoo-txt.dss\b and \bfoo-bin.dss\b are user "
137
"supplied \bdss\b XML schema files describing the input and "
138
"output formats.]"
139
"[+dss -x foo-bin '(time>=\"jan 1\")|{flat foo-txt}' foo.bin?Select "
140
"all \bfoo.bin\b records with \btime\b > jan 1 and list them in "
141
"the \bfoo-txt\b format.]"
142
"}"
143
144
"\n"
145
"\n [ expression ] [ file ... ]\n"
146
"\n"
147
148
"[+SEE ALSO?\bvczip\b(1), \bgzip\b(1), \bbzip2\b(1), \bpzip\b(1), \bcql\b(1), \bdss::dss\b(5P)]"
149
;
150
151
static void
152
showplugin(register Dsslib_t* lib, const char* style, Sfio_t* sp, int* sep, Dssdisc_t* disc)
153
{
154
register int i;
155
register const char* s;
156
157
if (*sep < 0)
158
{
159
if (lib->meth)
160
sfprintf(sfstdout, "%s\t--library=%s --method=%s,${style}\n", lib->meth->name, lib->name, lib->meth->name);
161
if (lib->queries)
162
for (i = 0; s = lib->queries[i].name; i++)
163
{
164
if (lib->meth && !streq(lib->meth->name, error_info.id))
165
sfprintf(sfstdout, "%s-", lib->meth->name);
166
else if (!streq(lib->name, error_info.id) && !streq(lib->name, s))
167
sfprintf(sfstdout, "%s-", lib->name);
168
sfprintf(sfstdout, "%s\t--library=%s --method=%s \"{%s --'${style}'}\" </dev/null\n", s, lib->name, error_info.id, s);
169
}
170
}
171
else
172
{
173
if (*sep)
174
sfputc(sfstderr, '\n');
175
else
176
*sep = 1;
177
dssoptlib(sp, lib, NiL, disc);
178
error(ERROR_USAGE, "%s", opthelp(sfstruse(sp), style));
179
}
180
}
181
182
int
183
main(int argc, char** argv)
184
{
185
int status;
186
int sep;
187
char* action;
188
char* expression;
189
char* file;
190
char* plugins;
191
Sfio_t* tmp;
192
Dss_t* dss;
193
Dssdisc_t disc;
194
Dssmeth_t* meth;
195
Dsslib_t* lib;
196
Dssstate_t* state;
197
Dssflags_t flags;
198
Dssflags_t test;
199
Dssoptdisc_t optdisc;
200
char style[32];
201
202
if (file = strrchr(*argv, '/'))
203
file++;
204
else
205
file = *argv;
206
error_info.id = file;
207
state = dssinit(&disc, errorf);
208
memset(&optdisc, 0, sizeof(optdisc));
209
optdisc.optdisc.version = OPT_VERSION;
210
optdisc.optdisc.infof = dssoptinfo;
211
optdisc.disc = &disc;
212
opt_info.disc = &optdisc.optdisc;
213
action = 0;
214
flags = 0;
215
meth = 0;
216
plugins = 0;
217
status = 0;
218
test = 0;
219
for (;;)
220
{
221
switch (optget(argv, usage))
222
{
223
case 'a':
224
flags |= DSS_APPEND;
225
continue;
226
case 'c':
227
action = "{count}";
228
continue;
229
case 'd':
230
flags |= DSS_DEBUG;
231
continue;
232
case 'f':
233
if (!(action = strdup(sfprints("{write %s}", fmtquote(opt_info.arg, "'", "'", strlen(opt_info.arg), FMT_ALWAYS|FMT_ESCAPED)))))
234
error(ERROR_SYSTEM|3, "out of space");
235
continue;
236
case 'I':
237
if (pathinclude(opt_info.arg))
238
error(ERROR_SYSTEM|3, "out of space");
239
continue;
240
case 'l':
241
if (!dssload(opt_info.arg, &disc))
242
break;
243
continue;
244
case 'm':
245
disc.map = opt_info.arg;
246
continue;
247
case 'n':
248
action = "{null}";
249
continue;
250
case 'p':
251
if (!(action = strdup(sfprints("{print %s}", fmtquote(opt_info.arg, "'", "'", strlen(opt_info.arg), FMT_ALWAYS|FMT_ESCAPED)))))
252
error(ERROR_SYSTEM|3, "out of space");
253
continue;
254
case 'q':
255
flags |= DSS_QUIET;
256
continue;
257
case 'v':
258
flags |= DSS_VERBOSE;
259
continue;
260
case 'x':
261
if (!(meth = dssmeth(opt_info.arg, &disc)))
262
error(3, "%s: unknown method", opt_info.arg);
263
continue;
264
case 'P':
265
sfsprintf(plugins = style, sizeof(style), "?%s", opt_info.arg);
266
continue;
267
case 'T':
268
test = opt_info.num;
269
continue;
270
case '?':
271
if (error_info.errors)
272
return 1;
273
error(ERROR_USAGE|4, "%s", opt_info.arg);
274
continue;
275
case ':':
276
error(2, "%s", opt_info.arg);
277
continue;
278
}
279
break;
280
}
281
if (error_info.errors)
282
return 1;
283
argv += opt_info.index;
284
if (plugins)
285
{
286
if (!(tmp = sfstropen()))
287
error(ERROR_SYSTEM|3, "out of space");
288
sep = -streq(plugins, "?list");
289
if (!*argv)
290
for (lib = dsslib(NiL, DSS_VERBOSE, &disc); lib; lib = (Dsslib_t*)dtnext(state->cx->libraries, lib))
291
showplugin(lib, plugins, tmp, &sep, &disc);
292
else
293
while (file = *argv++)
294
if (lib = dsslib(file, DSS_VERBOSE, &disc))
295
showplugin(lib, plugins, tmp, &sep, &disc);
296
sfclose(tmp);
297
return error_info.errors != 0;
298
}
299
if (!(expression = *argv++))
300
error(ERROR_USAGE|4, "%s", optusage(NiL));
301
if (!(dss = dssopen(flags, test, &disc, meth)))
302
return 1;
303
if (dssrun(dss, expression, NiL, action, argv))
304
status = 1;
305
if (dssclose(dss))
306
status = 1;
307
return status;
308
}
309
310