diff --git a/scripts/s25vmail/README b/scripts/s25vmail/README
deleted file mode 100644
index 040bf5ae23..0000000000
--- a/scripts/s25vmail/README
+++ /dev/null
@@ -1,63 +0,0 @@
-This directory contains software used for interfacing the
-FreeSWITCH voicemail application with the AT&T (aka Lucent
-aka Avaya) System 25 PBX. It's possible that System 75
-and Definity PBXs may also work.
-
-s25vmail.js goes into the FreeSWITCH scripts directory.
-s25vmail_mwi.c should be compiled and the resulting binary
-put into the FreeSWITCH bin directory. Modify the FreeSWITCH
-rc.d script to also start / stop s25vmail_mwi.
-
-Configuration fragments look something like:
-
- conf/openzap.conf:
-
- [span zt]
- ; A204DX
- name => OpenZAP
- dtmf_hangup = ##99
-
- number => 551
- fxo-channel => 49
-
- number => 552
- fxo-channel => 50
-
- number => 553
- fxo-channel => 51
-
- number => 554
- fxo-channel => 52
-
- conf/dialplan/default.xml
-
-
-
-
-
-
-
-Tested using FreeSWITCH SVN 10428 running on FreeBSD 6.3
-with a Sangoma A200DX Analog Series w/ Echo Cancellation
-ports card containing 2 FXO modules.
-
-Note that the PBX is * very * sensitive to how long it takes
-for the line to be hung up after it sends the DTMF hangup
-command. Failure to apply the following patch will cause
-the PBX to occasionally believe that some vmail lines were
-off hook for too long and are therfore out of service.
-
-Index: src/zap_io.c
-===================================================================
---- src/zap_io.c (revision 745)
-+++ src/zap_io.c (working copy)
-@@ -1728,7 +1728,8 @@
- zchan->dtmf_hangup_buf[zchan->span->dtmf_hangup_len - 1] = *p;
- if (!strcmp(zchan->dtmf_hangup_buf, zchan->span->dtmf_hangup)) {
- zap_log(ZAP_LOG_DEBUG, "DTMF hangup detected.\n");
-- zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_HANGUP);
-+ zchan->caller_data.hangup_cause = ZAP_CAUSE_NORMAL_CLEARING;
-+ zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_DOWN);
- break;
- }
- }
diff --git a/scripts/s25vmail/README.park b/scripts/s25vmail/README.park
deleted file mode 100644
index a6f1519803..0000000000
--- a/scripts/s25vmail/README.park
+++ /dev/null
@@ -1,72 +0,0 @@
-This directory contains software for configuring FreeSWITCH
-to provide AT&T (aka Lucent aka Avaya) System 25 PBX compatible
-park and pickup park functions. Specifically:
-
- a) Putting a call on hold and then dialing *5 will park the
- call on your phone.
-
- b) Dialing *8 followed by an extension will pickup a call parked
- on that extension.
-
-as a bonus:
-
- c) Doing a blind transfer of a call to *5 will park the call
- on your phone.
-
- d) Doing a blind transfer of a call to *5 followed by an extension
- will park the call on that extension.
-
- e) Dialing *8 without an extension will prompt for an extension.
-
-s25park.js goes into the FreeSWITCH scripts directory.
-
-Configuration fragments look something like:
-
- conf/dialplan/default.xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-The system25 park and pickup dialplan patterns are designed
-to only consider four digit extensions for local parking.
-"system25_pickup_from_extension" recognizes three digit
-extensions as being parked on a foreign PBX ... modify
-as appropriate for your installation.
-
-Be aware that the default dialplan contains an extension
-called "group-intercept" which needs to be commented out
-in order for "system25_pickup" to work since they both
-match *8.
-
-Tested using FreeSWITCH SVN 13769 running on FreeBSD 6.4.
diff --git a/scripts/s25vmail/s25park.js b/scripts/s25vmail/s25park.js
deleted file mode 100644
index a6be33c967..0000000000
--- a/scripts/s25vmail/s25park.js
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * File: s25park.js
- * Purpose: Implement AT&T System 25 PBX style parking.
- * Machine: OS:
- * Author: John Wehle Date: June 9, 2009
- */
-
-/*
- * Copyright (c) 2009 Feith Systems and Software, Inc.
- * All Rights Reserved
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * * Neither the name of the original author; nor the names of any contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
- * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-/* RE to sanity check that the caller id is a valid extension */
-var extRE = /^[0-9]{3,4}$/g;
-
-
-var dtmf_digits;
-
-function on_dtmf (session, type, obj, arg)
- {
-
- if (type == "dtmf") {
- dtmf_digits += obj.digit;
- return false;
- }
-
- return true;
- }
-
-
-function normalize_channel_name (name, direction, ip_addr)
- {
- var re = /^sofia\//g;
- var length = name.search (re);
- var new_name = name;
-
- if (length == -1)
- return new_name;
-
- if (direction == "inbound") {
- re = /@.*$/g;
-
- new_name = name.replace (re, "@" + ip_addr);
- }
- else if (direction == "outbound") {
- re = /\/sip:(.*@[^:]*):.*$/g;
-
- new_name = name.replace (re, "/$1");
- }
-
- return new_name;
- }
-
-
-session.answer ();
-
-session.execute ("sleep", "1000");
-
-/*
- * Figure out the normalized form of the requester's channel name.
- */
-
-var requester_channel_name = normalize_channel_name (
- session.getVariable ("channel_name"), "inbound",
- session.getVariable ("network_addr"));
-
-/*
- * Find the uuid for a call on the requester's phone.
- */
-
-var channels = apiExecute ("show", "channels as xml");
-var re = /\s+$/g;
-var length = channels.search (re);
-
-if (length == -1)
- length = channels.length;
-
-channels = channels.substring (0, length);
-
-var xchannels = new XML (channels);
-var our_uuid = session.getVariable ("uuid");
-var requester_uuid = "";
-
-for each (var channel in xchannels.row) {
- if (channel.uuid.toString () == our_uuid)
- continue;
-
- var channel_name = normalize_channel_name (channel.name.toString (),
- channel.direction.toString (), channel.ip_addr.toString ());
-
- if (channel_name == requester_channel_name) {
- requester_uuid = channel.uuid.toString ();
- break;
- }
- }
-
-if (requester_uuid == "") {
- session.sayPhrase ("voicemail_invalid_extension", "#", "", on_dtmf, "");
- session.hangup ();
- exit ();
- }
-
-/*
- * Find the peer uuid.
- */
-
-var udump = apiExecute ("uuid_dump", requester_uuid + " xml");
-var re = /\s+$/g;
-var length = udump.search (re);
-
-if (length == -1)
- length = udump.length;
-
-udump = udump.substring (0, length);
-
-var xudump = new XML (udump);
-var uuid = xudump.headers['Other-Leg-Unique-ID'].toString ();
-
-if (uuid == "") {
- session.sayPhrase ("voicemail_invalid_extension", "#", "", on_dtmf, "");
- session.hangup ();
- exit ();
- }
-
-var requester_id_number = session.getVariable ("caller_id_number");
-
-if (requester_id_number.search (extRE) == -1) {
- session.sayPhrase ("voicemail_invalid_extension", "#", "", on_dtmf, "");
- session.hangup ();
- exit ();
- }
-
-apiExecute ("uuid_setvar", uuid + " hangup_after_bridge false");
-apiExecute ("uuid_transfer", uuid + " *5" + requester_id_number + " XML default");
-
-/*
- * Provide confirmation beeps followed by some silence.
- */
-
-var confirmation = "tone_stream://L=3;%(100,100,350,440)";
-
-session.execute ("playback", confirmation);
-
-var i;
-
-for (i = 0; session.ready () && i < 100; i++)
- session.execute("sleep", "100");
-
-exit ();
diff --git a/scripts/s25vmail/s25vmail.js b/scripts/s25vmail/s25vmail.js
deleted file mode 100644
index 5c4e8643f6..0000000000
--- a/scripts/s25vmail/s25vmail.js
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * File: s25vmail.js
- * Purpose: Invoke voicemail based on AT&T System 25 PBX voicemail mode codes
- * Machine: OS:
- * Author: John Wehle Date: June 24, 2008
- *
- * The message waiting indicator is handled by a separate program.
- */
-
-/*
- * Copyright (c) 2008 Feith Systems and Software, Inc.
- * All Rights Reserved
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * * Neither the name of the original author; nor the names of any contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
- * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-var id_digits_required = 3;
-
-var digitTimeOut = 3000;
-var interDigitTimeOut = 1000;
-var absoluteTimeOut = 10000;
-
-
-var dtmf_digits = "";
-
-function on_dtmf (session, type, obj, arg)
- {
-
- if (type == "dtmf") {
- dtmf_digits += obj.digit;
- }
-
- return true;
- }
-
-
-function prompt_for_id ()
- {
- var dto;
- var id;
- var index;
- var repeat;
-
- dtmf_digits = "";
- id = "";
- repeat = 0;
-
- while (session.ready () && repeat < 3) {
- session.flushDigits ();
-
- /* play phrase - if digit keyed while playing callback will catch them*/
- session.sayPhrase ("voicemail_enter_id", "#", "", on_dtmf, "");
-
- if (! session.ready ())
- return "";
-
- id = dtmf_digits;
-
- if (id.indexOf ('#') == -1) {
- dto = digitTimeOut;
- if (dtmf_digits.length != 0)
- dto = interDigitTimeOut;
- dtmf_digits = session.getDigits (5, '#', dto,
- interDigitTimeOut, absoluteTimeOut);
- id += dtmf_digits;
- id += '#';
- }
-
- /* a valid id must meet the minimum length requirements */
- if ((index = id.indexOf ('#')) >= id_digits_required) {
- id = id.substring (0,index);
- break;
- }
-
- dtmf_digits = "";
- id = "";
- repeat++;
- }
-
- return id;
- }
-
-
-var start = "";
-var mode = "";
-var from = "";
-var to = "";
-
-var domain = session.getVariable ("domain");
-
-session.answer ();
-
-start = session.getDigits (1, '', digitTimeOut,
- interDigitTimeOut, absoluteTimeOut);
-
-if (start != "#") {
- var destination_number = session.getVariable ("destination_number");
-
- console_log ("err", destination_number + " received an invalid VMAIL start code from PBX\n");
- if (session.ready ())
- session.sayPhrase ("voicemail_goodbye", "#", "", on_dtmf, "");
- else
- console_log ("err", "Possibly due to early hangup from PBX\n");
- session.hangup ();
- exit();
- }
-
-mode = session.getDigits (5, '#', digitTimeOut,
- interDigitTimeOut, absoluteTimeOut);
-
-from = session.getDigits (5, '#', digitTimeOut,
- interDigitTimeOut, absoluteTimeOut);
-
-to = session.getDigits (5, '#', digitTimeOut,
- interDigitTimeOut, absoluteTimeOut);
-
-session.execute("sleep", "1000");
-
-// Verify that the proper parameters are present
-switch (mode) {
-
- // Direct Inside Access
- case "00":
- if (isNaN (parseInt (from, 10))) {
- console_log ("err", "Invalid VMAIL calling PDC from PBX\n");
- break;
- }
-
- session.setVariable ("voicemail_authorized", "false");
- session.execute ("voicemail", "check default " + domain + " " + from);
- break;
-
- // Direct Dial Access
- case "01":
- from = prompt_for_id ();
-
- if (! session.ready ()) {
- session.hangup ();
- exit();
- }
-
- if (isNaN (parseInt (from, 10))) {
- console_log ("err", "Invalid VMAIL mailbox from caller\n");
- break;
- }
-
- session.setVariable ("voicemail_authorized", "false");
- session.execute ("voicemail", "check default " + domain + " " + from);
- break;
-
- // Coverage - caller is inside
- case "02":
- if (isNaN (parseInt (from, 10)) || isNaN (parseInt (to, 10))) {
- console_log ("err", "Invalid VMAIL calling or called PDC from PBX\n");
- break;
- }
-
- session.setVariable ("effective_caller_id_name", "inside caller");
- session.setVariable ("effective_caller_id_number", from);
-
- session.execute ("voicemail", "default " + domain + " " + to);
- break;
-
- // Coverage - caller is dial
- case "03":
- if (isNaN (parseInt (to, 10))) {
- console_log ("err", "Invalid VMAIL called PDC from PBX\n");
- break;
- }
-
- session.setVariable ("effective_caller_id_name", "outside caller");
- session.setVariable ("effective_caller_id_number", "Unknown");
-
- session.execute ("voicemail", "default " + domain + " " + to);
- break;
-
- // Coverage - not yet defined
- case "04":
- break;
-
- // Leave Word Calling
- case "05":
- if (isNaN (parseInt (from, 10)) || isNaN (parseInt (to, 10))) {
- console_log ("err", "Invalid VMAIL calling or called PDC from PBX\n");
- break;
- }
- break;
-
- // Refresh MW lamps
- case "06":
- break;
-
- // Voice Port failed to answer
- case "08":
- if (isNaN (parseInt (to, 10))) {
- console_log ("err", "Invalid VMAIL PDC from PBX\n");
- break;
- }
-
- console_log ("err", "PBX reports problem with VMAIL PDC " + to + "\n");
- break;
-
- // Unknown
- default:
- console_log ("err", "Invalid VMAIL mode code from PBX\n");
- break;
- }
-
-exit();
diff --git a/scripts/s25vmail/s25vmail_mwi.c b/scripts/s25vmail/s25vmail_mwi.c
deleted file mode 100644
index d9c6798d7c..0000000000
--- a/scripts/s25vmail/s25vmail_mwi.c
+++ /dev/null
@@ -1,983 +0,0 @@
-/*
- * File: s25vmail_mwi.c
- * Purpose: Send AT&T System 25 PBX MWI DTMF based on MWI events
- * Machine: OS:
- * Author: John Wehle Date: July 24, 2008
- *
- * Tested using a Zyxel U90e configured using:
- *
- * at OK at&f OK at&d3&y2q2 OK ats0=0s2=255s15.7=0s18=4s35.1=0 OK
- * ats38.3=1s42.3=1s42.6=1 OK atl0 OK at&w OK at&v
- *
- * though just about any modem should work. Preferred settings are
- *
- * DTR OFF causes hangup and reset from profile 0
- * RTS / CTS flow control
- * allow abort during modem handshake
- * auto answer off
- * ring message off
- */
-
-/*
- * Copyright (c) 2008 Feith Systems and Software, Inc.
- * All Rights Reserved
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * * Neither the name of the original author; nor the names of any contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
- * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-
-#define LOGFILE "/var/log/s25vmail_mwi.log"
-
-
-static const char *MyName = "s25vmail_mwi";
-
-static int daimon = 0;
-static int error_msg_throttle = 0;
-static volatile int shutdown_server = 0;
-
-
-static void
-debugmsg (const char *fmt, ...)
- {
- char message[256];
- va_list args;
-
- if (daimon)
- return;
-
- va_start (args, fmt);
- vsprintf (message, fmt, args);
- va_end (args);
-
- fprintf (stderr, "%s: %s", MyName, message);
- if ( !strchr (message, '\n'))
- fprintf (stderr, "\n");
- fflush (stderr);
- }
-
-
-static void
-errmsg (const char *fmt, ...)
- {
- char time_stamp[256];
- struct tm *tmp;
- time_t now;
- va_list args;
-
- if (! daimon) {
- fprintf (stderr, "%s: ", MyName);
-
- va_start (args, fmt);
- vfprintf (stderr, fmt, args);
- va_end (args);
-
- if (! strchr (fmt, '\n'))
- fputc ('\n', stderr);
-
- fflush (stderr);
- return;
- }
-
- if (error_msg_throttle)
- return;
-
- time (&now);
-
- if ( !(tmp = localtime (&now)) ) {
- fprintf (stderr, "%s: errmsg -- localtime failed.\n", MyName);
- perror (MyName);
- fflush (stderr);
- return;
- }
-
- strftime (time_stamp, sizeof (time_stamp), "%b %d %H:%M:%S", tmp);
- fprintf (stderr, "%s %s[%d]: ", time_stamp, MyName, (int)getpid ());
-
- va_start (args, fmt);
- vfprintf (stderr, fmt, args);
- va_end (args);
-
- if (! strchr (fmt, '\n'))
- fputc ('\n', stderr);
-
- fflush (stderr);
- }
-
-
-static void
-catch_signal ()
- {
-
- shutdown_server = 1;
- }
-
-
-static void
-daemonize()
- {
-
-#ifdef SIGTSTP
- (void)signal(SIGTSTP, SIG_IGN);
-#endif
-#ifdef SIGTTIN
- (void)signal(SIGTTIN, SIG_IGN);
-#endif
-#ifdef SIGTTOU
- (void)signal(SIGTTOU, SIG_IGN);
-#endif
-
- switch (fork ()) {
- case 0:
- break;
-
- case -1:
- fprintf (stderr, "%s: daemonize -- fork failed.", MyName);
- perror (MyName);
- exit (1);
- /* NOTREACHED */
- break;
-
- default:
- exit (0);
- /* NOTREACHED */
- break;
- }
-
- setsid();
-
- close (0);
- close (1);
- close (2);
-
- (void)open ("/dev/null", O_RDWR);
- (void)open ("/dev/null", O_RDWR);
- (void)open (LOGFILE, O_WRONLY | O_APPEND | O_CREAT, 0644);
-
- daimon = 1;
- }
-
-
-static void
-install_signal_handlers ()
- {
- struct sigaction act;
-
- memset (&act, '\0', sizeof (act));
-
- act.sa_handler = catch_signal;
- sigemptyset (&act.sa_mask);
- act.sa_flags = 0;
-
- if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
- sigaction (SIGHUP, &act, NULL);
- if (signal (SIGINT, SIG_IGN) != SIG_IGN)
- sigaction (SIGINT, &act, NULL);
- (void)sigaction (SIGTERM, &act, NULL);
- }
-
-
-static int
-connect_to_service (const char *hostname, const char *port)
- {
- int sock;
- struct hostent *hp;
- struct in_addr address;
- struct servent *servp;
- struct sockaddr_in sin;
-
- if ((sock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
- char *errstr = strerror (errno);
-
- errmsg ("socket failed\n");
- errmsg (errstr);
- return -1;
- }
-
- memset (&sin, 0, sizeof (sin));
-
- if (isalpha (hostname[0])) {
- if ( !(hp = gethostbyname (hostname))) {
- char *errstr = strerror (errno);
-
- errmsg ("gethostbyname failed\n");
- errmsg (errstr);
- close (sock);
- return -1;
- }
- if (hp->h_addrtype != AF_INET) {
- errmsg ("gethostbyname returned unsupported family\n");
- close (sock);
- return -1;
- }
- memcpy (&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
- }
- else {
- address.s_addr = inet_addr (hostname);
-
- if ((long)address.s_addr == -1) {
- char *errstr = strerror (errno);
-
- errmsg ("inet_addr failed\n");
- errmsg (errstr);
- close (sock);
- return -1;
- }
- sin.sin_addr.s_addr = address.s_addr;
- }
-
- if (isalpha (*port)) {
- if ( !(servp = getservbyname(port, "tcp"))) {
- char *errstr = strerror (errno);
-
- errmsg ("getservbyname failed\n");
- errmsg (errstr);
- close (sock);
- return -1;
- }
- sin.sin_port = servp->s_port;
- }
- else
- sin.sin_port = htons ((unsigned short)atoi (port));
-
- sin.sin_family = AF_INET;
-
- if (connect (sock, (struct sockaddr *)&sin, sizeof(sin)) == -1) {
- char *errstr = strerror (errno);
-
- errmsg ("connect failed\n");
- errmsg (errstr);
- close (sock);
- return -1;
- }
-
- debugmsg ("Connected to service\n");
-
- return sock;
- }
-
-
-static ssize_t
-read_line (int fd, char *buf, size_t buf_len)
- {
- size_t l;
- ssize_t nbytes_read;
-
- l = 0;
-
- for ( ; ; ) {
- nbytes_read = read (fd, &buf[l], 1);
-
- if (nbytes_read < 0) {
- char *errstr = strerror (errno);
-
- errmsg ("read failed in middle of line\n");
- errmsg (errstr);
- return -1;
- }
-
- if (nbytes_read == 0) {
- if (l)
- errmsg ("EOF in middle of line\n");
- return l ? -1 : 0;
- }
-
- if (buf[l] == '\n') {
- while (l && buf[l - 1] == '\r')
- l--;
- buf[l++] = '\0';
- break;
- }
-
- l++;
-
- if (l == buf_len) {
- errmsg ("line too long\n");
- return -1;
- }
- }
-
- return l;
- }
-
-
-static int
-read_trailing_newline(int fd)
- {
- char c;
- ssize_t nbytes_read;
-
- nbytes_read = read (fd, &c, 1);
-
- if (nbytes_read < 0) {
- char *errstr = strerror (errno);
-
- errmsg ("read failed in trailing newline\n");
- errmsg (errstr);
- return -1;
- }
-
- if (nbytes_read == 0) {
- errmsg ("EOF in trailing newline\n");
- return -1;
- }
-
- if (c != '\n') {
- errmsg ("missing trailing newline\n");
- return -1;
- }
-
- return 0;
- }
-
-
-static char *
-retrieve_message (int fd)
- {
- char cl_buf[64];
- char ct_buf[64];
- char *h;
- char *m;
- ssize_t cl;
- ssize_t nbytes_read;
- size_t l;
- size_t nbytes_to_read;
-
- if (shutdown_server)
- return NULL;
-
- /*
- * Read / parse Content-Length and Content-Type.
- */
-
- nbytes_read = read_line (fd, cl_buf, sizeof (cl_buf));
-
- if (nbytes_read < 0) {
- errmsg ("read_line failed\n");
- return NULL;
- }
-
- if (nbytes_read == 0) {
-
- /*
- * EOF
- */
-
- return NULL;
- }
-
- nbytes_read = read_line (fd, ct_buf, sizeof (ct_buf));
-
- if (nbytes_read < 0) {
- errmsg ("read_line failed\n");
- return NULL;
- }
-
- if (nbytes_read == 0) {
- errmsg ("EOF in middle of headers\n");
- return NULL;
- }
-
- h = "Content-Length: ";
- l = strlen (h);
-
- if (strncmp (cl_buf, h, l) != 0) {
-
- /*
- * If the message header doesn't being with Content-Length,
- * then it needs to be a Content-Type we understand.
- */
-
- h = "Content-Type: ";
- l = strlen (h);
-
- if (strncmp (cl_buf, h, l) != 0) {
- errmsg ("missing Content-Type\n");
- return NULL;
- }
-
- if (strcmp (&cl_buf[l], "auth/request") != 0
- && strcmp (&cl_buf[l], "command/reply") != 0) {
- errmsg ("Unsupported Content-Type\n");
- return NULL;
- }
-
- if (ct_buf[0])
- if (read_trailing_newline (fd) < 0) {
- return NULL;
- }
-
- m = malloc (strlen (cl_buf) + 1 + strlen (ct_buf) + 1 + 1);
-
- if (! m) {
- char *errstr = strerror (errno);
-
- errmsg ("malloc failed\n");
- errmsg (errstr);
- return NULL;
- }
-
- sprintf (m, "%s\n%s\n", cl_buf, ct_buf);
-
- return m;
- }
-
- cl = atoi (&cl_buf[l]);
-
- if (cl <= 0) {
- errmsg ("Content-Length must be greater than zero\n");
- return NULL;
- }
-
- h = "Content-Type: ";
- l = strlen (h);
-
- if (strncmp (ct_buf, h, l) != 0) {
- errmsg ("missing Content-Type\n");
- return NULL;
- }
-
- if (strcmp (&ct_buf[l], "text/event-plain") != 0) {
- errmsg ("Unsupported Content-Type\n");
- return NULL;
- }
-
- if (read_trailing_newline (fd) < 0) {
- return NULL;
- }
-
- /*
- * Read the event.
- */
-
- m = malloc (cl);
-
- if (! m) {
- char *errstr = strerror (errno);
-
- errmsg ("malloc failed\n");
- errmsg (errstr);
- return NULL;
- }
-
- for (nbytes_to_read = cl; nbytes_to_read; nbytes_to_read -= nbytes_read) {
- nbytes_read = read (fd, m + (cl - nbytes_to_read), nbytes_to_read);
-
- if (nbytes_read < 0) {
- char *errstr = strerror (errno);
-
- errmsg ("read failed in middle of message\n");
- errmsg (errstr);
- free (m);
- return NULL;
- }
-
- if (nbytes_read == 0) {
- errmsg ("EOF in middle of message\n");
- free (m);
- return NULL;
- }
- }
-
- if (m[cl - 2] != '\n' || m[cl - 1] != '\n') {
- errmsg ("Message is missing trailing newlines\n");
- free (m);
- return NULL;
- }
-
- return m;
- }
-
-
-static int
-send_password (int fd, const char *passwd)
- {
- char *h;
- char *last;
- char *m;
- char *p;
- int l;
- size_t ml;
-
- m = retrieve_message (fd);
- if (! m)
- return -1;
-
- p = strtok_r (m, "\n", &last);
-
- h = "Content-Type: auth/request";
-
- if (strcmp (p, h) != 0) {
- errmsg ("Content-Type wasn't auth/request\n");
- free (m);
- return -1;
- }
-
- free (m);
-
- l = snprintf (NULL, 0, "auth %s\n\n", passwd);
- if (l <= 0) {
- errmsg ("snprintf failed\n");
- return -1;
- }
- l++;
-
- m = malloc (l);
- if (! m) {
- char *errstr = strerror (errno);
-
- errmsg ("malloc failed\n");
- errmsg (errstr);
- return -1;
- }
-
- ml = snprintf (m, l, "auth %s\n\n", passwd);
- if ((ml + 1) != l) {
- errmsg ("snprintf failed\n");
- free (m);
- return -1;
- }
-
- if (write (fd, m, ml) != ml) {
- char *errstr = strerror (errno);
-
- errmsg ("write failed\n");
- errmsg (errstr);
- free (m);
- return -1;
- }
-
- m = retrieve_message (fd);
- if (! m )
- return -1;
-
- p = strtok_r (m, "\n", &last);
-
- h = "Content-Type: command/reply";
-
- if (! p || strcmp (p, h) != 0) {
- errmsg ("Content-Type wasn't command/reply\n");
- free (m);
- return -1;
- }
-
- p = strtok_r (NULL, "\n", &last);
-
- h = "Reply-Text: +OK accepted";
-
- if (! p || strcmp (p, h) != 0) {
- errmsg ("auth wasn't accepted\n");
- free (m);
- return -1;
- }
-
- free (m);
-
- debugmsg ("Logged into service\n");
-
- return 0;
- }
-
-
-static int
-enable_mwi_event (int fd)
- {
- char *h;
- char *last;
- char *m;
- char *p;
- size_t ml;
-
- m = "event plain MESSAGE_WAITING\n\n";
- ml = strlen (m);
-
- if (write (fd, m, ml) != ml) {
- char *errstr = strerror (errno);
-
- errmsg ("write failed\n");
- errmsg (errstr);
- return -1;
- }
-
- m = retrieve_message (fd);
- if (! m )
- return -1;
-
- p = strtok_r (m, "\n", &last);
-
- h = "Content-Type: command/reply";
-
- if (! p || strcmp (p, h) != 0) {
- errmsg ("Content-Type wasn't command/reply\n");
- free (m);
- return -1;
- }
-
- p = strtok_r (NULL, "\n", &last);
-
- h = "Reply-Text: +OK event listener enabled plain";
-
- if (! p || strcmp (p, h) != 0) {
- errmsg ("event wasn't enabled\n");
- free (m);
- return -1;
- }
-
- free (m);
-
- debugmsg ("Enabled message waiting event\n");
-
- return 0;
- }
-
-
-static int
-process_mwi_event (char *m, const char *device)
- {
- char cbuf[64];
- char rbuf[64];
- char *h;
- char *last;
- char *ma;
- char *mw;
- char *p;
- int fd;
- int mwi_off;
- int mwi_on;
- int r;
- int w;
- size_t l;
- ssize_t ml;
- ssize_t nbytes_read;
- struct termios tio;
-
- debugmsg ("Processing MWI event\n");
-
- ma = NULL;
- mw = NULL;
-
- p = m;
-
- while ( (p = strtok_r (p, "\n", &last)) ) {
- h = "MWI-Messages-Waiting: ";
- l = strlen (h);
-
- if (strncmp (p, h, l) == 0)
- mw = p + l;
-
- h = "MWI-Message-Account: ";
- l = strlen (h);
-
- if (strncmp (p, h, l) == 0)
- ma = p + l;
-
- p = NULL;
- }
-
- if (! (ma && mw) ) {
- errmsg ("message account or message waiting missing\n");
- return -1;
- }
-
- p = strchr (ma, '\n');
- if (p)
- *p = '\n';
-
- p = strchr (mw, '\n');
- if (p)
- *p = '\n';
-
- /*
- * The account is considered to be a System 25 extension if
- * it's of the form:
- *
- * numeric_string@host
- */
-
- p = strchr (ma, '%');
- if (! p)
- p = strchr (ma, '@');
-
- if (! p || (strncmp (p, "%40", 3) != 0 && strncmp (p, "@", 1) != 0)) {
- debugmsg (" %s is not a System 25 extension\n", ma);
- return 0;
- }
-
- *p = '\0';
-
- for (p = ma; *p; p++)
- if (! isdigit (*p)) {
- debugmsg (" %s is not a System 25 extension\n", ma);
- return 0;
- }
-
- mwi_off = strcasecmp (mw, "no") == 0;
- mwi_on = strcasecmp (mw, "yes") == 0;
-
- if (mwi_off == mwi_on) {
- errmsg ("Unsupported Messages-Waiting\n");
- return 0;
- }
-
- for (r = 0; r < 3; r++) {
- if ((fd = open (device, O_RDWR)) < 0) {
- char *errstr = strerror (errno);
-
- errmsg ("open failed for device node <%s>.\n", device);
- errmsg (errstr);
- return -1;
- }
-
- cfmakeraw (&tio);
-
- tio.c_cflag = CS8 | CREAD | HUPCL | CCTS_OFLOW | CRTS_IFLOW;
-
- tio.c_cc[VMIN] = 0;
- tio.c_cc[VTIME] = 50;
-
- cfsetispeed (&tio, B9600);
- cfsetospeed (&tio, B9600);
-
- if (tcsetattr (fd, TCSAFLUSH, &tio) < 0) {
- char *errstr = strerror (errno);
-
- errmsg ("tcsetattr failed\n");
- errmsg (errstr);
- close (fd);
- return -1;
- }
-
- m = "AT";
- ml = strlen (m);
-
- if (write (fd, m, ml) != ml
- || write (fd, "\r\n", 2) != 2) {
- char *errstr = strerror (errno);
-
- errmsg ("write failed\n");
- errmsg (errstr);
- close (fd);
- return -1;
- }
-
- for (w = 0; w < 2; w++) {
- nbytes_read = read_line (fd, rbuf, sizeof (rbuf));
- if (nbytes_read > 0 && (rbuf[0] == '\0' || strcmp (rbuf, m) == 0))
- continue;
- break;
- }
-
- if (nbytes_read < 0) {
- errmsg ("read_line failed\n");
- close (fd);
- return -1;
- }
-
- if (nbytes_read == 0
- || strcmp (rbuf, "OK") != 0) {
- errmsg ("modem failed to wake up\n");
- close (fd);
- continue;
- }
-
- m = cbuf;
- ml = snprintf (cbuf, sizeof (cbuf),
- "ATDT%s%s", (mwi_on ? "#90" : "#91"), ma);
- if (ml <= 0 || ml >= sizeof (cbuf)) {
- errmsg ("snprintf failed.\n");
- close (fd);
- return -1;
- }
-
- if (write (fd, m, ml) != ml
- || write (fd, "\r\n", 2) != 2) {
- char *errstr = strerror (errno);
-
- errmsg ("write failed\n");
- errmsg (errstr);
- close (fd);
- return -1;
- }
-
- sleep (5);
-
- if (write (fd, "\r\n", 2) != 2) {
- char *errstr = strerror (errno);
-
- errmsg ("write failed\n");
- errmsg (errstr);
- close (fd);
- return -1;
- }
-
- for (w = 0; w < 2; w++) {
- nbytes_read = read_line (fd, rbuf, sizeof (rbuf));
- if (nbytes_read > 0 && (rbuf[0] == '\0' || strcmp (rbuf, m) == 0))
- continue;
- break;
- }
-
- if (nbytes_read < 0) {
- errmsg ("read_line failed\n");
- close (fd);
- return -1;
- }
-
- if (nbytes_read > 0 && strcmp (rbuf, "NO DIALTONE") == 0) {
- errmsg ("modem failed to detect dialtone\n");
- close (fd);
- return -1;
- }
-
- if (nbytes_read == 0
- || strcmp (rbuf, "NO CARRIER") != 0) {
- errmsg ("modem failed to update MWI\n");
- close (fd);
- continue;
- }
-
- close (fd);
-
- debugmsg (" message waiting indicator updated for %s\n", ma);
- return 0;
- }
-
- errmsg (" failed to update message waiting indicator for %s\n", ma);
-
- return -1;
- }
-
-
-int
-main (int argc, char **argv)
- {
- const char *device = "/dev/cuad0";
- const char *machine = "localhost";
- const char *port = "8021";
- const char *passwd = "ClueCon";
- char *m;
- int c;
- int debug;
- int fd;
- struct stat statbuf;
-
- debug = 0;
-
- while ((c = getopt (argc, argv, "dm:p:w:")) != -1)
- switch (c) {
- case 'd':
- debug = 1;
- break;
-
- case 'm':
- machine = optarg;
- break;
-
- case 'p':
- port = optarg;
- break;
-
- case 'w':
- passwd = optarg;
- break;
-
- case 'l':
- device = optarg;
- break;
-
- default:
- fprintf (stderr,
- "Usage: %s [-d] [-m machine] [-p port] [-w passwd] [-l device]\n",
- MyName);
- exit(1);
- /* NOTREACHED */
- break;
- }
-
- if (stat (device, &statbuf) < 0 || ! S_ISCHR (statbuf.st_mode)) {
- fprintf (stderr, "%s: stat failed for path <%s>\n", MyName, device);
- fprintf (stderr, "%s: or the path isn't a character special file.\n",
- MyName);
- perror (MyName);
- exit (1);
- }
-
- install_signal_handlers ();
-
- if (! debug)
- daemonize ();
-
- while (! shutdown_server) {
- sleep (5);
-
- fd = connect_to_service (machine, port);
- if (fd < 0) {
- error_msg_throttle = 1;
- continue;
- }
-
- if (send_password (fd, passwd) < 0
- || enable_mwi_event (fd) < 0) {
- error_msg_throttle = 1;
- close (fd);
- continue;
- }
-
- error_msg_throttle = 0;
-
- while (m = retrieve_message (fd)) {
- process_mwi_event (m, device);
- free (m);
- }
-
- close (fd);
- }
-
- exit (0);
- }