1eda14cbcSMatt Macy#!/bin/sh 2e92ffd9bSMartin Matuska# shellcheck disable=SC2154,SC3043 3eda14cbcSMatt Macy# zed-functions.sh 4eda14cbcSMatt Macy# 5eda14cbcSMatt Macy# ZED helper functions for use in ZEDLETs 6eda14cbcSMatt Macy 7eda14cbcSMatt Macy 8eda14cbcSMatt Macy# Variable Defaults 9eda14cbcSMatt Macy# 10eda14cbcSMatt Macy: "${ZED_LOCKDIR:="/var/lock"}" 11eda14cbcSMatt Macy: "${ZED_NOTIFY_INTERVAL_SECS:=3600}" 12eda14cbcSMatt Macy: "${ZED_NOTIFY_VERBOSE:=0}" 13eda14cbcSMatt Macy: "${ZED_RUNDIR:="/var/run"}" 14eda14cbcSMatt Macy: "${ZED_SYSLOG_PRIORITY:="daemon.notice"}" 15eda14cbcSMatt Macy: "${ZED_SYSLOG_TAG:="zed"}" 16eda14cbcSMatt Macy 17eda14cbcSMatt MacyZED_FLOCK_FD=8 18eda14cbcSMatt Macy 19eda14cbcSMatt Macy 20eda14cbcSMatt Macy# zed_check_cmd (cmd, ...) 21eda14cbcSMatt Macy# 22eda14cbcSMatt Macy# For each argument given, search PATH for the executable command [cmd]. 23eda14cbcSMatt Macy# Log a message if [cmd] is not found. 24eda14cbcSMatt Macy# 25eda14cbcSMatt Macy# Arguments 26eda14cbcSMatt Macy# cmd: name of executable command for which to search 27eda14cbcSMatt Macy# 28eda14cbcSMatt Macy# Return 29eda14cbcSMatt Macy# 0 if all commands are found in PATH and are executable 30eda14cbcSMatt Macy# n for a count of the command executables that are not found 31eda14cbcSMatt Macy# 32eda14cbcSMatt Macyzed_check_cmd() 33eda14cbcSMatt Macy{ 34eda14cbcSMatt Macy local cmd 35eda14cbcSMatt Macy local rv=0 36eda14cbcSMatt Macy 37eda14cbcSMatt Macy for cmd; do 38eda14cbcSMatt Macy if ! command -v "${cmd}" >/dev/null 2>&1; then 39eda14cbcSMatt Macy zed_log_err "\"${cmd}\" not installed" 40eda14cbcSMatt Macy rv=$((rv + 1)) 41eda14cbcSMatt Macy fi 42eda14cbcSMatt Macy done 43eda14cbcSMatt Macy return "${rv}" 44eda14cbcSMatt Macy} 45eda14cbcSMatt Macy 46eda14cbcSMatt Macy 47eda14cbcSMatt Macy# zed_log_msg (msg, ...) 48eda14cbcSMatt Macy# 49eda14cbcSMatt Macy# Write all argument strings to the system log. 50eda14cbcSMatt Macy# 51eda14cbcSMatt Macy# Globals 52eda14cbcSMatt Macy# ZED_SYSLOG_PRIORITY 53eda14cbcSMatt Macy# ZED_SYSLOG_TAG 54eda14cbcSMatt Macy# 55eda14cbcSMatt Macy# Return 56eda14cbcSMatt Macy# nothing 57eda14cbcSMatt Macy# 58eda14cbcSMatt Macyzed_log_msg() 59eda14cbcSMatt Macy{ 60eda14cbcSMatt Macy logger -p "${ZED_SYSLOG_PRIORITY}" -t "${ZED_SYSLOG_TAG}" -- "$@" 61eda14cbcSMatt Macy} 62eda14cbcSMatt Macy 63eda14cbcSMatt Macy 64eda14cbcSMatt Macy# zed_log_err (msg, ...) 65eda14cbcSMatt Macy# 66eda14cbcSMatt Macy# Write an error message to the system log. This message will contain the 67eda14cbcSMatt Macy# script name, EID, and all argument strings. 68eda14cbcSMatt Macy# 69eda14cbcSMatt Macy# Globals 70eda14cbcSMatt Macy# ZED_SYSLOG_PRIORITY 71eda14cbcSMatt Macy# ZED_SYSLOG_TAG 72eda14cbcSMatt Macy# ZEVENT_EID 73eda14cbcSMatt Macy# 74eda14cbcSMatt Macy# Return 75eda14cbcSMatt Macy# nothing 76eda14cbcSMatt Macy# 77eda14cbcSMatt Macyzed_log_err() 78eda14cbcSMatt Macy{ 79716fd348SMartin Matuska zed_log_msg "error: ${0##*/}:""${ZEVENT_EID:+" eid=${ZEVENT_EID}:"}" "$@" 80eda14cbcSMatt Macy} 81eda14cbcSMatt Macy 82eda14cbcSMatt Macy 83eda14cbcSMatt Macy# zed_lock (lockfile, [fd]) 84eda14cbcSMatt Macy# 85eda14cbcSMatt Macy# Obtain an exclusive (write) lock on [lockfile]. If the lock cannot be 86eda14cbcSMatt Macy# immediately acquired, wait until it becomes available. 87eda14cbcSMatt Macy# 88eda14cbcSMatt Macy# Every zed_lock() must be paired with a corresponding zed_unlock(). 89eda14cbcSMatt Macy# 90eda14cbcSMatt Macy# By default, flock-style locks associate the lockfile with file descriptor 8. 91eda14cbcSMatt Macy# The bash manpage warns that file descriptors >9 should be used with care as 92eda14cbcSMatt Macy# they may conflict with file descriptors used internally by the shell. File 93eda14cbcSMatt Macy# descriptor 9 is reserved for zed_rate_limit(). If concurrent locks are held 94eda14cbcSMatt Macy# within the same process, they must use different file descriptors (preferably 95eda14cbcSMatt Macy# decrementing from 8); otherwise, obtaining a new lock with a given file 96eda14cbcSMatt Macy# descriptor will release the previous lock associated with that descriptor. 97eda14cbcSMatt Macy# 98eda14cbcSMatt Macy# Arguments 99eda14cbcSMatt Macy# lockfile: pathname of the lock file; the lock will be stored in 100eda14cbcSMatt Macy# ZED_LOCKDIR unless the pathname contains a "/". 101eda14cbcSMatt Macy# fd: integer for the file descriptor used by flock (OPTIONAL unless holding 102eda14cbcSMatt Macy# concurrent locks) 103eda14cbcSMatt Macy# 104eda14cbcSMatt Macy# Globals 105eda14cbcSMatt Macy# ZED_FLOCK_FD 106eda14cbcSMatt Macy# ZED_LOCKDIR 107eda14cbcSMatt Macy# 108eda14cbcSMatt Macy# Return 109eda14cbcSMatt Macy# nothing 110eda14cbcSMatt Macy# 111eda14cbcSMatt Macyzed_lock() 112eda14cbcSMatt Macy{ 113eda14cbcSMatt Macy local lockfile="$1" 114eda14cbcSMatt Macy local fd="${2:-${ZED_FLOCK_FD}}" 115eda14cbcSMatt Macy local umask_bak 116eda14cbcSMatt Macy local err 117eda14cbcSMatt Macy 118eda14cbcSMatt Macy [ -n "${lockfile}" ] || return 119eda14cbcSMatt Macy if ! expr "${lockfile}" : '.*/' >/dev/null 2>&1; then 120eda14cbcSMatt Macy lockfile="${ZED_LOCKDIR}/${lockfile}" 121eda14cbcSMatt Macy fi 122eda14cbcSMatt Macy 123eda14cbcSMatt Macy umask_bak="$(umask)" 124eda14cbcSMatt Macy umask 077 125eda14cbcSMatt Macy 126eda14cbcSMatt Macy # Obtain a lock on the file bound to the given file descriptor. 127eda14cbcSMatt Macy # 1283ff01b23SMartin Matuska eval "exec ${fd}>> '${lockfile}'" 12916038816SMartin Matuska if ! err="$(flock --exclusive "${fd}" 2>&1)"; then 130eda14cbcSMatt Macy zed_log_err "failed to lock \"${lockfile}\": ${err}" 131eda14cbcSMatt Macy fi 132eda14cbcSMatt Macy 133eda14cbcSMatt Macy umask "${umask_bak}" 134eda14cbcSMatt Macy} 135eda14cbcSMatt Macy 136eda14cbcSMatt Macy 137eda14cbcSMatt Macy# zed_unlock (lockfile, [fd]) 138eda14cbcSMatt Macy# 139eda14cbcSMatt Macy# Release the lock on [lockfile]. 140eda14cbcSMatt Macy# 141eda14cbcSMatt Macy# Arguments 142eda14cbcSMatt Macy# lockfile: pathname of the lock file 143eda14cbcSMatt Macy# fd: integer for the file descriptor used by flock (must match the file 144eda14cbcSMatt Macy# descriptor passed to the zed_lock function call) 145eda14cbcSMatt Macy# 146eda14cbcSMatt Macy# Globals 147eda14cbcSMatt Macy# ZED_FLOCK_FD 148eda14cbcSMatt Macy# ZED_LOCKDIR 149eda14cbcSMatt Macy# 150eda14cbcSMatt Macy# Return 151eda14cbcSMatt Macy# nothing 152eda14cbcSMatt Macy# 153eda14cbcSMatt Macyzed_unlock() 154eda14cbcSMatt Macy{ 155eda14cbcSMatt Macy local lockfile="$1" 156eda14cbcSMatt Macy local fd="${2:-${ZED_FLOCK_FD}}" 157eda14cbcSMatt Macy local err 158eda14cbcSMatt Macy 159eda14cbcSMatt Macy [ -n "${lockfile}" ] || return 160eda14cbcSMatt Macy if ! expr "${lockfile}" : '.*/' >/dev/null 2>&1; then 161eda14cbcSMatt Macy lockfile="${ZED_LOCKDIR}/${lockfile}" 162eda14cbcSMatt Macy fi 163eda14cbcSMatt Macy 164eda14cbcSMatt Macy # Release the lock and close the file descriptor. 16516038816SMartin Matuska if ! err="$(flock --unlock "${fd}" 2>&1)"; then 166eda14cbcSMatt Macy zed_log_err "failed to unlock \"${lockfile}\": ${err}" 167eda14cbcSMatt Macy fi 168eda14cbcSMatt Macy eval "exec ${fd}>&-" 169eda14cbcSMatt Macy} 170eda14cbcSMatt Macy 171eda14cbcSMatt Macy 172eda14cbcSMatt Macy# zed_notify (subject, pathname) 173eda14cbcSMatt Macy# 174eda14cbcSMatt Macy# Send a notification via all available methods. 175eda14cbcSMatt Macy# 176eda14cbcSMatt Macy# Arguments 177eda14cbcSMatt Macy# subject: notification subject 178eda14cbcSMatt Macy# pathname: pathname containing the notification message (OPTIONAL) 179eda14cbcSMatt Macy# 180eda14cbcSMatt Macy# Return 181eda14cbcSMatt Macy# 0: notification succeeded via at least one method 182eda14cbcSMatt Macy# 1: notification failed 183eda14cbcSMatt Macy# 2: no notification methods configured 184eda14cbcSMatt Macy# 185eda14cbcSMatt Macyzed_notify() 186eda14cbcSMatt Macy{ 187eda14cbcSMatt Macy local subject="$1" 188eda14cbcSMatt Macy local pathname="$2" 189eda14cbcSMatt Macy local num_success=0 190eda14cbcSMatt Macy local num_failure=0 191eda14cbcSMatt Macy 192eda14cbcSMatt Macy zed_notify_email "${subject}" "${pathname}"; rv=$? 193eda14cbcSMatt Macy [ "${rv}" -eq 0 ] && num_success=$((num_success + 1)) 194eda14cbcSMatt Macy [ "${rv}" -eq 1 ] && num_failure=$((num_failure + 1)) 195eda14cbcSMatt Macy 196eda14cbcSMatt Macy zed_notify_pushbullet "${subject}" "${pathname}"; rv=$? 197eda14cbcSMatt Macy [ "${rv}" -eq 0 ] && num_success=$((num_success + 1)) 198eda14cbcSMatt Macy [ "${rv}" -eq 1 ] && num_failure=$((num_failure + 1)) 199eda14cbcSMatt Macy 200eda14cbcSMatt Macy zed_notify_slack_webhook "${subject}" "${pathname}"; rv=$? 201eda14cbcSMatt Macy [ "${rv}" -eq 0 ] && num_success=$((num_success + 1)) 202eda14cbcSMatt Macy [ "${rv}" -eq 1 ] && num_failure=$((num_failure + 1)) 203eda14cbcSMatt Macy 20416038816SMartin Matuska zed_notify_pushover "${subject}" "${pathname}"; rv=$? 20516038816SMartin Matuska [ "${rv}" -eq 0 ] && num_success=$((num_success + 1)) 20616038816SMartin Matuska [ "${rv}" -eq 1 ] && num_failure=$((num_failure + 1)) 20716038816SMartin Matuska 2083494f7c0SMartin Matuska zed_notify_ntfy "${subject}" "${pathname}"; rv=$? 2093494f7c0SMartin Matuska [ "${rv}" -eq 0 ] && num_success=$((num_success + 1)) 2103494f7c0SMartin Matuska [ "${rv}" -eq 1 ] && num_failure=$((num_failure + 1)) 2113494f7c0SMartin Matuska 212*f552d7adSMartin Matuska zed_notify_gotify "${subject}" "${pathname}"; rv=$? 213*f552d7adSMartin Matuska [ "${rv}" -eq 0 ] && num_success=$((num_success + 1)) 214*f552d7adSMartin Matuska [ "${rv}" -eq 1 ] && num_failure=$((num_failure + 1)) 215*f552d7adSMartin Matuska 216eda14cbcSMatt Macy [ "${num_success}" -gt 0 ] && return 0 217eda14cbcSMatt Macy [ "${num_failure}" -gt 0 ] && return 1 218eda14cbcSMatt Macy return 2 219eda14cbcSMatt Macy} 220eda14cbcSMatt Macy 221eda14cbcSMatt Macy 222eda14cbcSMatt Macy# zed_notify_email (subject, pathname) 223eda14cbcSMatt Macy# 224eda14cbcSMatt Macy# Send a notification via email to the address specified by ZED_EMAIL_ADDR. 225eda14cbcSMatt Macy# 226eda14cbcSMatt Macy# Requires the mail executable to be installed in the standard PATH, or 227eda14cbcSMatt Macy# ZED_EMAIL_PROG to be defined with the pathname of an executable capable of 228eda14cbcSMatt Macy# reading a message body from stdin. 229eda14cbcSMatt Macy# 230eda14cbcSMatt Macy# Command-line options to the mail executable can be specified in 231eda14cbcSMatt Macy# ZED_EMAIL_OPTS. This undergoes the following keyword substitutions: 232eda14cbcSMatt Macy# - @ADDRESS@ is replaced with the space-delimited recipient email address(es) 233eda14cbcSMatt Macy# - @SUBJECT@ is replaced with the notification subject 234e3aa18adSMartin Matuska# If @SUBJECT@ was omited here, a "Subject: ..." header will be added to notification 235e3aa18adSMartin Matuska# 236eda14cbcSMatt Macy# 237eda14cbcSMatt Macy# Arguments 238eda14cbcSMatt Macy# subject: notification subject 239eda14cbcSMatt Macy# pathname: pathname containing the notification message (OPTIONAL) 240eda14cbcSMatt Macy# 241eda14cbcSMatt Macy# Globals 242eda14cbcSMatt Macy# ZED_EMAIL_PROG 243eda14cbcSMatt Macy# ZED_EMAIL_OPTS 244eda14cbcSMatt Macy# ZED_EMAIL_ADDR 245eda14cbcSMatt Macy# 246eda14cbcSMatt Macy# Return 247eda14cbcSMatt Macy# 0: notification sent 248eda14cbcSMatt Macy# 1: notification failed 249eda14cbcSMatt Macy# 2: not configured 250eda14cbcSMatt Macy# 251eda14cbcSMatt Macyzed_notify_email() 252eda14cbcSMatt Macy{ 253e3aa18adSMartin Matuska local subject="${1:-"ZED notification"}" 254eda14cbcSMatt Macy local pathname="${2:-"/dev/null"}" 255eda14cbcSMatt Macy 256eda14cbcSMatt Macy : "${ZED_EMAIL_PROG:="mail"}" 257eda14cbcSMatt Macy : "${ZED_EMAIL_OPTS:="-s '@SUBJECT@' @ADDRESS@"}" 258eda14cbcSMatt Macy 259eda14cbcSMatt Macy # For backward compatibility with ZED_EMAIL. 260eda14cbcSMatt Macy if [ -n "${ZED_EMAIL}" ] && [ -z "${ZED_EMAIL_ADDR}" ]; then 261eda14cbcSMatt Macy ZED_EMAIL_ADDR="${ZED_EMAIL}" 262eda14cbcSMatt Macy fi 263eda14cbcSMatt Macy [ -n "${ZED_EMAIL_ADDR}" ] || return 2 264eda14cbcSMatt Macy 265eda14cbcSMatt Macy zed_check_cmd "${ZED_EMAIL_PROG}" || return 1 266eda14cbcSMatt Macy 267eda14cbcSMatt Macy [ -n "${subject}" ] || return 1 268eda14cbcSMatt Macy if [ ! -r "${pathname}" ]; then 269eda14cbcSMatt Macy zed_log_err \ 270dae17134SMartin Matuska "${ZED_EMAIL_PROG##*/} cannot read \"${pathname}\"" 271eda14cbcSMatt Macy return 1 272eda14cbcSMatt Macy fi 273eda14cbcSMatt Macy 274e3aa18adSMartin Matuska # construct cmdline options 275e3aa18adSMartin Matuska ZED_EMAIL_OPTS_PARSED="$(echo "${ZED_EMAIL_OPTS}" \ 276eda14cbcSMatt Macy | sed -e "s/@ADDRESS@/${ZED_EMAIL_ADDR}/g" \ 277eda14cbcSMatt Macy -e "s/@SUBJECT@/${subject}/g")" 278eda14cbcSMatt Macy 279e3aa18adSMartin Matuska # pipe message to email prog 280e92ffd9bSMartin Matuska # shellcheck disable=SC2086,SC2248 281e3aa18adSMartin Matuska { 282e3aa18adSMartin Matuska # no subject passed as option? 283e3aa18adSMartin Matuska if [ "${ZED_EMAIL_OPTS%@SUBJECT@*}" = "${ZED_EMAIL_OPTS}" ] ; then 284e3aa18adSMartin Matuska # inject subject header 285e3aa18adSMartin Matuska printf "Subject: %s\n" "${subject}" 286e3aa18adSMartin Matuska fi 287e3aa18adSMartin Matuska # output message 288e3aa18adSMartin Matuska cat "${pathname}" 289e3aa18adSMartin Matuska } | 290e3aa18adSMartin Matuska eval ${ZED_EMAIL_PROG} ${ZED_EMAIL_OPTS_PARSED} >/dev/null 2>&1 291eda14cbcSMatt Macy rv=$? 292eda14cbcSMatt Macy if [ "${rv}" -ne 0 ]; then 293dae17134SMartin Matuska zed_log_err "${ZED_EMAIL_PROG##*/} exit=${rv}" 294eda14cbcSMatt Macy return 1 295eda14cbcSMatt Macy fi 296eda14cbcSMatt Macy return 0 297eda14cbcSMatt Macy} 298eda14cbcSMatt Macy 299eda14cbcSMatt Macy 300eda14cbcSMatt Macy# zed_notify_pushbullet (subject, pathname) 301eda14cbcSMatt Macy# 302eda14cbcSMatt Macy# Send a notification via Pushbullet <https://www.pushbullet.com/>. 303eda14cbcSMatt Macy# The access token (ZED_PUSHBULLET_ACCESS_TOKEN) identifies this client to the 304eda14cbcSMatt Macy# Pushbullet server. The optional channel tag (ZED_PUSHBULLET_CHANNEL_TAG) is 305eda14cbcSMatt Macy# for pushing to notification feeds that can be subscribed to; if a channel is 306eda14cbcSMatt Macy# not defined, push notifications will instead be sent to all devices 307eda14cbcSMatt Macy# associated with the account specified by the access token. 308eda14cbcSMatt Macy# 309eda14cbcSMatt Macy# Requires awk, curl, and sed executables to be installed in the standard PATH. 310eda14cbcSMatt Macy# 311eda14cbcSMatt Macy# References 312eda14cbcSMatt Macy# https://docs.pushbullet.com/ 313eda14cbcSMatt Macy# https://www.pushbullet.com/security 314eda14cbcSMatt Macy# 315eda14cbcSMatt Macy# Arguments 316eda14cbcSMatt Macy# subject: notification subject 317eda14cbcSMatt Macy# pathname: pathname containing the notification message (OPTIONAL) 318eda14cbcSMatt Macy# 319eda14cbcSMatt Macy# Globals 320eda14cbcSMatt Macy# ZED_PUSHBULLET_ACCESS_TOKEN 321eda14cbcSMatt Macy# ZED_PUSHBULLET_CHANNEL_TAG 322eda14cbcSMatt Macy# 323eda14cbcSMatt Macy# Return 324eda14cbcSMatt Macy# 0: notification sent 325eda14cbcSMatt Macy# 1: notification failed 326eda14cbcSMatt Macy# 2: not configured 327eda14cbcSMatt Macy# 328eda14cbcSMatt Macyzed_notify_pushbullet() 329eda14cbcSMatt Macy{ 330eda14cbcSMatt Macy local subject="$1" 331eda14cbcSMatt Macy local pathname="${2:-"/dev/null"}" 332eda14cbcSMatt Macy local msg_body 333eda14cbcSMatt Macy local msg_tag 334eda14cbcSMatt Macy local msg_json 335eda14cbcSMatt Macy local msg_out 336eda14cbcSMatt Macy local msg_err 337eda14cbcSMatt Macy local url="https://api.pushbullet.com/v2/pushes" 338eda14cbcSMatt Macy 339eda14cbcSMatt Macy [ -n "${ZED_PUSHBULLET_ACCESS_TOKEN}" ] || return 2 340eda14cbcSMatt Macy 341eda14cbcSMatt Macy [ -n "${subject}" ] || return 1 342eda14cbcSMatt Macy if [ ! -r "${pathname}" ]; then 343eda14cbcSMatt Macy zed_log_err "pushbullet cannot read \"${pathname}\"" 344eda14cbcSMatt Macy return 1 345eda14cbcSMatt Macy fi 346eda14cbcSMatt Macy 347eda14cbcSMatt Macy zed_check_cmd "awk" "curl" "sed" || return 1 348eda14cbcSMatt Macy 349eda14cbcSMatt Macy # Escape the following characters in the message body for JSON: 350eda14cbcSMatt Macy # newline, backslash, double quote, horizontal tab, vertical tab, 351eda14cbcSMatt Macy # and carriage return. 352eda14cbcSMatt Macy # 353eda14cbcSMatt Macy msg_body="$(awk '{ ORS="\\n" } { gsub(/\\/, "\\\\"); gsub(/"/, "\\\""); 354eda14cbcSMatt Macy gsub(/\t/, "\\t"); gsub(/\f/, "\\f"); gsub(/\r/, "\\r"); print }' \ 355eda14cbcSMatt Macy "${pathname}")" 356eda14cbcSMatt Macy 357eda14cbcSMatt Macy # Push to a channel if one is configured. 358eda14cbcSMatt Macy # 359eda14cbcSMatt Macy [ -n "${ZED_PUSHBULLET_CHANNEL_TAG}" ] && msg_tag="$(printf \ 360eda14cbcSMatt Macy '"channel_tag": "%s", ' "${ZED_PUSHBULLET_CHANNEL_TAG}")" 361eda14cbcSMatt Macy 362eda14cbcSMatt Macy # Construct the JSON message for pushing a note. 363eda14cbcSMatt Macy # 364eda14cbcSMatt Macy msg_json="$(printf '{%s"type": "note", "title": "%s", "body": "%s"}' \ 365eda14cbcSMatt Macy "${msg_tag}" "${subject}" "${msg_body}")" 366eda14cbcSMatt Macy 367eda14cbcSMatt Macy # Send the POST request and check for errors. 368eda14cbcSMatt Macy # 369eda14cbcSMatt Macy msg_out="$(curl -u "${ZED_PUSHBULLET_ACCESS_TOKEN}:" -X POST "${url}" \ 370eda14cbcSMatt Macy --header "Content-Type: application/json" --data-binary "${msg_json}" \ 371eda14cbcSMatt Macy 2>/dev/null)"; rv=$? 372eda14cbcSMatt Macy if [ "${rv}" -ne 0 ]; then 373eda14cbcSMatt Macy zed_log_err "curl exit=${rv}" 374eda14cbcSMatt Macy return 1 375eda14cbcSMatt Macy fi 376eda14cbcSMatt Macy msg_err="$(echo "${msg_out}" \ 377eda14cbcSMatt Macy | sed -n -e 's/.*"error" *:.*"message" *: *"\([^"]*\)".*/\1/p')" 378eda14cbcSMatt Macy if [ -n "${msg_err}" ]; then 379eda14cbcSMatt Macy zed_log_err "pushbullet \"${msg_err}"\" 380eda14cbcSMatt Macy return 1 381eda14cbcSMatt Macy fi 382eda14cbcSMatt Macy return 0 383eda14cbcSMatt Macy} 384eda14cbcSMatt Macy 385eda14cbcSMatt Macy 386eda14cbcSMatt Macy# zed_notify_slack_webhook (subject, pathname) 387eda14cbcSMatt Macy# 388eda14cbcSMatt Macy# Notification via Slack Webhook <https://api.slack.com/incoming-webhooks>. 389eda14cbcSMatt Macy# The Webhook URL (ZED_SLACK_WEBHOOK_URL) identifies this client to the 390eda14cbcSMatt Macy# Slack channel. 391eda14cbcSMatt Macy# 392eda14cbcSMatt Macy# Requires awk, curl, and sed executables to be installed in the standard PATH. 393eda14cbcSMatt Macy# 394eda14cbcSMatt Macy# References 395eda14cbcSMatt Macy# https://api.slack.com/incoming-webhooks 396eda14cbcSMatt Macy# 397eda14cbcSMatt Macy# Arguments 398eda14cbcSMatt Macy# subject: notification subject 399eda14cbcSMatt Macy# pathname: pathname containing the notification message (OPTIONAL) 400eda14cbcSMatt Macy# 401eda14cbcSMatt Macy# Globals 402eda14cbcSMatt Macy# ZED_SLACK_WEBHOOK_URL 403eda14cbcSMatt Macy# 404eda14cbcSMatt Macy# Return 405eda14cbcSMatt Macy# 0: notification sent 406eda14cbcSMatt Macy# 1: notification failed 407eda14cbcSMatt Macy# 2: not configured 408eda14cbcSMatt Macy# 409eda14cbcSMatt Macyzed_notify_slack_webhook() 410eda14cbcSMatt Macy{ 411eda14cbcSMatt Macy [ -n "${ZED_SLACK_WEBHOOK_URL}" ] || return 2 412eda14cbcSMatt Macy 413eda14cbcSMatt Macy local subject="$1" 414eda14cbcSMatt Macy local pathname="${2:-"/dev/null"}" 415eda14cbcSMatt Macy local msg_body 416eda14cbcSMatt Macy local msg_tag 417eda14cbcSMatt Macy local msg_json 418eda14cbcSMatt Macy local msg_out 419eda14cbcSMatt Macy local msg_err 420eda14cbcSMatt Macy local url="${ZED_SLACK_WEBHOOK_URL}" 421eda14cbcSMatt Macy 422eda14cbcSMatt Macy [ -n "${subject}" ] || return 1 423eda14cbcSMatt Macy if [ ! -r "${pathname}" ]; then 424eda14cbcSMatt Macy zed_log_err "slack webhook cannot read \"${pathname}\"" 425eda14cbcSMatt Macy return 1 426eda14cbcSMatt Macy fi 427eda14cbcSMatt Macy 428eda14cbcSMatt Macy zed_check_cmd "awk" "curl" "sed" || return 1 429eda14cbcSMatt Macy 430eda14cbcSMatt Macy # Escape the following characters in the message body for JSON: 431eda14cbcSMatt Macy # newline, backslash, double quote, horizontal tab, vertical tab, 432eda14cbcSMatt Macy # and carriage return. 433eda14cbcSMatt Macy # 434eda14cbcSMatt Macy msg_body="$(awk '{ ORS="\\n" } { gsub(/\\/, "\\\\"); gsub(/"/, "\\\""); 435eda14cbcSMatt Macy gsub(/\t/, "\\t"); gsub(/\f/, "\\f"); gsub(/\r/, "\\r"); print }' \ 436eda14cbcSMatt Macy "${pathname}")" 437eda14cbcSMatt Macy 438eda14cbcSMatt Macy # Construct the JSON message for posting. 439eda14cbcSMatt Macy # 440c03c5b1cSMartin Matuska msg_json="$(printf '{"text": "*%s*\\n%s"}' "${subject}" "${msg_body}" )" 441eda14cbcSMatt Macy 442eda14cbcSMatt Macy # Send the POST request and check for errors. 443eda14cbcSMatt Macy # 444eda14cbcSMatt Macy msg_out="$(curl -X POST "${url}" \ 445eda14cbcSMatt Macy --header "Content-Type: application/json" --data-binary "${msg_json}" \ 446eda14cbcSMatt Macy 2>/dev/null)"; rv=$? 447eda14cbcSMatt Macy if [ "${rv}" -ne 0 ]; then 448eda14cbcSMatt Macy zed_log_err "curl exit=${rv}" 449eda14cbcSMatt Macy return 1 450eda14cbcSMatt Macy fi 451eda14cbcSMatt Macy msg_err="$(echo "${msg_out}" \ 452eda14cbcSMatt Macy | sed -n -e 's/.*"error" *:.*"message" *: *"\([^"]*\)".*/\1/p')" 453eda14cbcSMatt Macy if [ -n "${msg_err}" ]; then 454eda14cbcSMatt Macy zed_log_err "slack webhook \"${msg_err}"\" 455eda14cbcSMatt Macy return 1 456eda14cbcSMatt Macy fi 457eda14cbcSMatt Macy return 0 458eda14cbcSMatt Macy} 459eda14cbcSMatt Macy 46016038816SMartin Matuska# zed_notify_pushover (subject, pathname) 46116038816SMartin Matuska# 46216038816SMartin Matuska# Send a notification via Pushover <https://pushover.net/>. 46316038816SMartin Matuska# The access token (ZED_PUSHOVER_TOKEN) identifies this client to the 46416038816SMartin Matuska# Pushover server. The user token (ZED_PUSHOVER_USER) defines the user or 46516038816SMartin Matuska# group to which the notification will be sent. 46616038816SMartin Matuska# 46716038816SMartin Matuska# Requires curl and sed executables to be installed in the standard PATH. 46816038816SMartin Matuska# 46916038816SMartin Matuska# References 47016038816SMartin Matuska# https://pushover.net/api 47116038816SMartin Matuska# 47216038816SMartin Matuska# Arguments 47316038816SMartin Matuska# subject: notification subject 47416038816SMartin Matuska# pathname: pathname containing the notification message (OPTIONAL) 47516038816SMartin Matuska# 47616038816SMartin Matuska# Globals 47716038816SMartin Matuska# ZED_PUSHOVER_TOKEN 47816038816SMartin Matuska# ZED_PUSHOVER_USER 47916038816SMartin Matuska# 48016038816SMartin Matuska# Return 48116038816SMartin Matuska# 0: notification sent 48216038816SMartin Matuska# 1: notification failed 48316038816SMartin Matuska# 2: not configured 48416038816SMartin Matuska# 48516038816SMartin Matuskazed_notify_pushover() 48616038816SMartin Matuska{ 48716038816SMartin Matuska local subject="$1" 48816038816SMartin Matuska local pathname="${2:-"/dev/null"}" 48916038816SMartin Matuska local msg_body 49016038816SMartin Matuska local msg_out 49116038816SMartin Matuska local msg_err 49216038816SMartin Matuska local url="https://api.pushover.net/1/messages.json" 49316038816SMartin Matuska 49416038816SMartin Matuska [ -n "${ZED_PUSHOVER_TOKEN}" ] && [ -n "${ZED_PUSHOVER_USER}" ] || return 2 49516038816SMartin Matuska 49616038816SMartin Matuska if [ ! -r "${pathname}" ]; then 49716038816SMartin Matuska zed_log_err "pushover cannot read \"${pathname}\"" 49816038816SMartin Matuska return 1 49916038816SMartin Matuska fi 50016038816SMartin Matuska 50116038816SMartin Matuska zed_check_cmd "curl" "sed" || return 1 50216038816SMartin Matuska 50316038816SMartin Matuska # Read the message body in. 50416038816SMartin Matuska # 50516038816SMartin Matuska msg_body="$(cat "${pathname}")" 50616038816SMartin Matuska 50716038816SMartin Matuska if [ -z "${msg_body}" ] 50816038816SMartin Matuska then 50916038816SMartin Matuska msg_body=$subject 51016038816SMartin Matuska subject="" 51116038816SMartin Matuska fi 51216038816SMartin Matuska 51316038816SMartin Matuska # Send the POST request and check for errors. 51416038816SMartin Matuska # 51516038816SMartin Matuska msg_out="$( \ 51616038816SMartin Matuska curl \ 51716038816SMartin Matuska --form-string "token=${ZED_PUSHOVER_TOKEN}" \ 51816038816SMartin Matuska --form-string "user=${ZED_PUSHOVER_USER}" \ 51916038816SMartin Matuska --form-string "message=${msg_body}" \ 52016038816SMartin Matuska --form-string "title=${subject}" \ 52116038816SMartin Matuska "${url}" \ 52216038816SMartin Matuska 2>/dev/null \ 52316038816SMartin Matuska )"; rv=$? 52416038816SMartin Matuska if [ "${rv}" -ne 0 ]; then 52516038816SMartin Matuska zed_log_err "curl exit=${rv}" 52616038816SMartin Matuska return 1 52716038816SMartin Matuska fi 52816038816SMartin Matuska msg_err="$(echo "${msg_out}" \ 52916038816SMartin Matuska | sed -n -e 's/.*"errors" *:.*\[\(.*\)\].*/\1/p')" 53016038816SMartin Matuska if [ -n "${msg_err}" ]; then 53116038816SMartin Matuska zed_log_err "pushover \"${msg_err}"\" 53216038816SMartin Matuska return 1 53316038816SMartin Matuska fi 53416038816SMartin Matuska return 0 53516038816SMartin Matuska} 53616038816SMartin Matuska 53716038816SMartin Matuska 5383494f7c0SMartin Matuska# zed_notify_ntfy (subject, pathname) 5393494f7c0SMartin Matuska# 5403494f7c0SMartin Matuska# Send a notification via Ntfy.sh <https://ntfy.sh/>. 5413494f7c0SMartin Matuska# The ntfy topic (ZED_NTFY_TOPIC) identifies the topic that the notification 5423494f7c0SMartin Matuska# will be sent to Ntfy.sh server. The ntfy url (ZED_NTFY_URL) defines the 5433494f7c0SMartin Matuska# self-hosted or provided hosted ntfy service location. The ntfy access token 5443494f7c0SMartin Matuska# <https://docs.ntfy.sh/publish/#access-tokens> (ZED_NTFY_ACCESS_TOKEN) reprsents an 5453494f7c0SMartin Matuska# access token that could be used if a topic is read/write protected. If a 5463494f7c0SMartin Matuska# topic can be written to publicaly, a ZED_NTFY_ACCESS_TOKEN is not required. 5473494f7c0SMartin Matuska# 5483494f7c0SMartin Matuska# Requires curl and sed executables to be installed in the standard PATH. 5493494f7c0SMartin Matuska# 5503494f7c0SMartin Matuska# References 5513494f7c0SMartin Matuska# https://docs.ntfy.sh 5523494f7c0SMartin Matuska# 5533494f7c0SMartin Matuska# Arguments 5543494f7c0SMartin Matuska# subject: notification subject 5553494f7c0SMartin Matuska# pathname: pathname containing the notification message (OPTIONAL) 5563494f7c0SMartin Matuska# 5573494f7c0SMartin Matuska# Globals 5583494f7c0SMartin Matuska# ZED_NTFY_TOPIC 5593494f7c0SMartin Matuska# ZED_NTFY_ACCESS_TOKEN (OPTIONAL) 5603494f7c0SMartin Matuska# ZED_NTFY_URL 5613494f7c0SMartin Matuska# 5623494f7c0SMartin Matuska# Return 5633494f7c0SMartin Matuska# 0: notification sent 5643494f7c0SMartin Matuska# 1: notification failed 5653494f7c0SMartin Matuska# 2: not configured 5663494f7c0SMartin Matuska# 5673494f7c0SMartin Matuskazed_notify_ntfy() 5683494f7c0SMartin Matuska{ 5693494f7c0SMartin Matuska local subject="$1" 5703494f7c0SMartin Matuska local pathname="${2:-"/dev/null"}" 5713494f7c0SMartin Matuska local msg_body 5723494f7c0SMartin Matuska local msg_out 5733494f7c0SMartin Matuska local msg_err 5743494f7c0SMartin Matuska 5753494f7c0SMartin Matuska [ -n "${ZED_NTFY_TOPIC}" ] || return 2 5763494f7c0SMartin Matuska local url="${ZED_NTFY_URL:-"https://ntfy.sh"}/${ZED_NTFY_TOPIC}" 5773494f7c0SMartin Matuska 5783494f7c0SMartin Matuska if [ ! -r "${pathname}" ]; then 5793494f7c0SMartin Matuska zed_log_err "ntfy cannot read \"${pathname}\"" 5803494f7c0SMartin Matuska return 1 5813494f7c0SMartin Matuska fi 5823494f7c0SMartin Matuska 5833494f7c0SMartin Matuska zed_check_cmd "curl" "sed" || return 1 5843494f7c0SMartin Matuska 5853494f7c0SMartin Matuska # Read the message body in. 5863494f7c0SMartin Matuska # 5873494f7c0SMartin Matuska msg_body="$(cat "${pathname}")" 5883494f7c0SMartin Matuska 5893494f7c0SMartin Matuska if [ -z "${msg_body}" ] 5903494f7c0SMartin Matuska then 5913494f7c0SMartin Matuska msg_body=$subject 5923494f7c0SMartin Matuska subject="" 5933494f7c0SMartin Matuska fi 5943494f7c0SMartin Matuska 5953494f7c0SMartin Matuska # Send the POST request and check for errors. 5963494f7c0SMartin Matuska # 5973494f7c0SMartin Matuska if [ -n "${ZED_NTFY_ACCESS_TOKEN}" ]; then 5983494f7c0SMartin Matuska msg_out="$( \ 5993494f7c0SMartin Matuska curl \ 6003494f7c0SMartin Matuska -u ":${ZED_NTFY_ACCESS_TOKEN}" \ 6013494f7c0SMartin Matuska -H "Title: ${subject}" \ 6023494f7c0SMartin Matuska -d "${msg_body}" \ 6033494f7c0SMartin Matuska -H "Priority: high" \ 6043494f7c0SMartin Matuska "${url}" \ 6053494f7c0SMartin Matuska 2>/dev/null \ 6063494f7c0SMartin Matuska )"; rv=$? 6073494f7c0SMartin Matuska else 6083494f7c0SMartin Matuska msg_out="$( \ 6093494f7c0SMartin Matuska curl \ 6103494f7c0SMartin Matuska -H "Title: ${subject}" \ 6113494f7c0SMartin Matuska -d "${msg_body}" \ 6123494f7c0SMartin Matuska -H "Priority: high" \ 6133494f7c0SMartin Matuska "${url}" \ 6143494f7c0SMartin Matuska 2>/dev/null \ 6153494f7c0SMartin Matuska )"; rv=$? 6163494f7c0SMartin Matuska fi 6173494f7c0SMartin Matuska if [ "${rv}" -ne 0 ]; then 6183494f7c0SMartin Matuska zed_log_err "curl exit=${rv}" 6193494f7c0SMartin Matuska return 1 6203494f7c0SMartin Matuska fi 6213494f7c0SMartin Matuska msg_err="$(echo "${msg_out}" \ 6223494f7c0SMartin Matuska | sed -n -e 's/.*"errors" *:.*\[\(.*\)\].*/\1/p')" 6233494f7c0SMartin Matuska if [ -n "${msg_err}" ]; then 6243494f7c0SMartin Matuska zed_log_err "ntfy \"${msg_err}"\" 6253494f7c0SMartin Matuska return 1 6263494f7c0SMartin Matuska fi 6273494f7c0SMartin Matuska return 0 6283494f7c0SMartin Matuska} 6293494f7c0SMartin Matuska 6303494f7c0SMartin Matuska 631*f552d7adSMartin Matuska# zed_notify_gotify (subject, pathname) 632*f552d7adSMartin Matuska# 633*f552d7adSMartin Matuska# Send a notification via Gotify <https://gotify.net/>. 634*f552d7adSMartin Matuska# The Gotify URL (ZED_GOTIFY_URL) defines a self-hosted Gotify location. 635*f552d7adSMartin Matuska# The Gotify application token (ZED_GOTIFY_APPTOKEN) defines a 636*f552d7adSMartin Matuska# Gotify application token which is associated with a message. 637*f552d7adSMartin Matuska# The optional Gotify priority value (ZED_GOTIFY_PRIORITY) overrides the 638*f552d7adSMartin Matuska# default or configured priority at the Gotify server for the application. 639*f552d7adSMartin Matuska# 640*f552d7adSMartin Matuska# Requires curl and sed executables to be installed in the standard PATH. 641*f552d7adSMartin Matuska# 642*f552d7adSMartin Matuska# References 643*f552d7adSMartin Matuska# https://gotify.net/docs/index 644*f552d7adSMartin Matuska# 645*f552d7adSMartin Matuska# Arguments 646*f552d7adSMartin Matuska# subject: notification subject 647*f552d7adSMartin Matuska# pathname: pathname containing the notification message (OPTIONAL) 648*f552d7adSMartin Matuska# 649*f552d7adSMartin Matuska# Globals 650*f552d7adSMartin Matuska# ZED_GOTIFY_URL 651*f552d7adSMartin Matuska# ZED_GOTIFY_APPTOKEN 652*f552d7adSMartin Matuska# ZED_GOTIFY_PRIORITY 653*f552d7adSMartin Matuska# 654*f552d7adSMartin Matuska# Return 655*f552d7adSMartin Matuska# 0: notification sent 656*f552d7adSMartin Matuska# 1: notification failed 657*f552d7adSMartin Matuska# 2: not configured 658*f552d7adSMartin Matuska# 659*f552d7adSMartin Matuskazed_notify_gotify() 660*f552d7adSMartin Matuska{ 661*f552d7adSMartin Matuska local subject="$1" 662*f552d7adSMartin Matuska local pathname="${2:-"/dev/null"}" 663*f552d7adSMartin Matuska local msg_body 664*f552d7adSMartin Matuska local msg_out 665*f552d7adSMartin Matuska local msg_err 666*f552d7adSMartin Matuska 667*f552d7adSMartin Matuska [ -n "${ZED_GOTIFY_URL}" ] && [ -n "${ZED_GOTIFY_APPTOKEN}" ] || return 2 668*f552d7adSMartin Matuska local url="${ZED_GOTIFY_URL}/message?token=${ZED_GOTIFY_APPTOKEN}" 669*f552d7adSMartin Matuska 670*f552d7adSMartin Matuska if [ ! -r "${pathname}" ]; then 671*f552d7adSMartin Matuska zed_log_err "gotify cannot read \"${pathname}\"" 672*f552d7adSMartin Matuska return 1 673*f552d7adSMartin Matuska fi 674*f552d7adSMartin Matuska 675*f552d7adSMartin Matuska zed_check_cmd "curl" "sed" || return 1 676*f552d7adSMartin Matuska 677*f552d7adSMartin Matuska # Read the message body in. 678*f552d7adSMartin Matuska # 679*f552d7adSMartin Matuska msg_body="$(cat "${pathname}")" 680*f552d7adSMartin Matuska 681*f552d7adSMartin Matuska if [ -z "${msg_body}" ] 682*f552d7adSMartin Matuska then 683*f552d7adSMartin Matuska msg_body=$subject 684*f552d7adSMartin Matuska subject="" 685*f552d7adSMartin Matuska fi 686*f552d7adSMartin Matuska 687*f552d7adSMartin Matuska # Send the POST request and check for errors. 688*f552d7adSMartin Matuska # 689*f552d7adSMartin Matuska if [ -n "${ZED_GOTIFY_PRIORITY}" ]; then 690*f552d7adSMartin Matuska msg_out="$( \ 691*f552d7adSMartin Matuska curl \ 692*f552d7adSMartin Matuska --form-string "title=${subject}" \ 693*f552d7adSMartin Matuska --form-string "message=${msg_body}" \ 694*f552d7adSMartin Matuska --form-string "priority=${ZED_GOTIFY_PRIORITY}" \ 695*f552d7adSMartin Matuska "${url}" \ 696*f552d7adSMartin Matuska 2>/dev/null \ 697*f552d7adSMartin Matuska )"; rv=$? 698*f552d7adSMartin Matuska else 699*f552d7adSMartin Matuska msg_out="$( \ 700*f552d7adSMartin Matuska curl \ 701*f552d7adSMartin Matuska --form-string "title=${subject}" \ 702*f552d7adSMartin Matuska --form-string "message=${msg_body}" \ 703*f552d7adSMartin Matuska "${url}" \ 704*f552d7adSMartin Matuska 2>/dev/null \ 705*f552d7adSMartin Matuska )"; rv=$? 706*f552d7adSMartin Matuska fi 707*f552d7adSMartin Matuska 708*f552d7adSMartin Matuska if [ "${rv}" -ne 0 ]; then 709*f552d7adSMartin Matuska zed_log_err "curl exit=${rv}" 710*f552d7adSMartin Matuska return 1 711*f552d7adSMartin Matuska fi 712*f552d7adSMartin Matuska msg_err="$(echo "${msg_out}" \ 713*f552d7adSMartin Matuska | sed -n -e 's/.*"errors" *:.*\[\(.*\)\].*/\1/p')" 714*f552d7adSMartin Matuska if [ -n "${msg_err}" ]; then 715*f552d7adSMartin Matuska zed_log_err "gotify \"${msg_err}"\" 716*f552d7adSMartin Matuska return 1 717*f552d7adSMartin Matuska fi 718*f552d7adSMartin Matuska return 0 719*f552d7adSMartin Matuska} 720*f552d7adSMartin Matuska 721*f552d7adSMartin Matuska 7223494f7c0SMartin Matuska 723eda14cbcSMatt Macy# zed_rate_limit (tag, [interval]) 724eda14cbcSMatt Macy# 725eda14cbcSMatt Macy# Check whether an event of a given type [tag] has already occurred within the 726eda14cbcSMatt Macy# last [interval] seconds. 727eda14cbcSMatt Macy# 728eda14cbcSMatt Macy# This function obtains a lock on the statefile using file descriptor 9. 729eda14cbcSMatt Macy# 730eda14cbcSMatt Macy# Arguments 731eda14cbcSMatt Macy# tag: arbitrary string for grouping related events to rate-limit 732eda14cbcSMatt Macy# interval: time interval in seconds (OPTIONAL) 733eda14cbcSMatt Macy# 734eda14cbcSMatt Macy# Globals 735eda14cbcSMatt Macy# ZED_NOTIFY_INTERVAL_SECS 736eda14cbcSMatt Macy# ZED_RUNDIR 737eda14cbcSMatt Macy# 738eda14cbcSMatt Macy# Return 739eda14cbcSMatt Macy# 0 if the event should be processed 740eda14cbcSMatt Macy# 1 if the event should be dropped 741eda14cbcSMatt Macy# 742eda14cbcSMatt Macy# State File Format 743eda14cbcSMatt Macy# time;tag 744eda14cbcSMatt Macy# 745eda14cbcSMatt Macyzed_rate_limit() 746eda14cbcSMatt Macy{ 747eda14cbcSMatt Macy local tag="$1" 748eda14cbcSMatt Macy local interval="${2:-${ZED_NOTIFY_INTERVAL_SECS}}" 749eda14cbcSMatt Macy local lockfile="zed.zedlet.state.lock" 750eda14cbcSMatt Macy local lockfile_fd=9 751eda14cbcSMatt Macy local statefile="${ZED_RUNDIR}/zed.zedlet.state" 752eda14cbcSMatt Macy local time_now 753eda14cbcSMatt Macy local time_prev 754eda14cbcSMatt Macy local umask_bak 755eda14cbcSMatt Macy local rv=0 756eda14cbcSMatt Macy 757eda14cbcSMatt Macy [ -n "${tag}" ] || return 0 758eda14cbcSMatt Macy 759eda14cbcSMatt Macy zed_lock "${lockfile}" "${lockfile_fd}" 760eda14cbcSMatt Macy time_now="$(date +%s)" 761eda14cbcSMatt Macy time_prev="$(grep -E "^[0-9]+;${tag}\$" "${statefile}" 2>/dev/null \ 762eda14cbcSMatt Macy | tail -1 | cut -d\; -f1)" 763eda14cbcSMatt Macy 764eda14cbcSMatt Macy if [ -n "${time_prev}" ] \ 765eda14cbcSMatt Macy && [ "$((time_now - time_prev))" -lt "${interval}" ]; then 766eda14cbcSMatt Macy rv=1 767eda14cbcSMatt Macy else 768eda14cbcSMatt Macy umask_bak="$(umask)" 769eda14cbcSMatt Macy umask 077 770eda14cbcSMatt Macy grep -E -v "^[0-9]+;${tag}\$" "${statefile}" 2>/dev/null \ 771eda14cbcSMatt Macy > "${statefile}.$$" 772eda14cbcSMatt Macy echo "${time_now};${tag}" >> "${statefile}.$$" 773eda14cbcSMatt Macy mv -f "${statefile}.$$" "${statefile}" 774eda14cbcSMatt Macy umask "${umask_bak}" 775eda14cbcSMatt Macy fi 776eda14cbcSMatt Macy 777eda14cbcSMatt Macy zed_unlock "${lockfile}" "${lockfile_fd}" 778eda14cbcSMatt Macy return "${rv}" 779eda14cbcSMatt Macy} 780eda14cbcSMatt Macy 781eda14cbcSMatt Macy 782eda14cbcSMatt Macy# zed_guid_to_pool (guid) 783eda14cbcSMatt Macy# 784eda14cbcSMatt Macy# Convert a pool GUID into its pool name (like "tank") 785eda14cbcSMatt Macy# Arguments 786eda14cbcSMatt Macy# guid: pool GUID (decimal or hex) 787eda14cbcSMatt Macy# 788eda14cbcSMatt Macy# Return 789eda14cbcSMatt Macy# Pool name 790eda14cbcSMatt Macy# 791eda14cbcSMatt Macyzed_guid_to_pool() 792eda14cbcSMatt Macy{ 793eda14cbcSMatt Macy if [ -z "$1" ] ; then 794eda14cbcSMatt Macy return 795eda14cbcSMatt Macy fi 796eda14cbcSMatt Macy 79716038816SMartin Matuska guid="$(printf "%u" "$1")" 79816038816SMartin Matuska $ZPOOL get -H -ovalue,name guid | awk '$1 == '"$guid"' {print $2; exit}' 799eda14cbcSMatt Macy} 800eda14cbcSMatt Macy 801eda14cbcSMatt Macy# zed_exit_if_ignoring_this_event 802eda14cbcSMatt Macy# 803eda14cbcSMatt Macy# Exit the script if we should ignore this event, as determined by 804eda14cbcSMatt Macy# $ZED_SYSLOG_SUBCLASS_INCLUDE and $ZED_SYSLOG_SUBCLASS_EXCLUDE in zed.rc. 805eda14cbcSMatt Macy# This function assumes you've imported the normal zed variables. 806eda14cbcSMatt Macyzed_exit_if_ignoring_this_event() 807eda14cbcSMatt Macy{ 808eda14cbcSMatt Macy if [ -n "${ZED_SYSLOG_SUBCLASS_INCLUDE}" ]; then 809eda14cbcSMatt Macy eval "case ${ZEVENT_SUBCLASS} in 810eda14cbcSMatt Macy ${ZED_SYSLOG_SUBCLASS_INCLUDE});; 811eda14cbcSMatt Macy *) exit 0;; 812eda14cbcSMatt Macy esac" 813eda14cbcSMatt Macy elif [ -n "${ZED_SYSLOG_SUBCLASS_EXCLUDE}" ]; then 814eda14cbcSMatt Macy eval "case ${ZEVENT_SUBCLASS} in 815eda14cbcSMatt Macy ${ZED_SYSLOG_SUBCLASS_EXCLUDE}) exit 0;; 816eda14cbcSMatt Macy *);; 817eda14cbcSMatt Macy esac" 818eda14cbcSMatt Macy fi 819eda14cbcSMatt Macy} 820