Browse Source

Add --status-file (-0) option. This file keeps latest program status.

Georgi Chorbadzhiyski 7 years ago
parent
commit
2c1a032d69
8 changed files with 109 additions and 41 deletions
  1. 1
    0
      ChangeLog
  2. 1
    0
      README
  3. 3
    0
      data.c
  4. 2
    0
      data.h
  5. 11
    2
      notify-script.example
  6. 60
    35
      notify.c
  7. 19
    0
      tsdecrypt.1
  8. 12
    4
      tsdecrypt.c

+ 1
- 0
ChangeLog View File

@@ -5,6 +5,7 @@ xxxx-xx-xx : Version -next
5 5
    running of several notification scripts in parallel which can lead to
6 6
    races if the scripts are used for logging.
7 7
  * Start passing _INPUT_ADDR and _OUTPUT_ADDR variables to notify script.
8
+ * Add --status-file (-0) option. This file keeps latest program status.
8 9
 
9 10
 2013-09-12 : Version 10.0
10 11
  * Add --ecm-only (-v) option. This allows processing of ECMs but without

+ 1
- 0
README View File

@@ -104,6 +104,7 @@ Main options:
104 104
  -N --notify-program <prg>  | Execute <prg> to report events. Default: empty
105 105
  -9 --notify-wait           | Enable one by one notification delivery.
106 106
                             . Default: not set (async, deliver ASAP)
107
+ -0 --status-file <file>    | Save current program status in file.
107 108
 
108 109
 Input options:
109 110
  -I --input <source>        | Where to read from. File or multicast address.

+ 3
- 0
data.c View File

@@ -150,5 +150,8 @@ void data_free(struct ts *ts) {
150 150
 	// unhappy it is a good idea to free the memory (ONCE!).
151 151
 	FREE(ts->camd.newcamd.crypt_passwd);
152 152
 
153
+	ts->status_file = NULL;
154
+	FREE(ts->status_file_tmp);
155
+
153 156
 	pthread_attr_destroy(&ts->thread_attr);
154 157
 }

+ 2
- 0
data.h View File

@@ -360,6 +360,8 @@ struct ts {
360 360
 	struct notify		*notify;
361 361
 	char				*notify_program;
362 362
 	int					notify_wait;
363
+	char				*status_file;
364
+	char				*status_file_tmp;
363 365
 
364 366
 	unsigned int		input_buffer_time;
365 367
 	LIST				*input_buffer;

+ 11
- 2
notify-script.example View File

@@ -17,7 +17,10 @@ EMAIL_PROGRAM="/usr/sbin/sendmail -t -i"
17 17
 
18 18
 LOG_ENABLED="yes"
19 19
 LOG_DIR="."
20
-LOG_FILE="$LOGDIR/notify.${_IDENT}.notify.log"
20
+LOG_FILE="$LOG_DIR/notify.${_IDENT}.notify.log"
21
+
22
+STATUS_ENABLED="yes"
23
+STATUS_FILE="$LOG_DIR/status.${_IDENT}"
21 24
 
22 25
 # Environmental vars that are set by the calling process (tsdecrypt):
23 26
 #   _TS             Unix timestamp of the event.
@@ -50,7 +53,13 @@ then
50 53
 		"${_IDENT}" \
51 54
 		"${_MESSAGE_ID}" \
52 55
 		"${_MESSAGE_TEXT}" \
53
-		  >> $LOG_DIR/$LOG_FILE
56
+		  >> $LOG_FILE
57
+fi
58
+
59
+if [ "$STATUS_ENABLED" = "yes" ]; then
60
+	# Run tsdecrypt with --notify-wait otherwise the events might get here out of order
61
+	echo "${_IDENT}|${_TS}|${_MESSAGE_ID}|${_MESSAGE_TEXT}|${_INPUT_ADDR}|${_OUTPUT_ADDR}" > $STATUS_FILE.tmp
62
+	mv $STATUS_FILE.tmp $STATUS_FILE
54 63
 fi
55 64
 
56 65
 if [ "$EMAIL_ENABLED" = "yes" ]

+ 60
- 35
notify.c View File

@@ -33,12 +33,13 @@
33 33
 #include "util.h"
34 34
 
35 35
 struct npriv {
36
-	char	ident[512];
36
+	char	ident[128];
37 37
 	char	program[512];
38
-	char	msg_id[512];
39
-	char	text[512];
38
+	char	msg_id[64];
39
+	char	text[256];
40 40
 	char	input[128];
41 41
 	char	output[128];
42
+	time_t	ts;
42 43
 	int		sync;			/* Wait for message to be delivered */
43 44
 };
44 45
 
@@ -56,7 +57,7 @@ static void *do_notify(void *in) {
56 57
 		int e = 0;
57 58
 		unsigned int i, r;
58 59
 		char **env = calloc(32, sizeof(char *));
59
-		if (asprintf(&env[e++], "_TS=%ld"			, time(NULL)) < 0) exit(EXIT_FAILURE);
60
+		if (asprintf(&env[e++], "_TS=%ld"			, shared->ts) < 0) exit(EXIT_FAILURE);
60 61
 		if (asprintf(&env[e++], "_IDENT=%s"			, shared->ident) < 0) exit(EXIT_FAILURE);
61 62
 		if (asprintf(&env[e++], "_INPUT_ADDR=%s"	, shared->input) < 0) exit(EXIT_FAILURE);
62 63
 		if (asprintf(&env[e++], "_OUTPUT_ADDR=%s"	, shared->output) < 0) exit(EXIT_FAILURE);
@@ -117,45 +118,39 @@ static void *notify_thread(void *data) {
117 118
 
118 119
 struct notify *notify_alloc(struct ts *ts) {
119 120
 	unsigned int i;
120
-	if (!ts->ident || !ts->notify_program)
121
-		return NULL;
122 121
 	struct notify *n = calloc(1, sizeof(struct notify));
123
-	n->notifications = queue_new();
124
-	strncpy(n->ident, ts->ident, sizeof(n->ident) - 1);
125
-	n->ident[sizeof(n->ident) - 1] = '\0';
122
+	if (!n)
123
+		return NULL;
124
+
125
+	if (!ts->ident)
126
+		return NULL;
127
+
128
+	// Init notify members
129
+	strncpy(n->ident, ts->ident, sizeof(n->ident) - 2);
126 130
 	for (i=0; i<strlen(n->ident); i++) {
127 131
 		if (n->ident[i] == '/')
128 132
 			n->ident[i] = '-';
129 133
 	}
130
-	strncpy(n->program, ts->notify_program, sizeof(n->program) - 1);
131
-	n->program[sizeof(n->program) - 1] = '\0';
132
-	pthread_create(&n->thread, &ts->thread_attr , &notify_thread, n);
134
+
135
+	// We'll need the notify thread and the queue only if 'notify_program' is set
136
+	if (ts->ident && ts->notify_program) {
137
+		strncpy(n->program, ts->notify_program, sizeof(n->program) - 2);
138
+		n->notifications = queue_new();
139
+		pthread_create(&n->thread, &ts->thread_attr , &notify_thread, n);
140
+	}
133 141
 	return n;
134 142
 }
135 143
 
136
-static void npriv_init_defaults(struct notify *n, struct npriv *np) {
137
-	strncpy(np->program, n->program, sizeof(np->program) - 1);
138
-	strncpy(np->ident, n->ident, sizeof(np->ident) - 1);
139
-}
140
-
141
-static void notify_func(struct ts *ts, int sync_msg, char *msg_id, char *msg_text) {
142
-	struct npriv *np;
143
-
144
-	if (!ts->notify)
145
-		return;
146
-
147
-	np = calloc(1, sizeof(struct npriv));
148
-
144
+static void npriv_struct_fill(struct npriv *np, struct ts *ts, int sync_msg, char *msg_id, char *msg_text) {
149 145
 	np->sync = sync_msg;
150 146
 	if (ts->notify_wait)
151 147
 		np->sync = 1;
152
-	npriv_init_defaults(ts->notify, np);
148
+	np->ts = time(NULL);
153 149
 
154
-	strncpy(np->msg_id, msg_id, sizeof(np->ident) - 1);
155
-	np->msg_id[sizeof(np->ident) - 1] = 0;
156
-
157
-	strncpy(np->text, msg_text, sizeof(np->text) - 1);
158
-	np->text[sizeof(np->text) - 1] = 0;
150
+	strncpy(np->program, ts->notify->program, sizeof(np->program) - 2);
151
+	strncpy(np->ident, ts->notify->ident, sizeof(np->ident) - 2);
152
+	strncpy(np->msg_id, msg_id, sizeof(np->msg_id) - 2);
153
+	strncpy(np->text, msg_text, sizeof(np->text) - 2);
159 154
 
160 155
 	if (ts->input.type == NET_IO) {
161 156
 		snprintf(np->input, sizeof(np->input), "%s:%s", ts->input.hostname, ts->input.service);
@@ -171,8 +166,36 @@ static void notify_func(struct ts *ts, int sync_msg, char *msg_id, char *msg_tex
171 166
 	} else {
172 167
 		snprintf(np->output, sizeof(np->output), "DISABLED");
173 168
 	}
169
+}
174 170
 
175
-	queue_add(ts->notify->notifications, np);
171
+static void notify_func(struct ts *ts, int sync_msg, char *msg_id, char *msg_text) {
172
+	struct npriv np_local;
173
+	int np_local_inited = 0;
174
+
175
+	if (ts->status_file) {
176
+		memset(&np_local, 0, sizeof(np_local));
177
+		npriv_struct_fill(&np_local, ts, sync_msg, msg_id, msg_text);
178
+		np_local_inited = 1;
179
+		// Write status file
180
+		FILE *status_file = fopen(ts->status_file_tmp, "w");
181
+		if (status_file) {
182
+			fprintf(status_file, "%s|%ld|%s|%s|%s|%s\n", np_local.ident, np_local.ts, np_local.msg_id, np_local.text, np_local.input, np_local.output);
183
+			rename(ts->status_file_tmp, ts->status_file);
184
+			fclose(status_file);
185
+		}
186
+	}
187
+
188
+	if (ts->notify->notifications) {
189
+		struct npriv *np = calloc(1, sizeof(struct npriv));
190
+		if (np) {
191
+			if (np_local_inited) {
192
+				memcpy(np, &np_local, sizeof(*np));
193
+			} else {
194
+				npriv_struct_fill(np, ts, sync_msg, msg_id, msg_text);
195
+			}
196
+			queue_add(ts->notify->notifications, np);
197
+		}
198
+	}
176 199
 }
177 200
 
178 201
 #define MAX_MSG_TEXT 256
@@ -204,9 +227,11 @@ void notify_sync(struct ts *ts, char *msg_id, char *text_fmt, ...) {
204 227
 void notify_free(struct notify **pn) {
205 228
 	struct notify *n = *pn;
206 229
 	if (n) {
207
-		queue_add(n->notifications, NULL);
208
-		pthread_join(n->thread, NULL);
209
-		queue_free(&n->notifications);
230
+		if (n->notifications) {
231
+			queue_add(n->notifications, NULL);
232
+			pthread_join(n->thread, NULL);
233
+			queue_free(&n->notifications);
234
+		}
210 235
 		FREE(*pn);
211 236
 	}
212 237
 }

+ 19
- 0
tsdecrypt.1 View File

@@ -43,6 +43,25 @@ Setting this option makes sure that you'll have only one notify script
43 43
 running. \fB*NOTE*\fR if you set this option make sure that notification
44 44
 script does not take a lot of time to run or you'll run into problems.
45 45
 .TP
46
+\fB\-0\fR, \fB\-\-status-file\fR <filename>
47
+Write latest notification in file named <filename>. You can monitor this
48
+file to know what is the current tsdecrypt status.
49
+
50
+The file contains the following fields (see \fBEVENTS\fR bellow) separated
51
+by the pipe symbol (|).
52
+
53
+  _IDENT
54
+  _TS
55
+  _MESSAGE_ID
56
+  _MESSAGE_TEXT
57
+  _INPUT_ADDR
58
+  _OUTPUT_ADDR
59
+
60
+See \fBEVENTS\fR section for detailed description of the events.
61
+
62
+See \fBnotify-script.example\fR for example how to implement
63
+\fB--status-file\fR by using external notification script.
64
+.TP
46 65
 \fB\-S\fR, \fB\-\-syslog\fR
47 66
 Write log messages to local syslog.
48 67
 .TP

+ 12
- 4
tsdecrypt.c View File

@@ -77,9 +77,9 @@ static void LOG_func(const char *msg) {
77 77
 		LOG(msg);
78 78
 }
79 79
 
80
-static const char short_options[] = "i:d:N:9Sl:L:F:I:1:RzM:T:W:O:o:t:rk:g:upwxyc:C:Y:Q:A:s:U:P:B:46eZ:Ef:a:X:vqH:G:2:KJ:D:jbhVn:m:";
80
+static const char short_options[] = "i:d:N:90:Sl:L:F:I:1:RzM:T:W:O:o:t:rk:g:upwxyc:C:Y:Q:A:s:U:P:B:46eZ:Ef:a:X:vqH:G:2:KJ:D:jbhVn:m:";
81 81
 
82
-// Unused short options: 035789
82
+// Unused short options: 3578
83 83
 static const struct option long_options[] = {
84 84
 	{ "ident",				required_argument, NULL, 'i' },
85 85
 	{ "daemon",				required_argument, NULL, 'd' },
@@ -89,6 +89,7 @@ static const struct option long_options[] = {
89 89
 	{ "log-file",			required_argument, NULL, 'F' },
90 90
 	{ "notify-program",		required_argument, NULL, 'N' },
91 91
 	{ "notify-wait",		no_argument,       NULL, '9' },
92
+	{ "status-file",		required_argument, NULL, '0' },
92 93
 
93 94
 	{ "input",				required_argument, NULL, 'I' },
94 95
 	{ "input-source",		required_argument, NULL, '1' },
@@ -163,6 +164,7 @@ static void show_help(struct ts *ts) {
163 164
 	printf(" -N --notify-program <prg>  | Execute <prg> to report events. Default: empty\n");
164 165
 	printf(" -9 --notify-wait           | Enable one by one notification delivery.\n");
165 166
 	printf("                            . Default: not set (async, deliver ASAP)\n");
167
+	printf(" -0 --status-file <file>    | Save current program status in file.\n");
166 168
 	printf("\n");
167 169
 	printf("Input options:\n");
168 170
 	printf(" -I --input <source>        | Where to read from. File or multicast address.\n");
@@ -320,6 +322,11 @@ static void parse_options(struct ts *ts, int argc, char **argv) {
320 322
 			case '9': // --notify-wait
321 323
 				ts->notify_wait = !ts->notify_wait;
322 324
 				break;
325
+			case '0': // --status-file
326
+				ts->status_file = optarg;
327
+				ts->status_file_tmp = calloc(1, strlen(optarg) + 16);
328
+				snprintf(ts->status_file_tmp, strlen(optarg) + 16, "%s.tmp", optarg);
329
+				break;
323 330
 			case 'S': // --syslog
324 331
 				ts->syslog_active = 1;
325 332
 				ts->syslog_remote = 0;
@@ -612,7 +619,7 @@ static void parse_options(struct ts *ts, int argc, char **argv) {
612 619
 		}
613 620
 	}
614 621
 	if (!ts->ident) {
615
-		if (ts->syslog_active || ts->notify_program)
622
+		if (ts->syslog_active || ts->notify_program || ts->status_file)
616 623
 			ident_err = 1;
617 624
 	}
618 625
 
@@ -654,7 +661,6 @@ static void parse_options(struct ts *ts, int argc, char **argv) {
654 661
 	}
655 662
 
656 663
 	if (ident_err || ca_err || server_err || input_addr_err || output_addr_err || ts->input.type == WTF_IO || ts->output.type == WTF_IO) {
657
-		show_help(ts);
658 664
 		if (ident_err)
659 665
 			fprintf(stderr, "ERROR: Ident is not set, please use --ident option.\n");
660 666
 		if (ca_err)
@@ -688,6 +694,8 @@ static void parse_options(struct ts *ts, int argc, char **argv) {
688 694
 		ts_LOGf("Ident      : %s\n", ts->ident);
689 695
 	if (ts->notify_program)
690 696
 		ts_LOGf("Notify prg : %s (%s)\n", ts->notify_program, ts->notify_wait ? "sync" : "async");
697
+	if (ts->status_file)
698
+		ts_LOGf("Status file: %s\n", ts->status_file);
691 699
 	if (ts->pidfile)
692 700
 		ts_LOGf("Daemonize  : %s pid file.\n", ts->pidfile);
693 701
 	if (ts->syslog_active) {

Loading…
Cancel
Save