aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Christian Hesse <mail@eworm.de>2015-05-19 15:57:22 +0200
committerGravatar Christian Hesse <mail@eworm.de>2015-05-19 15:57:22 +0200
commitd187bd3b4805dcb3f9e1d6143ac1cd0531009868 (patch)
treef6ab52824b9f7543fc88452f408a51795fce9fcd
parent2e86d643dcae1edafa72c9ed1bca02bc85f6148d (diff)
downloadjournal-notify-d187bd3b4805dcb3f9e1d6143ac1cd0531009868.tar.gz
journal-notify-d187bd3b4805dcb3f9e1d6143ac1cd0531009868.tar.zst
add support for executing external commands
close #1
-rw-r--r--Makefile2
-rw-r--r--README.md12
-rwxr-xr-xexecute/echo.sh28
-rwxr-xr-xexecute/mail.sh26
-rw-r--r--journal-notify.c105
-rw-r--r--journal-notify.h11
6 files changed, 160 insertions, 24 deletions
diff --git a/Makefile b/Makefile
index b3b34ef..9230401 100644
--- a/Makefile
+++ b/Makefile
@@ -32,6 +32,8 @@ install-bin: journal-notify
$(INSTALL) -D -m0755 examples/journal-notify-crit-alert-emerg.desktop $(DESTDIR)/usr/share/journal-notify/examples/journal-notify-crit-alert-emerg.desktop
$(INSTALL) -D -m0755 examples/journal-notify-dhcpd.desktop $(DESTDIR)/usr/share/journal-notify/examples/journal-notify-dhcpd.desktop
$(INSTALL) -D -m0755 examples/journal-notify-sshd.desktop $(DESTDIR)/usr/share/journal-notify/examples/journal-notify-sshd.desktop
+ $(INSTALL) -D -m0755 execute/echo.sh $(DESTDIR)/usr/share/journal-notify/execute/echo.sh
+ $(INSTALL) -D -m0755 execute/mail.sh $(DESTDIR)/usr/share/journal-notify/execute/mail.sh
install-doc: README.html
$(INSTALL) -D -m0644 README.md $(DESTDIR)/usr/share/doc/journal-notify/README.md
diff --git a/README.md b/README.md
index 3c4f4d1..52b97a7 100644
--- a/README.md
+++ b/README.md
@@ -61,16 +61,26 @@ Be warned: This can flood your disktop with notifications.
* *-r REGEX*: This add a regular expression match for the message field.
* *-t SECONDS*: seconds to show the notification, 0 is forever
* *-v*: verbose output, can be specified multiple times
+* *-x EXECUTABLE*: execute EXECUTABLE
+* *-X EXECUTABLE*: execute EXECUTABLE, do not show notification
The screenshot shown above resulted from this command:
> journal-notify -m SYSLOG_IDENTIFIER=sshd -e -r "^(error:|Accepted)"
-i security-high
+The command specified by `-x` is called with three options. Make sure
+your executable understands these options:
+
+* *-i*: syslog identifier
+* *-p*: priority
+* *-m*: message
+
Additionally example desktop files are installed to
`/usr/share/journal-notify/examples`. You should copy them to
`~/.config/autostart/` to enable autostart or create your own desktop files
-there.
+there. Example execute scripts are installed to
+`/usr/share/journal-notify/execute/`.
### Upstream
diff --git a/execute/echo.sh b/execute/echo.sh
new file mode 100755
index 0000000..15ca215
--- /dev/null
+++ b/execute/echo.sh
@@ -0,0 +1,28 @@
+#!/bin/sh
+#
+# (C) 2015 by Christian Hesse <mail@eworm.de>
+#
+# This software may be used and distributed according to the terms
+# of the GNU General Public License, incorporated herein by reference.
+
+while getopts "i:p:m:" opt; do
+ case ${opt} in
+ i)
+ IDENTIFIER="${OPTARG}"
+ ;;
+ p)
+ PRIORITY="${OPTARG}"
+ ;;
+ m)
+ MESSAGE="${OPTARG}"
+ ;;
+ esac
+done
+
+echo "IDENTIFIER: ${IDENTIFIER}"
+echo "PRIORITY: ${PRIORITY}"
+echo "MESSAGE: ${MESSAGE}"
+
+exit 0
+
+# vim: set syntax=sh:
diff --git a/execute/mail.sh b/execute/mail.sh
new file mode 100755
index 0000000..2d757db
--- /dev/null
+++ b/execute/mail.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+#
+# (C) 2015 by Christian Hesse <mail@eworm.de>
+#
+# This software may be used and distributed according to the terms
+# of the GNU General Public License, incorporated herein by reference.
+
+while getopts "i:p:m:" opt; do
+ case ${opt} in
+ i)
+ IDENTIFIER="${OPTARG}"
+ ;;
+ p)
+ PRIORITY="${OPTARG}"
+ ;;
+ m)
+ MESSAGE="${OPTARG}"
+ ;;
+ esac
+done
+
+mail -s "[${PRIORITY}] ${IDENTIFIER}" mail@example.com <<< "${MESSAGE}"
+
+exit 0
+
+# vim: set syntax=sh:
diff --git a/journal-notify.c b/journal-notify.c
index 73af0f5..8f6e0b1 100644
--- a/journal-notify.c
+++ b/journal-notify.c
@@ -9,7 +9,7 @@
const char * program = NULL;
-const static char optstring[] = "aehi:m:nor:t:v";
+const static char optstring[] = "aehi:m:nor:t:vx:X:";
const static struct option options_long[] = {
/* name has_arg flag val */
{ "and", no_argument, NULL, 'a' },
@@ -22,6 +22,8 @@ const static struct option options_long[] = {
{ "regex", required_argument, NULL, 'r' },
{ "timeout", required_argument, NULL, 't' },
{ "verbose", no_argument, NULL, 'v' },
+ { "execute", required_argument, NULL, 'x' },
+ { "execute-only", required_argument, NULL, 'X' },
{ 0, 0, 0, 0 }
};
@@ -102,9 +104,15 @@ int main(int argc, char **argv) {
char * identifier, * message;
uint8_t priority;
- const char * icon = DEFAULTICON;
+ const char * priorityname,
+ * icon = DEFAULTICON;
int timeout = -1;
+ uint8_t executeonly = 0;
+ char * execute = NULL;
+ pid_t child_pid, wpid;
+ int status;
+
program = argv[0];
/* get command line options - part I
@@ -210,13 +218,23 @@ int main(int argc, char **argv) {
printf("Notifications will be displayed for %d seconds.\n", timeout);
break;
+ case 'X':
+ executeonly = 1;
+ case 'x':
+ execute = optarg;
+ if (verbose > 1)
+ printf("Command used for execution: %s\n", execute);
+
+ break;
}
}
- if (notify_init(program) == FALSE) {
- fprintf(stderr, "Failed to initialize notify.\n");
- rc = EXIT_FAILURE;
- goto out30;
+ if (executeonly == 0) {
+ if (notify_init(program) == FALSE) {
+ fprintf(stderr, "Failed to initialize notify.\n");
+ rc = EXIT_FAILURE;
+ goto out30;
+ }
}
while (1) {
@@ -266,29 +284,69 @@ int main(int argc, char **argv) {
continue;
}
priority = atoi(data + 9);
+ priorityname = priorities[priority];
if (verbose > 2)
printf("Received message from journal: %s\n", message);
- /* show notification */
if (have_regex == 0 || regexec(&regex, message, 0, NULL, 0) == 0) {
- for (i = 0; i < 3; i++) {
- if (verbose > 0)
- printf("Showing notification: %s: %s\n", identifier, message);
-
- if ((rc = notify(identifier, message, priority, icon, timeout)) == 0)
- break;
-
- fprintf(stderr, "Failed to show notification, reinitializing libnotify.\n");
- notify_uninit();
- usleep(500 * 1000);
- if (notify_init(program) == FALSE) {
- fprintf(stderr, "Failed to initialize notify.\n");
- rc = EXIT_FAILURE;
+ /* show notification */
+ if (executeonly == 0) {
+ for (i = 0; i < 3; i++) {
+ if (verbose > 0)
+ printf("Showing notification: %s: %s\n", identifier, message);
+
+ if ((rc = notify(identifier, message, priority, icon, timeout)) == 0)
+ break;
+
+ fprintf(stderr, "Failed to show notification, reinitializing libnotify.\n");
+ notify_uninit();
+ usleep(500 * 1000);
+ if (notify_init(program) == FALSE) {
+ fprintf(stderr, "Failed to initialize notify.\n");
+ rc = EXIT_FAILURE;
+ }
+ }
+ if (rc != 0)
+ goto out40;
+ }
+
+ /* execute command */
+ if (execute) {
+ if (verbose > 1)
+ printf("Executing: %s -i %s -p %s -m %s\n",
+ execute, identifier, priorityname, message);
+
+ if ((child_pid = fork()) < 0) {
+ fprintf(stderr, "fork() failed\n");
+ } else if (child_pid == 0) { /* This is the child */
+ rc = execlp(execute, execute, "-i", identifier,
+ "-p", priorityname, "-m", message, NULL);
+ /* execlp() should replace the process, so anything failed */
+ fprintf(stderr, "Failed to execute '%s': %s\n", execute, strerror(-rc));
+ goto out10;
+ } else { /* This is the parent */
+ do {
+ if ((wpid = waitpid(child_pid, &status, WUNTRACED|WCONTINUED)) < 0) {
+ perror("waitpid");
+ goto out40;
+ }
+
+ if (WIFEXITED(status)) {
+ if (WEXITSTATUS(status) > 0 || verbose > 1)
+ printf("child exited, status %d\n", WEXITSTATUS(status));
+ } else if (WIFSIGNALED(status)) {
+ printf("child killed (signal %d)\n", WTERMSIG(status));
+ } else if (WIFSTOPPED(status)) {
+ printf("child stopped (signal %d)\n", WSTOPSIG(status));
+ } else if (WIFCONTINUED(status)) {
+ printf("child continued\n");
+ } else {
+ printf("Unexpected status (0x%x)\n", status);
+ }
+ } while (!WIFEXITED(status) && !WIFSIGNALED(status));
}
}
- if (rc != 0)
- goto out40;
}
free(identifier);
@@ -298,7 +356,8 @@ int main(int argc, char **argv) {
rc = EXIT_SUCCESS;
out40:
- notify_uninit();
+ if (executeonly == 0)
+ notify_uninit();
out30:
if (have_regex > 0)
diff --git a/journal-notify.h b/journal-notify.h
index ee18b7b..0dd2962 100644
--- a/journal-notify.h
+++ b/journal-notify.h
@@ -16,6 +16,7 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <sys/wait.h>
#include <systemd/sd-journal.h>
@@ -25,6 +26,16 @@
#define DEFAULTICON "dialog-information"
+const char * priorities[] = {
+ "EMERG", /* 0 */
+ "ALERT",
+ "CRIT",
+ "ERR",
+ "WARNING",
+ "NOTICE",
+ "INFO",
+ "DEBUG" /* 7 */};
+
/*** notify ***/
int notify(const char * identifier, const char * message, uint8_t priority,
const char * icon, int timeout);