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