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
    running of several notification scripts in parallel which can lead to
5
    running of several notification scripts in parallel which can lead to
6
    races if the scripts are used for logging.
6
    races if the scripts are used for logging.
7
  * Start passing _INPUT_ADDR and _OUTPUT_ADDR variables to notify script.
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
 2013-09-12 : Version 10.0
10
 2013-09-12 : Version 10.0
10
  * Add --ecm-only (-v) option. This allows processing of ECMs but without
11
  * Add --ecm-only (-v) option. This allows processing of ECMs but without

+ 1
- 0
README View File

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

+ 3
- 0
data.c View File

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

+ 2
- 0
data.h View File

360
 	struct notify		*notify;
360
 	struct notify		*notify;
361
 	char				*notify_program;
361
 	char				*notify_program;
362
 	int					notify_wait;
362
 	int					notify_wait;
363
+	char				*status_file;
364
+	char				*status_file_tmp;
363
 
365
 
364
 	unsigned int		input_buffer_time;
366
 	unsigned int		input_buffer_time;
365
 	LIST				*input_buffer;
367
 	LIST				*input_buffer;

+ 11
- 2
notify-script.example View File

17
 
17
 
18
 LOG_ENABLED="yes"
18
 LOG_ENABLED="yes"
19
 LOG_DIR="."
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
 # Environmental vars that are set by the calling process (tsdecrypt):
25
 # Environmental vars that are set by the calling process (tsdecrypt):
23
 #   _TS             Unix timestamp of the event.
26
 #   _TS             Unix timestamp of the event.
50
 		"${_IDENT}" \
53
 		"${_IDENT}" \
51
 		"${_MESSAGE_ID}" \
54
 		"${_MESSAGE_ID}" \
52
 		"${_MESSAGE_TEXT}" \
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
 fi
63
 fi
55
 
64
 
56
 if [ "$EMAIL_ENABLED" = "yes" ]
65
 if [ "$EMAIL_ENABLED" = "yes" ]

+ 60
- 35
notify.c View File

33
 #include "util.h"
33
 #include "util.h"
34
 
34
 
35
 struct npriv {
35
 struct npriv {
36
-	char	ident[512];
36
+	char	ident[128];
37
 	char	program[512];
37
 	char	program[512];
38
-	char	msg_id[512];
39
-	char	text[512];
38
+	char	msg_id[64];
39
+	char	text[256];
40
 	char	input[128];
40
 	char	input[128];
41
 	char	output[128];
41
 	char	output[128];
42
+	time_t	ts;
42
 	int		sync;			/* Wait for message to be delivered */
43
 	int		sync;			/* Wait for message to be delivered */
43
 };
44
 };
44
 
45
 
56
 		int e = 0;
57
 		int e = 0;
57
 		unsigned int i, r;
58
 		unsigned int i, r;
58
 		char **env = calloc(32, sizeof(char *));
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
 		if (asprintf(&env[e++], "_IDENT=%s"			, shared->ident) < 0) exit(EXIT_FAILURE);
61
 		if (asprintf(&env[e++], "_IDENT=%s"			, shared->ident) < 0) exit(EXIT_FAILURE);
61
 		if (asprintf(&env[e++], "_INPUT_ADDR=%s"	, shared->input) < 0) exit(EXIT_FAILURE);
62
 		if (asprintf(&env[e++], "_INPUT_ADDR=%s"	, shared->input) < 0) exit(EXIT_FAILURE);
62
 		if (asprintf(&env[e++], "_OUTPUT_ADDR=%s"	, shared->output) < 0) exit(EXIT_FAILURE);
63
 		if (asprintf(&env[e++], "_OUTPUT_ADDR=%s"	, shared->output) < 0) exit(EXIT_FAILURE);
117
 
118
 
118
 struct notify *notify_alloc(struct ts *ts) {
119
 struct notify *notify_alloc(struct ts *ts) {
119
 	unsigned int i;
120
 	unsigned int i;
120
-	if (!ts->ident || !ts->notify_program)
121
-		return NULL;
122
 	struct notify *n = calloc(1, sizeof(struct notify));
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
 	for (i=0; i<strlen(n->ident); i++) {
130
 	for (i=0; i<strlen(n->ident); i++) {
127
 		if (n->ident[i] == '/')
131
 		if (n->ident[i] == '/')
128
 			n->ident[i] = '-';
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
 	return n;
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
 	np->sync = sync_msg;
145
 	np->sync = sync_msg;
150
 	if (ts->notify_wait)
146
 	if (ts->notify_wait)
151
 		np->sync = 1;
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
 	if (ts->input.type == NET_IO) {
155
 	if (ts->input.type == NET_IO) {
161
 		snprintf(np->input, sizeof(np->input), "%s:%s", ts->input.hostname, ts->input.service);
156
 		snprintf(np->input, sizeof(np->input), "%s:%s", ts->input.hostname, ts->input.service);
171
 	} else {
166
 	} else {
172
 		snprintf(np->output, sizeof(np->output), "DISABLED");
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
 #define MAX_MSG_TEXT 256
201
 #define MAX_MSG_TEXT 256
204
 void notify_free(struct notify **pn) {
227
 void notify_free(struct notify **pn) {
205
 	struct notify *n = *pn;
228
 	struct notify *n = *pn;
206
 	if (n) {
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
 		FREE(*pn);
235
 		FREE(*pn);
211
 	}
236
 	}
212
 }
237
 }

+ 19
- 0
tsdecrypt.1 View File

43
 running. \fB*NOTE*\fR if you set this option make sure that notification
43
 running. \fB*NOTE*\fR if you set this option make sure that notification
44
 script does not take a lot of time to run or you'll run into problems.
44
 script does not take a lot of time to run or you'll run into problems.
45
 .TP
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
 \fB\-S\fR, \fB\-\-syslog\fR
65
 \fB\-S\fR, \fB\-\-syslog\fR
47
 Write log messages to local syslog.
66
 Write log messages to local syslog.
48
 .TP
67
 .TP

+ 12
- 4
tsdecrypt.c View File

77
 		LOG(msg);
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
 static const struct option long_options[] = {
83
 static const struct option long_options[] = {
84
 	{ "ident",				required_argument, NULL, 'i' },
84
 	{ "ident",				required_argument, NULL, 'i' },
85
 	{ "daemon",				required_argument, NULL, 'd' },
85
 	{ "daemon",				required_argument, NULL, 'd' },
89
 	{ "log-file",			required_argument, NULL, 'F' },
89
 	{ "log-file",			required_argument, NULL, 'F' },
90
 	{ "notify-program",		required_argument, NULL, 'N' },
90
 	{ "notify-program",		required_argument, NULL, 'N' },
91
 	{ "notify-wait",		no_argument,       NULL, '9' },
91
 	{ "notify-wait",		no_argument,       NULL, '9' },
92
+	{ "status-file",		required_argument, NULL, '0' },
92
 
93
 
93
 	{ "input",				required_argument, NULL, 'I' },
94
 	{ "input",				required_argument, NULL, 'I' },
94
 	{ "input-source",		required_argument, NULL, '1' },
95
 	{ "input-source",		required_argument, NULL, '1' },
163
 	printf(" -N --notify-program <prg>  | Execute <prg> to report events. Default: empty\n");
164
 	printf(" -N --notify-program <prg>  | Execute <prg> to report events. Default: empty\n");
164
 	printf(" -9 --notify-wait           | Enable one by one notification delivery.\n");
165
 	printf(" -9 --notify-wait           | Enable one by one notification delivery.\n");
165
 	printf("                            . Default: not set (async, deliver ASAP)\n");
166
 	printf("                            . Default: not set (async, deliver ASAP)\n");
167
+	printf(" -0 --status-file <file>    | Save current program status in file.\n");
166
 	printf("\n");
168
 	printf("\n");
167
 	printf("Input options:\n");
169
 	printf("Input options:\n");
168
 	printf(" -I --input <source>        | Where to read from. File or multicast address.\n");
170
 	printf(" -I --input <source>        | Where to read from. File or multicast address.\n");
320
 			case '9': // --notify-wait
322
 			case '9': // --notify-wait
321
 				ts->notify_wait = !ts->notify_wait;
323
 				ts->notify_wait = !ts->notify_wait;
322
 				break;
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
 			case 'S': // --syslog
330
 			case 'S': // --syslog
324
 				ts->syslog_active = 1;
331
 				ts->syslog_active = 1;
325
 				ts->syslog_remote = 0;
332
 				ts->syslog_remote = 0;
612
 		}
619
 		}
613
 	}
620
 	}
614
 	if (!ts->ident) {
621
 	if (!ts->ident) {
615
-		if (ts->syslog_active || ts->notify_program)
622
+		if (ts->syslog_active || ts->notify_program || ts->status_file)
616
 			ident_err = 1;
623
 			ident_err = 1;
617
 	}
624
 	}
618
 
625
 
654
 	}
661
 	}
655
 
662
 
656
 	if (ident_err || ca_err || server_err || input_addr_err || output_addr_err || ts->input.type == WTF_IO || ts->output.type == WTF_IO) {
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
 		if (ident_err)
664
 		if (ident_err)
659
 			fprintf(stderr, "ERROR: Ident is not set, please use --ident option.\n");
665
 			fprintf(stderr, "ERROR: Ident is not set, please use --ident option.\n");
660
 		if (ca_err)
666
 		if (ca_err)
688
 		ts_LOGf("Ident      : %s\n", ts->ident);
694
 		ts_LOGf("Ident      : %s\n", ts->ident);
689
 	if (ts->notify_program)
695
 	if (ts->notify_program)
690
 		ts_LOGf("Notify prg : %s (%s)\n", ts->notify_program, ts->notify_wait ? "sync" : "async");
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
 	if (ts->pidfile)
699
 	if (ts->pidfile)
692
 		ts_LOGf("Daemonize  : %s pid file.\n", ts->pidfile);
700
 		ts_LOGf("Daemonize  : %s pid file.\n", ts->pidfile);
693
 	if (ts->syslog_active) {
701
 	if (ts->syslog_active) {

Loading…
Cancel
Save