1 /* zxbustailf.c - tailf like utility for sending tail of a log to zxbus
2 * Copyright (c) 2012 Sampo Kellomaki (sampo@iki.fi), All Rights Reserved.
3 * This is confidential unpublished proprietary source code of the author.
4 * NO WARRANTY, not even implied warranties. Contains trade secrets.
5 * Distribution prohibited unless authorized in writing.
6 * Licensed under Apache License 2.0, see file COPYING.
7 * $Id: zxcot.c,v 1.5 2009-11-29 12:23:06 sampo Exp $
8 *
9 * 27.8.2009, created --Sampo
10 */
11
12 #include "platform.h" /* for dirent.h and unistd.h */
13
14 #include <string.h>
15 #include <stdio.h>
16 #include <fcntl.h>
17 #include <errno.h>
18 #include <sys/wait.h>
19
20 #include "platform.h"
21 #include "errmac.h"
22 #include "zx.h"
23 #include "zxid.h"
24 #include "zxidutil.h"
25 #include "zxidconf.h"
26 #include "c/zxidvers.h"
27 #include "c/zx-const.h"
28 #include "c/zx-ns.h"
29 #include "c/zx-data.h"
30
31 char* help =
32 "zxbustailf - tail a log file and send events to zxbus R" ZXID_REL "\n\
33 zxbus is an Audit Bus for TAS3 or end2end Trus Assurance (e2eTA).\n\
34 Copyright (c) 2012 Sampo Kellomaki (sampo@iki.fi), All Rights Reserved.\n\
35 NO WARRANTY, not even implied warranties. Licensed under Apache License v2.0\n\
36 See http://www.apache.org/licenses/LICENSE-2.0\n\
37 Send well researched bug reports to the author. Home: zxid.org\n\
38 \n\
39 Usage: zxbustailf [options] < stream-to-log # Will stop at EOF\n\
40 zxbustailf [options] /file/to/tailf\n\
41 zxbustailf [options] -e MSG </dev/null\n\
42 -c CONF Optional configuration string (default -c PATH=/var/zxid/)\n\
43 Most of the configuration is read from " ZXID_CONF_PATH "\n\
44 -c 'BUS_URL=stomps://localhost:2229/' -- Typical invocation\n\
45 -ch CHAN Indicate logging channel. Default is to use configuration.\n\
46 -n N or -N Output the last N lines of file - the default is to log all.\n\
47 -e MSG Log message from command line\n\
48 -ctl CTL Send ZXCTL command (for testing and benchmarking)\n\
49 -i N Number of iterations of connect-send-disconnect cycle. For benchmarking.\n\
50 -is N Number of sends per connection, for benchmarking.\n\
51 -it N Number of threads launching parallel sessions, for benchmarking.\n\
52 -v Verbose messages.\n\
53 -q Be extra quiet.\n\
54 -a -a Turn on ascii coloring for stdout.\n\
55 -d Turn on debugging.\n\
56 -dc Dump config.\n\
57 -h This help message\n\
58 -- End of options\n\
59 \n\
60 echo '<query>Foo</query>' | zxbustailf -a https://idp.tas3.eu/zxididp?o=B user:pw -t urn:x-demo-svc\n\
61 \n";
62
63 int dryrun = 0;
64 extern int zxbus_verbose; /* zxbusprod.c */
65 extern int zxbus_ascii_color;
66 int n_iter = 1;
67 int n_send = 1;
68 int n_thr = 1;
69 char* bdy = 0;
70 char* ctl = 0;
71 char* chan = "default";
72 zxid_conf* cf;
73
74 /* Called by: main x8, zxbusd_main, zxbuslist_main, zxbustailf_main, zxcall_main, zxcot_main, zxdecode_main */
opt(int * argc,char *** argv,char *** env)75 static void opt(int* argc, char*** argv, char*** env)
76 {
77 struct zx_str* ss;
78 if (*argc <= 1) return;
79
80 while (1) {
81 ++(*argv); --(*argc);
82
83 if (!(*argc) || ((*argv)[0][0] != '-')) break; /* normal exit from options loop */
84
85 switch ((*argv)[0][1]) {
86 case '-': if ((*argv)[0][2]) break;
87 ++(*argv); --(*argc);
88 DD("End of options by --");
89 return; /* -- ends the options */
90
91 case 'a':
92 switch ((*argv)[0][2]) {
93 case '\0':
94 ++zxbus_ascii_color;;
95 continue;
96 }
97 break;
98
99 case 'c':
100 switch ((*argv)[0][2]) {
101 case '\0':
102 ++(*argv); --(*argc);
103 if ((*argc) < 1) break;
104 zxid_parse_conf(cf, (*argv)[0]);
105 continue;
106 case 'h':
107 ++(*argv); --(*argc);
108 if ((*argc) < 1) break;
109 chan = (*argv)[0];
110 continue;
111 case 't':
112 ++(*argv); --(*argc);
113 if ((*argc) < 1) break;
114 ctl = (*argv)[0];
115 continue;
116 }
117 break;
118
119 case 'd':
120 switch ((*argv)[0][2]) {
121 case '\0':
122 ++errmac_debug;
123 if (errmac_debug == 2)
124 strncpy(errmac_instance, "\t\e[43mzxbustailf\e[0m", sizeof(errmac_instance));
125 continue;
126 case 'c':
127 ss = zxid_show_conf(cf);
128 if (zxbus_verbose>1) {
129 fprintf(stdout, "\n======== CONF ========\n%.*s\n^^^^^^^^ CONF ^^^^^^^^\n",ss->len,ss->s);
130 exit(0);
131 }
132 fprintf(stderr, "\n======== CONF ========\n%.*s\n^^^^^^^^ CONF ^^^^^^^^\n",ss->len,ss->s);
133 continue;
134 }
135 break;
136
137 case 'e':
138 switch ((*argv)[0][2]) {
139 case '\0':
140 ++(*argv); --(*argc);
141 if ((*argc) < 1) break;
142 bdy = (*argv)[0];
143 continue;
144 }
145 break;
146
147 case 'i':
148 switch ((*argv)[0][2]) {
149 case '\0':
150 ++(*argv); --(*argc);
151 if (!(*argc)) break;
152 n_iter = atoi((*argv)[0]);
153 continue;
154 case 's':
155 if ((*argv)[0][3]) break;
156 ++(*argv); --(*argc);
157 if (!(*argc)) break;
158 n_send = atoi((*argv)[0]);
159 continue;
160 case 't':
161 if ((*argv)[0][3]) break;
162 ++(*argv); --(*argc);
163 if (!(*argc)) break;
164 n_thr = atoi((*argv)[0]);
165 continue;
166 }
167 break;
168
169 case 'n':
170 switch ((*argv)[0][2]) {
171 case '\0':
172 ++dryrun;
173 continue;
174 }
175 break;
176
177 case 'q':
178 switch ((*argv)[0][2]) {
179 case '\0':
180 zxbus_verbose = 0;
181 continue;
182 }
183 break;
184
185 case 'v':
186 switch ((*argv)[0][2]) {
187 case '\0':
188 ++zxbus_verbose;
189 continue;
190 }
191 break;
192
193 }
194 /* fall thru means unrecognized flag */
195 if (*argc)
196 fprintf(stderr, "Unrecognized flag `%s'\n", (*argv)[0]);
197 help:
198 if (zxbus_verbose>1) {
199 fprintf(stdout, "%s", help);
200 exit(0);
201 }
202 fprintf(stderr, "%s", help);
203 /*fprintf(stderr, "version=0x%06x rel(%s)\n", zxid_version(), zxid_version_str());*/
204 exit(3);
205 }
206 }
207
208
209 #ifndef zxbustailf_main
210 #define zxbustailf_main main
211 #endif
212 extern int zxid_suppress_vpath_warning;
213
214 /*() Audit Bus producer tool */
215
216 /* Called by: */
zxbustailf_main(int argc,char ** argv,char ** env)217 int zxbustailf_main(int argc, char** argv, char** env)
218 {
219 int len,ns,nt,pid;
220 char buf[64];
221 pid_t* kids;
222 strncpy(errmac_instance, "\tzxbustailf", sizeof(errmac_instance));
223 zxbus_verbose = 1;
224 zxid_suppress_vpath_warning = 1;
225 cf = zxid_new_conf_to_cf(0);
226 opt(&argc, &argv, &env);
227
228 if (n_thr > 1) {
229 /* Fork test clients in great (specified) numbers. */
230 kids = ZX_ALLOC(cf->ctx, n_thr * sizeof(pid_t));
231
232 for (nt = 0; nt < n_thr; ++nt) {
233 if ((kids[nt] = fork()) == -1) { perror("fork"); exit(1); }
234 if (!kids[nt])
235 goto kid;
236 }
237 D("All forked (%d), now waiting...", n_thr);
238 for (nt = 0; nt < n_thr; ++nt) {
239 if ((pid = wait(&len))==-1) { perror("wait"); exit(1); }
240 if (WIFEXITED(len)) {
241 if (WEXITSTATUS(len)) {
242 ERR("wait(%d): Process exited with nozero status %x.", pid, WEXITSTATUS(len));
243 }
244 } else {
245 ERR("wait(%d): Process died abnormally %x.", pid, len);
246 }
247 }
248 D("All waited (%d), done.", n_thr);
249 return 0;
250 } else {
251 nt = -1;
252 }
253 kid:
254 D("Kid (%d/%d)", nt, n_thr);
255 for (; n_iter; --n_iter) {
256 if (n_send > 1 || n_iter > 1) {
257 for (ns = n_send; ns; --ns) {
258 len = snprintf(buf, sizeof(buf), "test(%d,%d,%d)", nt, n_iter, ns);
259 D("sending(%.*s) n_send=%d n_iter=%d", len, buf, n_send, n_iter);
260 zxbus_send(cf, chan, len, buf);
261 }
262 } else {
263 if (ctl) {
264 zxbus_send_cmd(cf, "ZXCTL", chan, strlen(ctl), ctl);
265 } else if (bdy) {
266 if (!zxbus_send(cf, chan, strlen(bdy), bdy))
267 return 1;
268 }
269 }
270 /* *** implement actual tail functionality */
271
272 zxbus_close_all(cf);
273 }
274 return 0;
275 }
276
277 /* EOF -- zxbustailf.c */
278