You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by zw...@apache.org on 2013/08/30 18:20:29 UTC

[16/50] git commit: Revert "TS-2143 Remove alarm email address support (and config)."

Revert "TS-2143 Remove alarm email address support (and config)."

This reverts commit 821d3fdd058c730aeba596bf2480fa8efb1ab27b.


Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/dec9a7f0
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/dec9a7f0
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/dec9a7f0

Branch: refs/heads/5.0.x
Commit: dec9a7f018a850f181c5ea86f0ba3a6ebfaa0221
Parents: 3a78753
Author: Leif Hedstrom <zw...@apache.org>
Authored: Fri Aug 23 09:22:15 2013 -0600
Committer: Leif Hedstrom <zw...@apache.org>
Committed: Fri Aug 23 09:23:31 2013 -0600

----------------------------------------------------------------------
 ci/jenkins/records.config              |   1 +
 lib/perl/lib/Apache/TS/AdminClient.pm  |   1 +
 lib/records/I_RecAlarms.h              |   8 ++
 lib/records/I_RecSignals.h             |   5 ++
 mgmt/Alarms.cc                         | 114 +++++++++++++++++++++++-----
 mgmt/Alarms.h                          |  12 ++-
 mgmt/BaseManager.h                     |   8 ++
 mgmt/LocalManager.cc                   |  13 ++++
 mgmt/RecordsConfig.cc                  |   2 +
 proxy/InkAPI.cc                        |  12 +++
 proxy/api/ts/experimental.h            |  15 ++++
 proxy/config/records.config.default.in |   1 +
 proxy/example_alarm_bin.sh             |  50 ++++++++++--
 13 files changed, 215 insertions(+), 27 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/dec9a7f0/ci/jenkins/records.config
----------------------------------------------------------------------
diff --git a/ci/jenkins/records.config b/ci/jenkins/records.config
index 702618f..239e901 100644
--- a/ci/jenkins/records.config
+++ b/ci/jenkins/records.config
@@ -43,6 +43,7 @@ CONFIG proxy.config.accept_threads INT 1
 # Local Manager
 #
 ##############################################################################
+CONFIG proxy.config.admin.admin_user STRING admin
 CONFIG proxy.config.admin.number_config_bak INT 3
 CONFIG proxy.config.admin.user_id STRING nobody
 ##############################################################################

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/dec9a7f0/lib/perl/lib/Apache/TS/AdminClient.pm
----------------------------------------------------------------------
diff --git a/lib/perl/lib/Apache/TS/AdminClient.pm b/lib/perl/lib/Apache/TS/AdminClient.pm
index 837cf16..f6fa827 100644
--- a/lib/perl/lib/Apache/TS/AdminClient.pm
+++ b/lib/perl/lib/Apache/TS/AdminClient.pm
@@ -264,6 +264,7 @@ The Apache Traffic Server Administration Manual will explain what these strings
 
  proxy.config.accept_threads
  proxy.config.task_threads
+ proxy.config.admin.admin_user
  proxy.config.admin.autoconf.localhost_only
  proxy.config.admin.autoconf.pac_filename
  proxy.config.admin.autoconf_port

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/dec9a7f0/lib/records/I_RecAlarms.h
----------------------------------------------------------------------
diff --git a/lib/records/I_RecAlarms.h b/lib/records/I_RecAlarms.h
index 25bebb9..985c656 100644
--- a/lib/records/I_RecAlarms.h
+++ b/lib/records/I_RecAlarms.h
@@ -47,4 +47,12 @@
 #define REC_ALARM_PROXY_HTTP_CONGESTED_SERVER   20
 #define REC_ALARM_PROXY_HTTP_ALLEVIATED_SERVER  21
 
+#define REC_ALARM_WDA_BILLING_CONNECTION_DIED   100
+#define REC_ALARM_WDA_BILLING_CORRUPTED_DATA    101
+#define REC_ALARM_WDA_XF_ENGINE_DOWN            102
+#define REC_ALARM_WDA_RADIUS_CORRUPTED_PACKETS  103
+
+#define REC_ALARM_ACC_ALARMS_START              200
+#define REC_ALARM_ACC_ALARMS_END                299
+
 #endif

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/dec9a7f0/lib/records/I_RecSignals.h
----------------------------------------------------------------------
diff --git a/lib/records/I_RecSignals.h b/lib/records/I_RecSignals.h
index 2e6f21b..0115e56 100644
--- a/lib/records/I_RecSignals.h
+++ b/lib/records/I_RecSignals.h
@@ -45,6 +45,11 @@
 #define REC_SIGNAL_HTTP_CONGESTED_SERVER        20
 #define REC_SIGNAL_HTTP_ALLEVIATED_SERVER       21
 
+#define REC_SIGNAL_WDA_BILLING_CONNECTION_DIED  100
+#define REC_SIGNAL_WDA_BILLING_CORRUPTED_DATA   101
+#define REC_SIGNAL_WDA_XF_ENGINE_DOWN           102
+#define REC_SIGNAL_WDA_RADIUS_CORRUPTED_PACKETS 103
+
 #define REC_SIGNAL_ACC_ALARMS_START             200
 #define REC_SIGNAL_ACC_ALARMS_END               299
 

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/dec9a7f0/mgmt/Alarms.cc
----------------------------------------------------------------------
diff --git a/mgmt/Alarms.cc b/mgmt/Alarms.cc
index 56f46d0..94fbbf8 100644
--- a/mgmt/Alarms.cc
+++ b/mgmt/Alarms.cc
@@ -211,6 +211,11 @@ Alarms::signalAlarm(alarm_t a, const char *desc, const char *ip)
   case MGMT_ALARM_PROXY_HTTP_CONGESTED_SERVER:
   case MGMT_ALARM_PROXY_HTTP_ALLEVIATED_SERVER:
     return;
+  case MGMT_ALARM_WDA_BILLING_CONNECTION_DIED:
+  case MGMT_ALARM_WDA_BILLING_CORRUPTED_DATA:
+  case MGMT_ALARM_WDA_XF_ENGINE_DOWN:
+    priority = 2;
+    break;
   default:
     priority = 2;
     break;
@@ -220,12 +225,19 @@ Alarms::signalAlarm(alarm_t a, const char *desc, const char *ip)
   if (desc && (priority == 1 || priority == 2) && !ip) {
 
     if (strcmp(prev_alarm_text, desc) == 0) {   /* a repeated alarm */
-      time_t time_delta = time(0) - last_sent;
-      if (time_delta < 900) {
-        mgmt_log("[Alarms::signalAlarm] Skipping Alarm: '%s'\n", desc);
-        return;
-      } else {
-        last_sent = time(0);
+
+      /* INKqa11884: repeated wireless alarms always signalled */
+      if (a != MGMT_ALARM_WDA_BILLING_CONNECTION_DIED &&
+          a != MGMT_ALARM_WDA_BILLING_CORRUPTED_DATA &&
+          a != MGMT_ALARM_WDA_XF_ENGINE_DOWN) {
+
+        time_t time_delta = time(0) - last_sent;
+        if (time_delta < 900) {
+          mgmt_log("[Alarms::signalAlarm] Skipping Alarm: '%s'\n", desc);
+          return;
+        } else {
+          last_sent = time(0);
+        }
       }
     } else {
       ink_strlcpy(prev_alarm_text, desc, sizeof(prev_alarm_text));
@@ -244,9 +256,11 @@ Alarms::signalAlarm(alarm_t a, const char *desc, const char *ip)
    * don't want every node in the cluster reporting the same alarm.
    */
   if (priority == 1 && alarm_bin && alarm_bin_path && !ip) {
-    execAlarmBin(desc, a);
+    execAlarmBin(desc);
   }
 
+
+
   ink_mutex_acquire(&mutex);
   if (!ip) {
     // if an OEM alarm, then must create the unique key alarm type;
@@ -257,8 +271,18 @@ Alarms::signalAlarm(alarm_t a, const char *desc, const char *ip)
     }
     snprintf(buf, sizeof(buf), "%d", a);
     if (ink_hash_table_lookup(local_alarms, buf, &hash_value) != 0) {
-      ink_mutex_release(&mutex);
-      return;
+      // INKqa11884: if wireless alarm already active, just
+      // update desc with new timestamp and skip to actions part
+      if (a == MGMT_ALARM_WDA_BILLING_CONNECTION_DIED ||
+          a == MGMT_ALARM_WDA_BILLING_CORRUPTED_DATA ||
+          a == MGMT_ALARM_WDA_XF_ENGINE_DOWN) {
+        Debug("alarm", "[signalAlarm] wireless alarm already active");
+        atmp = (Alarm *) hash_value;
+        goto ALARM_REPEAT;
+      } else {
+        ink_mutex_release(&mutex);
+        return;
+      }
     }
   } else {
     snprintf(buf, sizeof(buf), "%d-%s", a, ip);
@@ -267,8 +291,18 @@ Alarms::signalAlarm(alarm_t a, const char *desc, const char *ip)
       //   still active
       atmp = (Alarm *) hash_value;
       atmp->seen = true;
-      ink_mutex_release(&mutex);
-      return;
+
+      // INKqa11884: if wireless alarm already active, just
+      // update desc with new timstamp and skip to actions part
+      if (a == MGMT_ALARM_WDA_BILLING_CONNECTION_DIED ||
+          a == MGMT_ALARM_WDA_BILLING_CORRUPTED_DATA ||
+          a == MGMT_ALARM_WDA_XF_ENGINE_DOWN) {
+        Debug("alarm", "[Alarms::signalAlarm] wireless alarm already active");
+        goto ALARM_REPEAT;
+      } else {
+        ink_mutex_release(&mutex);
+        return;
+      }
     }
   }
 
@@ -289,6 +323,7 @@ Alarms::signalAlarm(alarm_t a, const char *desc, const char *ip)
     ink_hash_table_insert(remote_alarms, (InkHashTableKey) (buf), (atmp));
   }
 
+ALARM_REPEAT:
   // Swap desc with time-stamped description.  Kinda hackish
   // Temporary until we get a new
   // alarm system in place.  TS 5.0.0, 02/08/2001
@@ -364,7 +399,7 @@ Alarms::signalAlarm(alarm_t a, const char *desc, const char *ip)
   }
   /* Priority 2 alarms get signalled if they are the first unsolved occurence. */
   if (priority == 2 && alarm_bin && alarm_bin_path && !ip) {
-    execAlarmBin(desc, a);
+    execAlarmBin(desc);
   }
 
   return;
@@ -504,17 +539,29 @@ Alarms::checkSystemNAlert()
 }                               /* End Alarms::checkSystenNAlert */
 
 void
-Alarms::execAlarmBin(const char *desc, alarm_t a)
+Alarms::execAlarmBin(const char *desc)
 {
   char cmd_line[1024];
-  char alarm[80];
+  char *alarm_email_from_name = 0;
+  char *alarm_email_from_addr = 0;
+  char *alarm_email_to_addr = 0;
   bool found;
 
+  // get email info
+  alarm_email_from_name = REC_readString("proxy.config.product_name", &found);
+  if (!found)
+    alarm_email_from_name = 0;
+  alarm_email_from_addr = REC_readString("proxy.config.admin.admin_user", &found);
+  if (!found)
+    alarm_email_from_addr = 0;
+  alarm_email_to_addr = REC_readString("proxy.config.alarm_email", &found);
+  if (!found)
+    alarm_email_to_addr = 0;
+
   int status;
   pid_t pid;
 
   ink_filepath_make(cmd_line, sizeof(cmd_line), alarm_bin_path, alarm_bin);
-  snprintf(alarm, sizeof(alarm), "%d", a);
 
 #ifdef POSIX_THREAD
   if ((pid = fork()) < 0)
@@ -549,10 +596,21 @@ Alarms::execAlarmBin(const char *desc, alarm_t a)
       waitpid(pid, &status, 0); // to reap the thread
     }
   } else {
-    int res = execl(cmd_line, alarm_bin, desc, alarm, (char*)NULL);
-
+    int res;
+    if (alarm_email_from_name && alarm_email_from_addr && alarm_email_to_addr) {
+      res = execl(cmd_line, alarm_bin, desc, alarm_email_from_name, alarm_email_from_addr, alarm_email_to_addr, (char*)NULL);
+    } else {
+      res = execl(cmd_line, alarm_bin, desc, (char*)NULL);
+    }
     _exit(res);
   }
+
+
+
+  // free memory
+  ats_free(alarm_email_from_name);
+  ats_free(alarm_email_from_addr);
+  ats_free(alarm_email_to_addr);
 }
 
 //
@@ -563,8 +621,22 @@ Alarms::execAlarmBin(const char *desc, alarm_t a)
 const char *
 Alarms::getAlarmText(alarm_t id)
 {
-  if (id < alarmTextNum)
-    return alarmText[id];
-  else
-    return alarmText[0];      // "Unknown Alarm";
+  const char *wda_conn_died = "The connection to the billing system is broken. Unable to retrieve user profile.";
+  const char *wda_corr_data =
+    "Could not read user profile or URL list from the billing system. The data received doesn't have the expected format.";
+  const char *wda_xf_down = "The XF engine heartbeat could not be properly detected. It appears dead.";
+
+  switch (id) {
+  case MGMT_ALARM_WDA_BILLING_CONNECTION_DIED:
+    return wda_conn_died;
+  case MGMT_ALARM_WDA_BILLING_CORRUPTED_DATA:
+    return wda_corr_data;
+  case MGMT_ALARM_WDA_XF_ENGINE_DOWN:
+    return wda_xf_down;
+  default:
+    if (id < alarmTextNum)
+      return alarmText[id];
+    else
+      return alarmText[0];      // "Unknown Alarm";
+  }
 }

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/dec9a7f0/mgmt/Alarms.h
----------------------------------------------------------------------
diff --git a/mgmt/Alarms.h b/mgmt/Alarms.h
index a712d01..a58a350 100644
--- a/mgmt/Alarms.h
+++ b/mgmt/Alarms.h
@@ -75,8 +75,18 @@
 #define MGMT_ALARM_PROXY_HTTP_ALLEVIATED_SERVER  21     /* Congestion control -- alleviated server */
 #define MGMT_ALARM_PROXY_FTP_ERROR	         22
 
+// Wireless (WDA) alarms
+#define MGMT_ALARM_WDA_BILLING_CONNECTION_DIED   100
+#define MGMT_ALARM_WDA_BILLING_CORRUPTED_DATA    101
+#define MGMT_ALARM_WDA_XF_ENGINE_DOWN            102
+
 #define MGMT_ALARM_SAC_SERVER_DOWN		400
 
+// ACC alarms -- 200-300 -- I tried using just one, but a bunch of 'ACL was dropped'
+// warnings didn't get to the manager UI, that's badness.
+#define MGMT_ALARM_ACC_ALARMS_START              200
+#define MGMT_ALARM_ACC_ALARMS_END                299
+
 extern const char *alarmText[];
 extern const int alarmTextNum;
 
@@ -119,7 +129,7 @@ public:
   void clearUnSeen(char *ip);
 
   void checkSystemNAlert();
-  void execAlarmBin(const char *desc, alarm_t a);
+  void execAlarmBin(const char *desc);
 
   const char *getAlarmText(alarm_t id);
   InkHashTable *getLocalAlarms()

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/dec9a7f0/mgmt/BaseManager.h
----------------------------------------------------------------------
diff --git a/mgmt/BaseManager.h b/mgmt/BaseManager.h
index 80268a4..a8d268c 100644
--- a/mgmt/BaseManager.h
+++ b/mgmt/BaseManager.h
@@ -93,6 +93,14 @@
 #define MGMT_SIGNAL_HTTP_CONGESTED_SERVER   20  /* Congestion control -- congested server */
 #define MGMT_SIGNAL_HTTP_ALLEVIATED_SERVER  21  /* Congestion control -- alleviated server */
 
+// Wireless (WDA) plugin signal
+// Warning: 1. Don't change the # mapping 'cuase 3rd party software depends on them.
+//          2. Ensure 1:1 maps with alarms in Alarm.h
+#define INK_MGMT_SIGNAL_WDA_BILLING_CONNECTION_DIED  100
+#define INK_MGMT_SIGNAL_WDA_BILLING_CORRUPTED_DATA   101
+#define INK_MGMT_SIGNAL_WDA_XF_ENGINE_DOWN           102
+#define INK_MGMT_SIGNAL_WDA_RADIUS_CORRUPTED_PACKETS 103
+
 #define INK_MGMT_SIGNAL_ACC_ALARMS_START  200
 #define INK_MGMT_SIGNAL_ACC_ALARMS_END    299
 

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/dec9a7f0/mgmt/LocalManager.cc
----------------------------------------------------------------------
diff --git a/mgmt/LocalManager.cc b/mgmt/LocalManager.cc
index 79b1ef4..863a771 100644
--- a/mgmt/LocalManager.cc
+++ b/mgmt/LocalManager.cc
@@ -697,6 +697,16 @@ LocalManager::handleMgmtMsgFromProcesses(MgmtMessageHdr * mh)
     alarm_keeper->signalAlarm(MGMT_ALARM_PROXY_HTTP_ALLEVIATED_SERVER, data_raw);
     break;
     // Congestion Control - end
+  case INK_MGMT_SIGNAL_WDA_BILLING_CONNECTION_DIED:
+    alarm_keeper->signalAlarm(MGMT_ALARM_WDA_BILLING_CONNECTION_DIED, data_raw);
+    break;
+  case INK_MGMT_SIGNAL_WDA_BILLING_CORRUPTED_DATA:
+    alarm_keeper->signalAlarm(MGMT_ALARM_WDA_BILLING_CORRUPTED_DATA, data_raw);
+    break;
+  case INK_MGMT_SIGNAL_WDA_XF_ENGINE_DOWN:
+    alarm_keeper->signalAlarm(MGMT_ALARM_WDA_XF_ENGINE_DOWN, data_raw);
+    break;
+    // Wireless plugin signal - end
   case INK_MGMT_SIGNAL_SAC_SERVER_DOWN:
     alarm_keeper->signalAlarm(MGMT_ALARM_SAC_SERVER_DOWN, data_raw);
     break;
@@ -705,6 +715,9 @@ LocalManager::handleMgmtMsgFromProcesses(MgmtMessageHdr * mh)
     break;
   }
 
+  // #define MGMT_ALARM_ACC_ALARMS_START              200
+  // #define MGMT_ALARM_ACC_ALARMS_END                299
+
   if (mh->msg_id >= INK_MGMT_SIGNAL_ACC_ALARMS_START && mh->msg_id <= INK_MGMT_SIGNAL_ACC_ALARMS_END) {
     alarm_keeper->signalAlarm(mh->msg_id, data_raw);
   }

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/dec9a7f0/mgmt/RecordsConfig.cc
----------------------------------------------------------------------
diff --git a/mgmt/RecordsConfig.cc b/mgmt/RecordsConfig.cc
index 8e90ac1..93e8c7d 100644
--- a/mgmt/RecordsConfig.cc
+++ b/mgmt/RecordsConfig.cc
@@ -239,6 +239,8 @@ RecordElement RecordsConfig[] = {
   ,
   {RECT_CONFIG, "proxy.config.admin.autoconf.pac_filename", RECD_STRING, "proxy.pac", RECU_DYNAMIC, RR_NULL, RECC_NULL, NULL, RECA_NULL}
   ,
+  {RECT_CONFIG, "proxy.config.admin.admin_user", RECD_STRING, "admin", RECU_DYNAMIC, RR_REQUIRED, RECC_STR, ".+", RECA_NO_ACCESS}
+  ,
   {RECT_CONFIG, "proxy.config.admin.number_config_bak", RECD_INT, "3", RECU_NULL, RR_NULL, RECC_NULL, NULL, RECA_NULL}
   ,
   {RECT_CONFIG, "proxy.config.admin.user_id", RECD_STRING, TS_PKGSYSUSER, RECU_NULL, RR_REQUIRED, RECC_NULL, NULL, RECA_NULL}

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/dec9a7f0/proxy/InkAPI.cc
----------------------------------------------------------------------
diff --git a/proxy/InkAPI.cc b/proxy/InkAPI.cc
index 289bbb2..6ae68ea 100644
--- a/proxy/InkAPI.cc
+++ b/proxy/InkAPI.cc
@@ -6975,6 +6975,18 @@ TSMgmtConfigIntSet(const char *var_name, TSMgmtInt value)
   return TS_SUCCESS;
 }
 
+
+/* Alarm */
+/* return type is "int" currently, it should be TSReturnCode */
+void
+TSSignalWarning(TSAlarmType code, char *msg)
+{
+  sdk_assert(code >= TS_SIGNAL_WDA_BILLING_CONNECTION_DIED && code <= TS_SIGNAL_WDA_RADIUS_CORRUPTED_PACKETS);
+  sdk_assert(sdk_sanity_check_null_ptr((void*)msg) == TS_SUCCESS);
+
+  REC_SignalWarning(code, msg);
+}
+
 void
 TSICPFreshnessFuncSet(TSPluginFreshnessCalcFunc funcp)
 {

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/dec9a7f0/proxy/api/ts/experimental.h
----------------------------------------------------------------------
diff --git a/proxy/api/ts/experimental.h b/proxy/api/ts/experimental.h
index 1eb2da8..282bd06 100644
--- a/proxy/api/ts/experimental.h
+++ b/proxy/api/ts/experimental.h
@@ -314,6 +314,21 @@ extern "C"
 #define TS_NET_EVENT_DATAGRAM_OPEN	      TS_EVENT_INTERNAL_211
 #define TS_NET_EVENT_DATAGRAM_ERROR          TS_EVENT_INTERNAL_212
 
+  typedef enum
+    {
+      TS_SIGNAL_WDA_BILLING_CONNECTION_DIED = 100,
+      TS_SIGNAL_WDA_BILLING_CORRUPTED_DATA = 101,
+      TS_SIGNAL_WDA_XF_ENGINE_DOWN = 102,
+      TS_SIGNAL_WDA_RADIUS_CORRUPTED_PACKETS = 103
+    } TSAlarmType;
+
+  /* ===== Alarm ===== */
+  /****************************************************************************
+   *  ??
+   *  contact: OXYGEN
+   ****************************************************************************/
+  tsapi void TSSignalWarning(TSAlarmType code, char *msg);
+
   /*****************************************************************************
    * 			Cluster RPC API support 			     *
    *****************************************************************************/

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/dec9a7f0/proxy/config/records.config.default.in
----------------------------------------------------------------------
diff --git a/proxy/config/records.config.default.in b/proxy/config/records.config.default.in
index 848fc8e..549001a 100644
--- a/proxy/config/records.config.default.in
+++ b/proxy/config/records.config.default.in
@@ -43,6 +43,7 @@ CONFIG proxy.config.accept_threads INT 1
 # Local Manager
 #
 ##############################################################################
+CONFIG proxy.config.admin.admin_user STRING admin
 CONFIG proxy.config.admin.number_config_bak INT 3
 CONFIG proxy.config.admin.user_id STRING @pkgsysuser@
 ##############################################################################

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/dec9a7f0/proxy/example_alarm_bin.sh
----------------------------------------------------------------------
diff --git a/proxy/example_alarm_bin.sh b/proxy/example_alarm_bin.sh
index b970779..c288f07 100644
--- a/proxy/example_alarm_bin.sh
+++ b/proxy/example_alarm_bin.sh
@@ -18,14 +18,54 @@
 
 #
 #   Example alarm bin program. Proxy manager execs this script with
-#   a brief message as its argument, and an alarm code.
+# a brief message as its argument. This program sends mail to the
+# e-mail address passed in by the caller.  The subject of the
+# e-mail is the passed in message, and a 'date' stamp is added 
+# as the body.
 #
-if [ $# -eq 2 ]; then
-  # two parameters, from ATS
-    echo "$0: desc=$1 alarm=$2"
+ostype=`(uname -s) 2>/dev/null`
+if [ "$ostype" = "Linux" ]; then
+SENDMAIL="/usr/sbin/sendmail"
+else
+  SENDMAIL="/usr/lib/sendmail"
+fi
+
+if [ ! -x $SENDMAIL ]; then
+    echo "$0: Could not find $SENDMAIL program"
+    exit 1
+fi
+
+if [ $# -eq 1 ]; then
+  # if only one parameter, then no email information was provided
+  msg="`hostname` $1"
+  echo
+  echo "[example_alarm_bin.sh] no e-mail sent: $msg"
+  echo
+  exit 0
+
+elif [ $# -eq 4 ]; then
+  # if four parameters, the caller specified email information
+  msg="`hostname` $1"
+  email_from_name=$2
+  email_from_addr=$3
+  email_to_addr=$4
+
+  result=`(echo "From: $email_from_name <$email_from_addr>"; echo "To: $email_to_addr"; echo "Subject: $msg"; echo; date) | $SENDMAIL -bm $email_to_addr`
+  if [ "$result" = "" ]; then
+    echo
+    echo "[example_alarm_bin.sh] sent alarm: $msg";
+    echo
+    exit 0
+  else
+    echo
+    echo "[example_alarm_bin.sh] sendmail failed"
+    echo
+    exit 1
+  fi
+
 else
   # give a little help
-  echo "Usage: example_alarm_bin.sh <message> <alarm type ID>"
+  echo "Usage: example_alarm_bin.sh <message> [<email_from_name> <email_from_addr> <email_to_addr>]"
   exit
 
 fi