Logo Search packages:      
Sourcecode: vbox3 version File versions  Download package

voice.c

/*
** $Id: voice.c,v 1.9 2003/09/28 12:58:33 pape Exp $
**
** Copyright 1996-1998 Michael 'Ghandi' Herold <michael@abadonna.mayn.de>
*/

#ifdef HAVE_CONFIG_H
#     include "../config.h"
#endif

#if TIME_WITH_SYS_TIME
#   include <sys/time.h>
#   include <time.h>
#else
#   if HAVE_SYS_TIME_H
#      include <sys/time.h>
#   else
#      include <time.h>
#   endif
#endif

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>

#include "voice.h"
#include "log.h"
#include "modem.h"
#include "stringutils.h"
#include "vboxrc.h"
#include "vboxgetty.h"
#include "tclscript.h"
#include "control.h"
#include "audio.h"
#include "breaklist.h"

/** Variables ************************************************************/

static struct vboxuser *voicevboxuser;
static struct vboxcall *voicevboxcall;

static int voicedesc = -1;
static int voicevbox =  0;
static int voicestat =  VBOXVOICE_STAT_OK;
static int audiodesc = -1;

static unsigned char voicename_ulaw[PATH_MAX + 1];
static unsigned char voicename_vbox[PATH_MAX + 1];
static unsigned char voicename_call[PATH_MAX + 1];

unsigned char voice_touchtone_sequence[VBOXVOICE_SEQUENCE + 1];

/** Prototypes ***********************************************************/

static void voice_stop_vtxrtx(void);
static void voice_create_vboxcall(void);
static void voice_remove_vboxcall(void);
static void voice_mkdir(unsigned char *);
static int  voice_check_touchtone(int);

/************************************************************************* 
 ** voice_init(): Beantwortet den Anruf und startet das Tcl-Skript.           **
 *************************************************************************
 ** => vboxuser   Zeiger auf die vboxuser-Struktur                                              **
 ** => vboxcall   Zeiger auf die vboxcall-Struktur                                              **
 *************************************************************************/

int voice_init(struct vboxuser *vboxuser, struct vboxcall *vboxcall)
{
      unsigned char     tempconnect[12];
      unsigned char     msgsavetime[32];
      time_t            currenttime;
      char          *stop;
      int               rc;

      struct vbox_tcl_variable vars[] = 
      {
            { "vbxv_savetime"       , msgsavetime                       },
            { "vbxv_callerid"       , vboxuser->incomingid  },
            { "vbxv_callername"     , vboxcall->name              },
            { "vbxv_localphone"     , vboxuser->localphone  },
            { "vbxv_username"       , vboxuser->name              },
            { "vbxv_userhome"       , vboxuser->home              },
            { "vbxv_usedscript"     , vboxcall->script            },
            { "vbxv_saveulaw"       , voicename_ulaw              },
            { "vbxv_savevbox"       , voicename_vbox              },
            { NULL                              , NULL                                    }
      };

      printstring(msgsavetime, "%d", vboxcall->savetime);

            /* Die beiden übergebenen Strukturen global machen, damit alle    */
            /* Voice Funktionen sie benutzen können.                                            */

      voicevboxuser = vboxuser;
      voicevboxcall = vboxcall;

            /* Die Namen der beiden Dateien (*.ulaw und *.vbox) erzeugen.     */
            /* Eine Datei enthält die Audiodaten, die andere die Inform-      */
            /* ationen über den Benutzer.                                                                   */

      currenttime = time(NULL);

      printstring(voicename_ulaw, "%s/new/%11.11lu-%8.8lu.ulaw", vboxuser->home, (unsigned long)currenttime, (unsigned long)getpid());
      printstring(voicename_vbox, "%s/new/%11.11lu-%8.8lu.vbox", vboxuser->home, (unsigned long)currenttime, (unsigned long)getpid());

            /* Den Namen der Call Datei erzeugen, in dem später Daten zum     */
            /* aktuellen Anruf gesichert werden.                                                      */

      printstring(voicename_call, "%s/vboxcall-%s", vboxuser->home, savettydname);

            /* Userspool Verzeichnisstruktur erzeugen. Wenn eines der   */
            /* Verzeichnisse bereits existiert, bleibt es unverändert.  */

      voice_mkdir(NULL );
      voice_mkdir("new");
      voice_mkdir("msg");
      voice_mkdir("tcl");

            /* Variablen für Tcl erzeugen, Kompression setzen, Full Duplex    */
            /* Audio Modus starten und das Skript aufrufen.                               */

      log_line(LOG_A, "Answering call...\n");

      voicevbox =  0;
      voicedesc = -1;
      audiodesc = -1;

      *voice_touchtone_sequence = '\0';

      if (scr_init_variables(vars) == 0)
      {
        int what =-1;
        if (strcmp(progbasename, "vboxputty") == 0)
          {
            char buf[64];
            int oldtimeout, i;
            
            if (modem_command(&vboxmodem, "ATS18=1", "OK") <= 0)
            {
                  log_line(LOG_W, "Setting S18=1 failed.\n");
                  quit_program(1);
            }
              sprintf(buf, "ATD%s", vboxuser->incomingid);
              oldtimeout =modemsetup.commandtimeout;
            modemsetup.commandtimeout =vboxcall->ringring *4;
            for (i =0; (i < vboxputty_busydial)
                  && ((what = modem_command(&vboxmodem, buf, "VCON|CONNECT|BUSY"))
                                          == 3); i++)
            {
                  sleep(vboxputty_busywait);
            }
            if (what == 3)
            {
              // Busy
              quit_program(1);
            }
            modemsetup.commandtimeout = oldtimeout;
            sleep(vboxputty_wait);
          }
        else
          {
            what = modem_command(&vboxmodem, "ATA", "VCON");
          }
        if (what > 0)
            {
                  log_line(LOG_D, "Setting voice compression to \"ulaw\"...\n");

                  if (modem_command(&vboxmodem, "AT+VSM=6+VLS=2", "OK") > 0)
                  {
                        log_line(LOG_D, "Starting full duplex audio mode...\n");

                        if (modem_command(&vboxmodem, "AT+VTX+VRX", "CONNECT") > 0)
                        {
                              voice_hear(0);
                              voice_save(0);

                                    /* Bevor das Skript gestartet wird, werden die  */
                                    /* ersten 11 Byte vom Modem eingelesen. Damit   */
                                    /* wird ein Fehler in i4l umgangen, der die           */
                                    /* Connectmessage bei Full Duplex 2x in den Mo- */
                                    /* dembuffer schreibt.                                                  */

                              modem_set_timeout(2);
                              vboxmodem_raw_read(&vboxmodem, tempconnect, 11);
                              modem_set_timeout(0);

                              voice_create_vboxcall();

      {
      int r, pid, wstat;
      if ((pid =fork()) == -1) {
          log_line(LOG_E, "fork failed.\n");
          exit(1);
      }
      if (pid == 0) {
        if (seteuid(0) == -1) {
          log_line(LOG_E, "seteuid failed.\n");
          exit(1);
        }
        if (setgid(vboxuser->gid) == -1) {
          log_line(LOG_E, "setgid failed.\n");
          exit(1);
        }
        if (setuid(vboxuser->uid) == -1) {
          log_line(LOG_E, "setuid failed.\n");
          exit(1);
        }

                              rc = scr_execute(vboxcall->script, vboxuser);

        exit(rc);
      }
      do
        r =waitpid(pid, &wstat, 0);
      while ((r == -1) && (errno == EINTR));
      if (WIFEXITED(wstat) && (WEXITSTATUS(wstat) == 0))
        rc =0;
      else
        rc =-1;
      }

                              voice_remove_vboxcall();

                              voice_hear(0);
                              voice_save(0);

                              voice_stop_vtxrtx();

                              if ((stop = ctrl_exists(vboxuser->home, "suspend", savettydname)))
                              {
                                    ctrl_remove(vboxuser->home, "suspend", savettydname);

                                    if (!vboxmodem.nocarrier)
                                    {
                                          log_line(LOG_A, "Suspending call to number %s...\n", stop);

                                          if (modem_command(&vboxmodem, "AT+S1", "OK") > 0) {
                                                log_line(LOG_D, "Call suspended to number %s.\n", stop);
                                          } else {
                                                log_line(LOG_E, "Can't suspend call to number %s.\n", stop);
                                          }
                                    }
                              }

                              return(rc);
                        }
                  }
            }
      }

      log_line(LOG_E, "Unable to answer call!\n");

      return(-1);
}

/*************************************************************************
 ** voice_wait(): Liest eine angegebene Zeit lang Audiodaten vom Modem. **
 *************************************************************************
 ** => timeout          Timeout in Sekunden                                                                       **
 *************************************************************************
 ** <=                         0 wenn der Timeout eingetreten ist.                                    **
 **                            1 wenn eine gültige Touchtonesequenz gefunden wurde. **
 **                            2 wenn der Anruf suspended werden soll.                          **
 **                           -1 bei einem Fehler oder Remote hangup                                  **
 *************************************************************************/

int voice_wait(int timeout)
{
      unsigned char  modem_line_i[1];
      unsigned char  modem_line_o[VBOXVOICE_BUFSIZE + 1];
      int            total_byte_i;
      int            total_byte_o;
      int            modem_byte_i;
      int            modem_byte_o;
      int            last_was_dle;
      int            result;
      char          *stop;

      total_byte_i = 0;
      total_byte_o = 0;
      last_was_dle = 0;
      voicestat    = VBOXVOICE_STAT_OK;

      log(LOG_D, "Reading voice datas (%ds timeout)...\n", timeout);

      modem_set_timeout(timeout);
      
      while (voicestat == VBOXVOICE_STAT_OK)
      {
            modem_byte_i = 0;
            modem_byte_o = 0;
            result       = 0;

            while ((modem_byte_o < (VBOXVOICE_BUFSIZE - 2)) && (voicestat == VBOXVOICE_STAT_OK))
            {
                  if ((result = vboxmodem_raw_read(&vboxmodem, modem_line_i, 1)) == 1)
                  {
                        modem_byte_i++;

                        if (last_was_dle)
                        {
                              switch (*modem_line_i)
                              {
                                    case DLE:
                                          modem_line_o[modem_byte_o++] = DLE;
                                          break;

                                    case ETX:
                                          voicestat |= VBOXVOICE_STAT_HANGUP;
                                          break;
                                          
                                    default:
                                          if (voice_check_touchtone(*modem_line_i) == 0) voicestat |= VBOXVOICE_STAT_TOUCHTONE;
                                          break;
                              }
                              
                              last_was_dle = 0;
                        }
                        else
                        {
                              if (*modem_line_i == DLE) last_was_dle = 1;

                              modem_line_o[modem_byte_o++] = *modem_line_i;
                        }
                  }
                  else break;
            }

            total_byte_o += modem_byte_o;
            total_byte_i += modem_byte_i;

            if (modem_byte_o > 0)
            {
                  if (voicedesc != -1) write(voicedesc, modem_line_o, modem_byte_o);
                  if (audiodesc != -1) write(audiodesc, modem_line_o, modem_byte_o);

                        /* Einmal in der Sekunde die Logmessage ausgeben und die    */
                        /* Controls checken.                                                          */

                  if ((total_byte_o >= VBOXVOICE_SAMPLERATE) || (voicestat != VBOXVOICE_STAT_OK))
                  {
                        log_line(LOG_D, "Wait: incoming %04d; outgoing %04d...\n", total_byte_i, total_byte_o);

                        total_byte_i = 0;
                        total_byte_o = 0;

                        if ((stop = ctrl_exists(voicevboxuser->home, "suspend", savettydname)))
                        {
                              log(LOG_D, "Control \"vboxctrl-suspend-%s\" detected: %s.\n", savettydname, stop);

                              voicestat |= VBOXVOICE_STAT_SUSPEND;
                        }

                        if ((stop = ctrl_exists(voicevboxuser->home, "audio", savettydname)))
                        {
                              log(LOG_D, "Control \"vboxctrl-audio-%s\" detected: %s.\n", savettydname, stop);

                              if (strcasecmp(stop,  "stop") == 0) voice_hear(0);
                              if (strcasecmp(stop, "start") == 0) voice_hear(1);
                        }
                  }
            }

            if ((result != 1) || (modem_get_timeout()))
            {
                  if (!modem_get_timeout())
                  {
                        log_line(LOG_W, "Can't read voice data (%s).\n", strerror(errno));

                        voicestat |= VBOXVOICE_STAT_TIMEOUT;
                  }
                  else voicestat |= VBOXVOICE_STAT_TIMEOUT;
            }
      }     

      modem_set_timeout(0);

      result = 0;

      if (voicestat & VBOXVOICE_STAT_TOUCHTONE)
      {
            log_line(LOG_D, "Full touchtone sequence found!\n");

            result = 1;
      }

      if (voicestat & VBOXVOICE_STAT_SUSPEND) result = 2;

      if ((voicestat & VBOXVOICE_STAT_HANGUP) || (vboxmodem.nocarrier))
      {
            log_line(LOG_D, "*** Remote hangup ***\n");

            voice_save(0);
            voice_hear(0);          

            modem_command(&vboxmodem, "", "NO CARRIER");

            result = -1;
      }
      
      return(result);
}

/************************************************************************* 
 ** voice_play(): Spielt eine Nachricht ab und liest dabei Voicedaten   **
 **                           vom Modem.                                                                                      **
 *************************************************************************
 ** name                      Name der Nachricht die gespielt werden soll.                      **
 *************************************************************************
 ** <=                         0 wenn der Timeout eingetreten ist.                                    **
 **                            1 wenn eine gültige Touchtonesequenz gefunden wurde. **
 **                            2 wenn der Anruf suspended werden soll.                          **
 **                           -1 bei einem Fehler oder Remote hangup                                  **
 *************************************************************************/

int voice_play(unsigned char *name)
{
      unsigned char  modem_line_i[1];
      unsigned char  modem_line_o[VBOXVOICE_BUFSIZE + 1];
      int                     total_byte_i;
      int                     total_byte_o;
      int            modem_byte_i;
      int            modem_byte_o;
      int            last_was_dle;
      int            result;
      int            desc;
      char          *stop;
      int            i;

      if ((!name) || (!*name))
      {
            log(LOG_W, "No message to play selected (ignored).\n");

            return(0);
      }

      log(LOG_D, "Playing \"%s\"...\n", name);

      errno = 0;
      desc  = open(name, O_RDONLY);

      if (desc == -1)
      {
      printstring(temppathname, "%s/msg/%s", voicevboxuser->home, name);

   errno = 0;
      desc  = open(temppathname, O_RDONLY);
      }

      if (desc == -1)
      {
            printstring(temppathname, "%s/msg/%s", PKGDATADIR, name);

      errno = 0;
            desc  = open(temppathname, O_RDONLY);
      }

      if (desc == -1)
      {
            log(LOG_W, "Can't open \"%s\" (%s).\n", name, strerror(errno));

            return(0);
      }

      total_byte_i      = 0;
      total_byte_o      = 0;
      voicestat         = VBOXVOICE_STAT_OK;

      while (voicestat == VBOXVOICE_STAT_OK)
      {
            modem_byte_i = 0;
            modem_byte_o = 0;
            result       = 0;

            modem_set_timeout(5);

            while ((modem_byte_o < (VBOXVOICE_BUFSIZE - 2)) && (voicestat == VBOXVOICE_STAT_OK))
            {
                  if ((i = read(desc, modem_line_i, 1)) != 1)
                  {
                        if (i != 0) log(LOG_W, "Can't read \"%s\" [%d] (%s).\n", name, i, strerror(errno));

                        voicestat |= VBOXVOICE_STAT_DONE;
                  }
                  else {
                    if (*modem_line_i == DLE) {
                      /* Escape sequence for DLE in data stream. */
                      vboxmodem_raw_write(&vboxmodem, modem_line_i, 1);
                    }
                    vboxmodem_raw_write(&vboxmodem, modem_line_i, 1);
                  }
                  if ((result = vboxmodem_raw_read(&vboxmodem, modem_line_i, 1)) == 1)
                  {
                        modem_byte_i++;

                        if (*modem_line_i == DLE) {
                          /* immediately read escape sequence */
                          if ((result = vboxmodem_raw_read(&vboxmodem, modem_line_i, 1)) != 1) {
                            break;
                          }
                              switch (*modem_line_i)
                              {
                                    case DLE:
                                          modem_line_o[modem_byte_o++] = DLE;
                                          break;

                                    case ETX:
                                          voicestat |= VBOXVOICE_STAT_HANGUP;
                                          break;
                                          
                                    default:
                                          if (voice_check_touchtone(*modem_line_i) == 0) voicestat |= VBOXVOICE_STAT_TOUCHTONE;
                                          break;
                              }
                        }
                        else
                        {
                          modem_line_o[modem_byte_o++] = *modem_line_i;
                        }
                  }
                  else break;
            }

            modem_set_timeout(0);

            total_byte_o += modem_byte_o;
            total_byte_i += modem_byte_i;

            if (modem_byte_o > 0)
            {
                  if (voicedesc != -1) write(voicedesc, modem_line_o, modem_byte_o);
                  if (audiodesc != -1) write(audiodesc, modem_line_o, modem_byte_o);

                        /* Einmal in der Sekunde die Logmessage ausgeben und die    */
                        /* Controls checken.                                                          */

                  if ((total_byte_o >= VBOXVOICE_SAMPLERATE) || (voicestat != VBOXVOICE_STAT_OK))
                  {
                        log_line(LOG_D, "Play: incoming %04d; outgoing %04d...\n", total_byte_i, total_byte_o);

                        total_byte_i = 0;
                        total_byte_o = 0;

                        if ((stop = ctrl_exists(voicevboxuser->home, "suspend", savettydname)))
                        {
                              log(LOG_D, "Control \"vboxctrl-suspend-%s\" detected: %s.\n", savettydname, stop);

                              voicestat |= VBOXVOICE_STAT_SUSPEND;
                        }

                        if ((stop = ctrl_exists(voicevboxuser->home, "audio", savettydname)))
                        {
                              log(LOG_D, "Control \"vboxctrl-audio-%s\" detected: %s.\n", savettydname, stop);

                              if (strcasecmp(stop,  "stop") == 0) voice_hear(0);
                              if (strcasecmp(stop, "start") == 0) voice_hear(1);
                        }
                  }
            }

            if ((result != 1) || (modem_get_timeout()))
            {
                  if (!modem_get_timeout())
                  {
                        log_line(LOG_W, "Can't read voice data (%s).\n", strerror(errno));

                        voicestat |= VBOXVOICE_STAT_TIMEOUT;
                  }
                  else voicestat |= VBOXVOICE_STAT_TIMEOUT;
            }
      }     

      modem_set_timeout(0);

      if (desc != -1) close(desc);

      result = 0;

      if (voicestat & VBOXVOICE_STAT_TOUCHTONE)
      {
            log_line(LOG_D, "Full touchtone sequence found!\n");

            result = 1;
      }

      if (voicestat & VBOXVOICE_STAT_SUSPEND) result = 2;

      if ((voicestat & VBOXVOICE_STAT_HANGUP) || (vboxmodem.nocarrier))
      {
            log_line(LOG_D, "*** Remote hangup ***\n");

            voice_save(0);
            voice_hear(0);          

            modem_command(&vboxmodem, "", "NO CARRIER");

            result = -1;
      }
      
      return(result);
}

/************************************************************************* 
 ** voice_save(): Schaltet das mitspeichern der eingehenden Voicedaten  **
 **                           ein oder aus.                                                                                   **
 *************************************************************************
 ** => save             > 0 um das mitspeichern einzuschalten; alle anderen   **
 **                           Werte schaltes es aus.                                                              **
 *************************************************************************/

int voice_save(int save)
{
      FILE *vbox;

      if (save > 0)
      {
            if (voicedesc == -1)
            {
                  log(LOG_D, "Starting voice recording...\n");
                  log(LOG_D, "Opening \"%s\"...\n", voicename_ulaw);

                  errno = 0;

                  if ((voicedesc = open(voicename_ulaw, O_WRONLY|O_CREAT|O_APPEND, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) == -1)
                  {
                        log(LOG_E, "Can't open/append \"%s\" (%s).\n", voicename_ulaw, strerror(errno));

                        return(-1);
                  }
            }

            if (!voicevbox)
            {
                        /* Wenn die *.vbox Datei noch nicht existiert wird sie      */
                        /* jetzt erzeugt. Die Datei enthält die Informationen       */
                        /* wer wann wie die Nachricht gesprochen hat.                     */

                  log(LOG_D, "Creating \"%s\"...\n", voicename_vbox);

                  errno = 0;

                  if ((vbox = fopen(voicename_vbox, "w")))
                  {
                        fprintf(vbox, "Name: %s\n" , voicevboxcall->name      );
                        fprintf(vbox, "ID  : %s\n" , voicevboxuser->incomingid);
                        fprintf(vbox, "Time: %ld\n", time(NULL)               );

                        fclose(vbox);

                        voicevbox = 1;
                  }
                  else log(LOG_E, "Can't create \"%s\" (%s).\n", voicename_vbox, strerror(errno));
            }
      }
      else
      {
            if (voicedesc != -1)
            {
                  log(LOG_D, "Stopping voice recording...\n");
                  log(LOG_D, "Closing \"%s\"...\n", voicename_ulaw);

                  close(voicedesc);
            }
            
            voicedesc = -1;
      }

      return(0);
}

/************************************************************************* 
 ** voice_hear(): Schaltet das mithören der Voicedaten über /dev/audio  **
 **                           ein oder aus.                                                                                   **
 *************************************************************************
 ** => mode             > 0 um das Mithören einzuschalten; alle anderen Werte **
 **                           schalten das Mithören aus.                                                          **
 **                                                                                                                                       **
 ** Die Funktion gibt 0 zurück wenn die Aktion ausgeführt werden konnte **
 ** oder -1 wenn nicht.                                                                                                 **
 *************************************************************************/

int voice_hear(int mode)
{
      if (mode > 0)
      {
            if (audiodesc == -1)
            {
                  log(LOG_D, "Starting audio playback...\n");

                  if ((audiodesc = audio_open_dev("/dev/audio")) == -1) return(-1);
            }
      }
      else
      {
            if (audiodesc != -1)
            {
                  log(LOG_D, "Stopping audio playback...\n");

                  audio_close_dev(audiodesc);
            }
            
            audiodesc = -1;
      }

      return(0);
}

/************************************************************************* 
 ** FIXME
 *************************************************************************/

static void voice_stop_vtxrtx(void)
{
      unsigned char line[4];
      int           have;

      if (!vboxmodem.nocarrier)
      {
                  /* DLE/DC4 an den Modememluator schicken um den Record-Modus */
                  /* zu stoppen. Der Emulator sollte mit DLE/ETX antworten.    */

            log_line(LOG_D, "Sending \"<DLE><DC4>\" to stop record mode...\n");

            printstring(line, "%c%c", DLE, DC4);

            vboxmodem_raw_write(&vboxmodem, line, 2);

            have = 0;

            modem_set_timeout(modemsetup.commandtimeout);

            while (vboxmodem_raw_read(&vboxmodem, line, 1) == 1)
            {
                  log_char(LOG_D, *line);

                  if (*line != DLE)
                  {
                        if ((*line == ETX) && (have))
                        {
                              have++;

                              break;
                        }
                        else have = 0;
                  }
                  else have = 1;
            }

            modem_set_timeout(0);

            if (have == 2) log_line(LOG_D, "Found <DLE><ETX>!\n");

            log_line(LOG_D, "Sending \"<DLE><ETX>\" to stop playback mode...\n");

            printstring(line, "%c%c", DLE, ETX);

            vboxmodem_raw_write(&vboxmodem, line, 2);

            have = 0;

            modem_set_timeout(modemsetup.commandtimeout);

            while (vboxmodem_raw_read(&vboxmodem, line, 1) == 1)
            {
                  log_char(LOG_D, *line);

                  if (*line != DLE)
                  {
                        if ((*line == DC4) && (have))
                        {
                              have++;

                              break;
                        }
                        else have = 0;
                  }
                  else have = 1;
            }

            modem_set_timeout(0);

            if (have == 2) log_line(LOG_D, "Found <DLE><DC4>!\n");
      }
}

/************************************************************************* 
 ** voice_create_vboxcall():  Erzeugt eine Call Datei mit Informationen **
 **                                                   über den aktuellen Anruf.                                   **
 *************************************************************************/

static void voice_create_vboxcall(void)
{
      FILE *call;

      log(LOG_D, "Creating \"%s\"...\n", voicename_call);

      if ((call = fopen(voicename_call, "w")))
      {
                  /* CallerID, Name, tty-Device und die aktuelle PID in der   */
                  /* Datei speichern.                                                                                   */

            fprintf(call, "%s:%s:%s:%d\n", voicevboxuser->incomingid, voicevboxuser->name, savettydname, getpid());

            fclose(call);
      }
      else log(LOG_E, "Can't create \"%s\" (%s)!\n", voicename_call, strerror(errno));
}

/************************************************************************* 
 ** voice_remove_vboxcall():  Löscht die Call Datei.                                      **
 *************************************************************************/

static void voice_remove_vboxcall(void)
{
      log(LOG_D, "Removing \"%s\"...\n", voicename_call);

      if (remove(voicename_call) != 0)
      {
            if (errno != ENOENT) log(LOG_E, "Can't remove \"%s\" (%s)!\n", voicename_call, strerror(errno));
      }
}

/************************************************************************* 
 ** voice_mkdir():      Erzeugt die Verzeichnisse im Userspool.                     **
 *************************************************************************/

static void voice_mkdir(unsigned char *name)
{
      if (name)
            printstring(temppathname, "%s/%s", voicevboxuser->home, name);
      else
            printstring(temppathname, "%s", voicevboxuser->home);

      log(LOG_D, "Creating directory \"%s\"...\n", temppathname);

      errno = 0;

      if (mkdir(temppathname, S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH) == -1)
      {
            if (errno != EEXIST)
            {
                  log(LOG_E, "Can't create \"%s\" (%s).\n", temppathname, strerror(errno));
            }
      }
}

/************************************************************************* 
 ** voice_check_touchtone():  Prüft ob es sich bei einem Zeichen um           **
 **                                                   einen Touchtone handelt.                                    **
 *************************************************************************
 ** => c                                              Zeichen                                                                       **
 **                                                                                                                                       **
 ** Rückgabe ist 0 wenn es ein Touchtone war oder -1 wenn nicht.              **
 *************************************************************************/

static int voice_check_touchtone(int c)
{
      unsigned char  tone[2];
      unsigned char *stop;
      int                     i;

      switch (c)
      {
            case '0':
            case '1':
            case '2':
            case '3':
            case '4':
            case '5':
            case '6':
            case '7':
            case '8':
            case '9':
            case 'A':
            case 'B':
            case 'C':
            case 'D':
            case '#':
            case '*':
            {
                  if (c != '*')
                  {
                        tone[0] = c;
                        tone[1] = 0;

                        if (*voice_touchtone_sequence == '*')
                        {
                                    /* Wenn das erste Zeichen in der Sequenz ein '*'      */
                                    /* ist (Sequenzstart) wird der neue Touchtone am      */
                                    /* Ende angehängt - es sei denn die Sequenz ent-      */
                                    /* hält ein '#' (Sequenzende).                                          */

                              if (!(stop = rindex(voice_touchtone_sequence, '#')))
                              {
                                    if (strlen(voice_touchtone_sequence) >= VBOXVOICE_SEQUENCE)
                                    {
                                                /* Die Sequenz ist bereits voll; der neue */
                                                /* Touchtone wird nicht angehängt!              */

                                          log(LOG_E, "Internal touchtone sequence is full (touchtone ignored).\n");
                                    }
                                    else strcat(voice_touchtone_sequence, tone);
                              }
                              else strcpy(voice_touchtone_sequence, tone);
                        }
                        else
                        {
                                    /* Erstes Zeichen in der Sequenz ist kein '*', der    */
                                    /* Touchtone ersetzt die alte Sequenz.                            */

                              strcpy(voice_touchtone_sequence, tone);
                        }
                  }
                  else strcpy(voice_touchtone_sequence, "*");

                  log(LOG_I, "Touchtone \"%c\" entered (%s).\n", c, voice_touchtone_sequence);

                        /* Prüfen ob die eingegebene Sequenz in der Breakliste      */
                        /* vorkommt.                                                                                          */

                  for (i = 0; i < VBOXBREAK_MAX_ENTRIES; i++)
                  {
                        if (breaklist[i])
                        {
                              if (strcmp(breaklist[i], voice_touchtone_sequence) == 0) return(0);
                        }
                  }
            }
            break;

            case 'q':   /* Quiet                            */
            case 's':   /* Silence                    */
            case 'c':   /* Fax calling tone     */
            case 'b':   /* Busy tone                  */
                  break;

            default:
         log_line(LOG_W, "Illegal \"<DLE>\" shielded code \"");
         log_char(LOG_W, c);
         log_text(LOG_W, "\" (ignored)...\n");
                  break;
      }

      return(-1);
}

Generated by  Doxygen 1.6.0   Back to index