diff --git a/alertik.c b/alertik.c index 6c20ac9..5247194 100644 --- a/alertik.c +++ b/alertik.c @@ -5,7 +5,6 @@ #define _POSIX_C_SOURCE 200809L #include -#include #include #include "alertik.h" @@ -15,35 +14,32 @@ #include "notifiers.h" #include "syslog.h" -/* Misc. */ -#define LAST_SENT_THRESHOLD_SECS 10 /* Minimum time (in secs) between two */ -time_t time_last_sent_notify; /* notifications. */ - +/* + * Alertik + */ static void *handle_messages(void *p) { ((void)p); - size_t i; + + int handled = 0; struct log_event ev = {0}; while (syslog_pop_msg_from_fifo(&ev) >= 0) { print_log_event(&ev); - if ((time(NULL) - time_last_sent_notify) <= LAST_SENT_THRESHOLD_SECS) { + if (!is_within_notify_threshold()) { log_msg("ignoring, reason: too many notifications!\n"); continue; } - /* Check if it belongs to any of our desired events. */ - for (i = 0; i < NUM_EVENTS; i++) { - if (strstr(ev.msg, handlers[i].str)) { - handlers[i].hnd(&ev); - break; - } - } + handled = process_static_event(&ev); + handled += process_environment_event(&ev); - if (i == NUM_EVENTS) - log_msg("> No match!\n"); + if (handled) + update_notify_last_sent(); + else + log_msg("> Not handled!\n"); } return NULL; } @@ -53,6 +49,10 @@ int main(void) pthread_t handler; int fd; +/* TODO: remove setup_notifiers().. + * think about env vars for the static events too, like enable/disable + */ + log_init(); setup_notifiers(); init_environment_events(); diff --git a/alertik.h b/alertik.h index 8f2aa88..9575df6 100644 --- a/alertik.h +++ b/alertik.h @@ -10,7 +10,6 @@ #define MIN(a,b) (((a)<(b))?(a):(b)) - extern time_t time_last_sent_notify; extern char *get_formatted_time(time_t time, char *time_str); extern void log_msg(const char *fmt, ...); extern int send_telegram_notification(const char *msg); diff --git a/env_events.c b/env_events.c index d530734..616bffc 100644 --- a/env_events.c +++ b/env_events.c @@ -11,6 +11,7 @@ #include #include "log.h" +#include "events.h" #include "env_events.h" #include "alertik.h" #include "notifiers.h" @@ -20,6 +21,7 @@ static const char *const match_types[] = {"substr", "regex"}; /* Environment events list. */ +static int num_env_events; struct env_event env_events[MAX_ENV_EVENTS] = {0}; /** @@ -80,30 +82,89 @@ get_event_idx(int ev_num, char *str, const char *const *str_list, int size) panic("String parameter (%s) invalid for %s\n", env, str); } +/**/ +static int handle_regex(struct log_event *ev, int idx_env) +{ + ((void)ev); + ((void)idx_env); + return 0; +} +/**/ +static int handle_substr(struct log_event *ev, int idx_env) +{ + int notif_idx; + char time_str[32] = {0}; + struct env_event *env_ev; + char notification_message[2048] = {0}; + env_ev = &env_events[idx_env]; + notif_idx = env_ev->ev_notifier_idx; + if (!strstr(ev->msg, env_ev->ev_match_str)) + return 0; + log_msg("> Environment event detected!\n"); + log_msg("> type: substr, match: (%s), notifier: %s\n", + env_ev->ev_match_str, notifiers_str[notif_idx]); + + /* Format the message. */ + snprintf( + notification_message, + sizeof notification_message - 1, + "%s, at: %s", + env_ev->ev_mask_msg, + get_formatted_time(ev->timestamp, time_str) + ); + + if (notifiers[notif_idx].send_notification(notification_message) < 0) + log_msg("unable to send the notification through %s\n", + notifiers_str[notif_idx]); + + return 1; +} + +/** + * @brief Given an environment-variable event, checks if it + * belongs to one of the registered events and then, handle + * it. + * + * @param ev Event to be processed. + * + * @return Returns the amount of matches, 0 if none (not handled). + */ +int process_environment_event(struct log_event *ev) +{ + int i; + int handled; + + for (i = 0, handled = 0; i < num_env_events; i++) { + if (env_events[i].ev_match_type == EVNT_SUBSTR) + handled += handle_substr(ev, i); + else + handled += handle_regex(ev, i); + } + return handled; +} /**/ int init_environment_events(void) { char *tmp; - int events; - tmp = getenv("ENV_EVENTS"); - if (!tmp || (str2int(&events, tmp) < 0) || events <= 0) { + + if (!tmp || (str2int(&num_env_events, tmp) < 0) || num_env_events <= 0) { log_msg("Environment events not detected, disabling...\n"); return (0); } - if (events >= MAX_ENV_EVENTS) - panic("Environment events exceeds the maximum supported (%d/%d)\n", - events, MAX_ENV_EVENTS); + if (num_env_events >= MAX_ENV_EVENTS) + panic("Environment ENV_EVENTS exceeds the maximum supported (%d/%d)\n", + num_env_events, MAX_ENV_EVENTS); log_msg("%d environment events found, registering...\n"); - for (int i = 0; i < events; i++) { + for (int i = 0; i < num_env_events; i++) { /* EVENTn_MATCH_TYPE. */ env_events[i].ev_match_type = get_event_idx(i, "MATCH_TYPE", match_types, MATCH_TYPES_LEN); @@ -117,7 +178,7 @@ int init_environment_events(void) } log_msg("Environment events summary:\n"); - for (int i = 0; i < events; i++) { + for (int i = 0; i < num_env_events; i++) { printf( "EVENT%d_MATCH_TYPE: %s\n" "EVENT%d_MATCH_STR: %s\n" @@ -128,7 +189,9 @@ int init_environment_events(void) i, notifiers_str[env_events[i].ev_notifier_idx], i, env_events[i].ev_mask_msg ); - } + /* Try to setup notifier if not yet. */ + notifiers[env_events[i].ev_notifier_idx].setup(); + } return (0); } diff --git a/env_events.h b/env_events.h index ee2bf42..f97de7a 100644 --- a/env_events.h +++ b/env_events.h @@ -7,6 +7,7 @@ #define ENV_EVENTS_H #define MAX_ENV_EVENTS 16 + struct log_event; struct env_event { int ev_match_type; /* whether regex or str. */ @@ -17,5 +18,6 @@ extern struct env_event env_events[MAX_ENV_EVENTS]; extern int init_environment_events(void); + extern int process_environment_event(struct log_event *ev); #endif /* ENV_EVENTS_H */ diff --git a/events.c b/events.c index 921b67a..baf4125 100644 --- a/events.c +++ b/events.c @@ -21,6 +21,29 @@ struct ev_handler handlers[NUM_EVENTS] = { /* Add new handlers here. */ }; +/** + * @brief Given an event, checks if it belongs to one of the + * registered events and then, handle it. + * + * @param ev Event to be processed. + * + * @return Returns the amount of matches, 0 if none (not handled). + */ +int process_static_event(struct log_event *ev) +{ + int i; + int handled; + + for (i = 0, handled = 0; i < NUM_EVENTS; i++) { + if (strstr(ev->msg, handlers[i].str)) { + handlers[i].hnd(ev); + handled += 1; + } + } + return handled; +} + + ///////////////////////////// FAILED LOGIN ATTEMPTS /////////////////////////// static int parse_login_attempt_msg(const char *msg, char *wifi_iface, char *mac_addr) diff --git a/events.h b/events.h index 9167567..edfcf10 100644 --- a/events.h +++ b/events.h @@ -11,8 +11,8 @@ #define MSG_MAX 2048 #define NUM_EVENTS 1 - #define EVNT_SUBSTR 1 - #define EVNT_REGEX 2 + #define EVNT_SUBSTR 0 + #define EVNT_REGEX 1 /* Log event. */ struct log_event { @@ -27,5 +27,6 @@ }; extern struct ev_handler handlers[NUM_EVENTS]; + extern int process_static_event(struct log_event *ev); #endif /* EVENTS_H */ diff --git a/log.h b/log.h index 66b961e..fc4b549 100644 --- a/log.h +++ b/log.h @@ -8,6 +8,7 @@ #include #include + #include #include struct log_event; diff --git a/notifiers.c b/notifiers.c index 47baec1..ac3d0d7 100644 --- a/notifiers.c +++ b/notifiers.c @@ -12,6 +12,13 @@ #include "notifiers.h" #include "alertik.h" +/* + * Notification handling/notifiers + */ + +/* EPOCH in secs of last sent notification. */ +static time_t time_last_sent_notify; + /* Just to omit the print to stdout. */ size_t libcurl_noop_cb(void *ptr, size_t size, size_t nmemb, void *data) { ((void)ptr); @@ -19,6 +26,16 @@ size_t libcurl_noop_cb(void *ptr, size_t size, size_t nmemb, void *data) { return size * nmemb; } +/**/ +void update_notify_last_sent(void) { + time_last_sent_notify = time(NULL); +} + +/**/ +int is_within_notify_threshold(void) { + return (time(NULL) - time_last_sent_notify) > LAST_SENT_THRESHOLD_SECS; +} + //////////////////////////////// TELEGRAM ////////////////////////////////////// /* Telegram & request settings. */ static char *telegram_bot_token; @@ -26,6 +43,10 @@ static char *telegram_chat_id; void setup_telegram(void) { + static int setup = 0; + if (setup) + return; + telegram_bot_token = getenv("TELEGRAM_BOT_TOKEN"); telegram_chat_id = getenv("TELEGRAM_CHAT_ID"); if (!telegram_bot_token || !telegram_chat_id) { @@ -36,6 +57,7 @@ void setup_telegram(void) "- TELEGRAM_CHAT_ID\n" ); } + setup = 1; } int send_telegram_notification(const char *msg) @@ -87,8 +109,7 @@ int send_telegram_notification(const char *msg) log_msg("> Unable to send request!\n"); goto error; } else { - time_last_sent_notify = time(NULL); /* Update the time of our last sent */ - log_msg("> Done!\n"); /* notification. */ + log_msg("> Done!\n"); } #endif diff --git a/notifiers.h b/notifiers.h index d5bf4d3..7a71b4d 100644 --- a/notifiers.h +++ b/notifiers.h @@ -16,6 +16,9 @@ #define NUM_NOTIFIERS 1 + /* Minimum time (in secs) between two */ + #define LAST_SENT_THRESHOLD_SECS 10 + /* Notifiers list, like: * - Telegram * - Slack @@ -32,5 +35,7 @@ extern struct notifier notifiers[NUM_NOTIFIERS]; extern void setup_notifiers(void); + extern int is_within_notify_threshold(void); + extern void update_notify_last_sent(void); #endif /* NOTIFIERS_H */