isdn4k-utils/vbox/src/script.c

600 lines
15 KiB
C

/*
** $Id$
**
** Copyright (C) 1996, 1997 Michael 'Ghandi' Herold
*/
#include "config.h"
#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 <stdio.h>
#include <stdlib.h>
#include <tcl.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <netinet/in.h>
#include "script.h"
#include "log.h"
#include "voice.h"
#include "modem.h"
#include "libvbox.h"
/** Tcl functions *********************************************************/
int vbox_breaklist(ClientData, Tcl_Interp *, int, char *[]);
int vbox_init_touchtones(ClientData, Tcl_Interp *, int, char *[]);
int vbox_put_message(ClientData, Tcl_Interp *, int, char *[]);
int vbox_get_message(ClientData, Tcl_Interp *, int, char *[]);
int vbox_wait(ClientData, Tcl_Interp *, int, char *[]);
int vbox_pause(ClientData, Tcl_Interp *, int, char *[]);
int vbox_get_nr_new_messages(ClientData, Tcl_Interp *, int, char *[]);
int vbox_get_nr_all_messages(ClientData, Tcl_Interp *, int, char *[]);
int vbox_message_info(ClientData, Tcl_Interp *, int, char *[]);
static struct vbox_tcl_function vbox_tcl_functions[] =
{
{ "vbox_breaklist" , vbox_breaklist },
{ "vbox_put_message" , vbox_put_message },
{ "vbox_play_message" , vbox_put_message },
{ "vbox_get_message" , vbox_get_message },
{ "vbox_record_message" , vbox_get_message },
{ "vbox_init_touchtones" , vbox_init_touchtones },
{ "vbox_wait" , vbox_wait },
{ "vbox_pause" , vbox_pause },
{ "vbox_get_nr_new_messages", vbox_get_nr_new_messages },
{ "vbox_get_nr_all_messages", vbox_get_nr_all_messages },
{ "vbox_message_info" , vbox_message_info },
{ NULL , NULL }
};
/** Prototypes ************************************************************/
static int init_tcl_functions(Tcl_Interp *);
static int init_tcl_variables(Tcl_Interp *);
static int make_tcl_variable(Tcl_Interp *, char *, char *);
/** Defines **************************************************************/
#define MYMKVAR(V, A) make_tcl_variable(interp, V, A)
/*************************************************************************/
/** script_run(): Starts a external tcl script. **/
/*************************************************************************/
int script_run(char *script)
{
Tcl_Interp *interpreter;
int result;
int rcdelete;
log(L_DEBUG, "Initializing tcl script \"%s\"...\n", script);
breaklist_init();
result = FALSE;
if ((interpreter = Tcl_CreateInterp()))
{
if (Tcl_Init(interpreter) == TCL_OK)
{
if (init_tcl_functions(interpreter))
{
if (init_tcl_variables(interpreter))
{
log(L_DEBUG, "Answering call...\n");
if (modem_command("ATA", "VCON|CONNECT") > 0)
{
log(L_INFO, "Running tcl script \"%s\"...\n", script);
if (Tcl_EvalFile(interpreter, script) != TCL_OK)
{
log(L_ERROR, "In \"%s\": %s (line %d).\n", script, interpreter->result, interpreter->errorLine);
}
else
{
log(L_DEBUG, "Back from tcl script...\n");
result = TRUE;
}
}
else log(L_FATAL, "Can't answer call!\n");
}
else log(L_ERROR, "In \"%s\": %s (line %d).\n", script, interpreter->result, interpreter->errorLine);
}
else log(L_FATAL, "Can't create all new tcl commands.\n");
if ((rcdelete = Tcl_InterpDeleted(interpreter)) == 0)
{
log(L_DEBUG, "Freeing tcl interpreter...\n");
Tcl_DeleteInterp(interpreter);
}
else
{
log(L_ERROR, "Can't free tcl interpreter - Tcl_InterpDeleted() returns %d!\n", rcdelete);
result = FALSE;
}
}
else log(L_FATAL, "Can't initialize tcl interpreter.\n");
}
else log(L_FATAL, "Can't create tcl interpreter.\n");
breaklist_exit();
if (!result)
{
log(L_ERROR, "General tcl problem - setting flag to quit program...\n");
}
return(result);
}
/**************************************************************************/
/** init_tcl_functions(): Inits all new tcl functions. **/
/**************************************************************************/
static int init_tcl_functions(Tcl_Interp *interp)
{
int i;
i = 0;
while (vbox_tcl_functions[i].name)
{
if (!Tcl_CreateCommand(interp, vbox_tcl_functions[i].name, vbox_tcl_functions[i].proc, NULL, NULL))
{
log(L_FATAL, "Can't create tcl function '%s'.\n", vbox_tcl_functions[i].name);
returnerror();
}
i++;
}
returnok();
}
/**************************************************************************/
/** init_tcl_variables(): Inits all new tcl variables. **/
/**************************************************************************/
static int init_tcl_variables(Tcl_Interp *interp)
{
char savename[32];
char savetime[32];
printstring(savename, "%14.14lu-%8.8lu", (unsigned long)time(NULL), (unsigned long)getpid());
printstring(savetime, "%d", setup.voice.recordtime);
if (!MYMKVAR("vbox_var_bindir" , BINDIR )) returnerror();
if (!MYMKVAR("vbox_var_savename" , savename )) returnerror();
if (!MYMKVAR("vbox_var_rectime" , savetime )) returnerror();
if (!MYMKVAR("vbox_var_spooldir" , setup.spool )) returnerror();
if (!MYMKVAR("vbox_var_checknew", setup.voice.checknewpath)) returnerror();
if (!MYMKVAR("vbox_msg_standard" , setup.voice.standardmsg)) returnerror();
if (!MYMKVAR("vbox_msg_beep" , setup.voice.beepmsg )) returnerror();
if (!MYMKVAR("vbox_msg_timeout" , setup.voice.timeoutmsg )) returnerror();
if (!MYMKVAR("vbox_caller_id" , setup.voice.callerid )) returnerror();
if (!MYMKVAR("vbox_caller_phone" , setup.voice.phone )) returnerror();
if (!MYMKVAR("vbox_caller_name" , setup.voice.name )) returnerror();
if (!MYMKVAR("vbox_user_name" , setup.users.name )) returnerror();
if (!MYMKVAR("vbox_user_home" , setup.users.home )) returnerror();
if (!MYMKVAR("vbox_flag_standard", setup.voice.domessage ? "TRUE" : "FALSE")) returnerror();
if (!MYMKVAR("vbox_flag_beep" , setup.voice.dobeep ? "TRUE" : "FALSE")) returnerror();
if (!MYMKVAR("vbox_flag_timeout" , setup.voice.dotimeout ? "TRUE" : "FALSE")) returnerror();
if (!MYMKVAR("vbox_flag_record" , setup.voice.dorecord ? "TRUE" : "FALSE")) returnerror();
returnok();
}
/**************************************************************************/
/** make_tcl_variable(): Creates a new tcl variable. **/
/**************************************************************************/
static int make_tcl_variable(Tcl_Interp *interp, char *var, char *arg)
{
if (Tcl_VarEval(interp, "set ", var, " \"", arg, "\"", NULL) != TCL_OK)
{
log(L_FATAL, "Can't initzalize tcl variable '%s'.\n", var);
returnerror();
}
returnok();
}
/*************************************************************************/
/** script_check_interpreter(): Checks tcl interpreter versions. **/
/*************************************************************************/
int script_check_interpreter(void)
{
log(L_INFO, "Tcl interpreter version %s...\n", TCL_VERSION);
returnok();
}
/*************************************************************************/
/** vbox_message_info(): Returns message header fields. **/
/*************************************************************************/
int vbox_message_info(ClientData cd, Tcl_Interp *ip, int argc, char *argv[])
{
vaheader_t header;
int fd;
char *name;
char *need;
int field;
strcpy(ip->result, "");
if (argc == 3)
{
name = argv[1];
need = argv[2];
if ((fd = open(name, O_RDONLY)) != -1)
{
if (header_get(fd, &header))
{
field = (int)xstrtol(need, 0);
switch (field)
{
case 1:
printstring(ip->result, "%ld", (long)ntohl(header.time));
break;
case 2:
printstring(ip->result, "%d", (int)ntohl(header.compression));
break;
case 3:
printstring(ip->result, "%s", header.callerid);
break;
case 4:
printstring(ip->result, "%s", header.name);
break;
case 5:
printstring(ip->result, "%s", header.phone);
break;
case 6:
printstring(ip->result, "%s", header.location);
break;
default:
log(L_ERROR, "[vbox_message_info] unknown field number %d.\n", field);
break;
}
}
else log(L_ERROR, "[vbox_message_info] can't get header from '%s'.\n", name);
close(fd);
}
else log(L_ERROR, "[vbox_message_info] can't open '%s'.\n", name);
}
else log(L_ERROR, "[vbox_message_info] usage: vbox_message_info <message> <fieldnr>\n");
return(TCL_OK);
}
/*************************************************************************/
/** vbox_breaklist(): DTMF sequence support. **/
/*************************************************************************/
int vbox_breaklist(ClientData cd, Tcl_Interp *ip, int argc, char *argv[])
{
int i;
char *line;
if (argc == 2)
{
if (strcasecmp(argv[1], "list") == 0)
{
for (i = 0; i < VBOX_MAX_BREAKLIST; i++)
{
if ((line = breaklist_nr(i)))
{
log(L_DEBUG, "[vbox_breaklist] %s\n", line);
}
}
return(TCL_OK);
}
}
if (argc >= 3)
{
if (strcasecmp(argv[1], "add") == 0)
{
for (i = 2; i < argc; i++)
{
if (!breaklist_add(argv[i]))
{
log(L_ERROR, "[vbox_breaklist] can't add \"%s\".\n", argv[i]);
}
}
return(TCL_OK);
}
if (strcasecmp(argv[1], "rem") == 0)
{
for (i = 2; i < argc; i++)
{
if (strcasecmp(argv[i], "all") == 0)
{
breaklist_exit();
}
else breaklist_rem(argv[i]);
}
return(TCL_OK);
}
}
log(L_ERROR, "[vbox_breaklist] usage: vbox_breaklist <rem|add> <sequence> [sequence] [...]\n");
return(TCL_OK);
}
/*************************************************************************/
/** vbox_put_message(): Plays a voice message. **/
/*************************************************************************/
int vbox_put_message(ClientData cd, Tcl_Interp *ip, int argc, char *argv[])
{
int result;
if (argc != 2)
{
log(L_ERROR, "[vbox_put_message] usage: vbox_put_message <messagename>\n");
printstring(ip->result, "ERROR");
}
else
{
result = voice_put_message(argv[1]);
switch (result)
{
case VOICE_ACTION_ERROR:
printstring(ip->result, "ERROR");
break;
case VOICE_ACTION_LOCALHANGUP:
case VOICE_ACTION_REMOTEHANGUP:
printstring(ip->result, "HANGUP");
break;
case VOICE_ACTION_TOUCHTONES:
printstring(ip->result, touchtones);
touchtones[0] = '\0';
break;
default:
printstring(ip->result, "OK");
break;
}
log(L_DEBUG, "[vbox_put_message] result \"%s\".\n", ip->result);
}
return(TCL_OK);
}
/*************************************************************************/
/** vbox_get_message(): Records a voice message. **/
/*************************************************************************/
int vbox_get_message(ClientData cd, Tcl_Interp *ip, int argc, char *argv[])
{
int result;
if (argc != 3)
{
log(L_ERROR, "[vbox_get_message] usage: vbox_get_message <messagename> <recordtime>\n");
printstring(ip->result, "ERROR");
}
else
{
result = voice_get_message(argv[1], argv[2], TRUE);
switch (result)
{
case VOICE_ACTION_ERROR:
printstring(ip->result, "ERROR");
break;
case VOICE_ACTION_TIMEOUT:
printstring(ip->result, "TIMEOUT");
break;
case VOICE_ACTION_LOCALHANGUP:
case VOICE_ACTION_REMOTEHANGUP:
printstring(ip->result, "HANGUP");
break;
case VOICE_ACTION_TOUCHTONES:
printstring(ip->result, touchtones);
touchtones[0] = '\0';
break;
default:
printstring(ip->result, "OK");
break;
}
log(L_DEBUG, "[vbox_get_message] result \"%s\".\n", ip->result);
}
return(TCL_OK);
}
/*************************************************************************/
/** vbox_wait(): Waits for DTMF input. **/
/*************************************************************************/
int vbox_wait(ClientData cd, Tcl_Interp *ip, int argc, char *argv[])
{
int result;
if (argc != 2)
{
log(L_ERROR, "[vbox_wait] usage: vbox_wait <seconds>\n");
printstring(ip->result, "ERROR");
}
else
{
result = voice_get_message("", argv[1], FALSE);
switch (result)
{
case VOICE_ACTION_ERROR:
printstring(ip->result, "ERROR");
break;
case VOICE_ACTION_TIMEOUT:
printstring(ip->result, "TIMEOUT");
break;
case VOICE_ACTION_LOCALHANGUP:
case VOICE_ACTION_REMOTEHANGUP:
printstring(ip->result, "HANGUP");
break;
case VOICE_ACTION_TOUCHTONES:
printstring(ip->result, touchtones);
touchtones[0] = '\0';
break;
default:
printstring(ip->result, "OK");
break;
}
log(L_DEBUG, "[vbox_wait] result \"%s\".\n", ip->result);
}
return(TCL_OK);
}
/*************************************************************************/
/** vbox_pause(): Sleeps some milliseconds. **/
/*************************************************************************/
int vbox_pause(ClientData cd, Tcl_Interp *ip, int argc, char *argv[])
{
long p;
if (argc != 2)
{
log(L_ERROR, "[vbox_pause] usage: vbox_pause <ms>\n");
printstring(ip->result, "ERROR");
}
else
{
p = xstrtol(argv[1], 800);
log(L_JUNK, "[vbox_pause] waiting %lu ms...\n", p);
xpause(p);
printstring(ip->result, "OK");
}
return(TCL_OK);
}
/*************************************************************************/
/** vbox_init_touchtones(): Initialize touchtone sequence. **/
/*************************************************************************/
int vbox_init_touchtones(ClientData cd, Tcl_Interp *ip, int argc, char *argv[])
{
*touchtones = '\0';
printstring(ip->result, "OK");
return(TCL_OK);
}
/*************************************************************************/
/** vbox_get_nr_new_messages(): Returns the number of new messages. **/
/*************************************************************************/
int vbox_get_nr_new_messages(ClientData cd, Tcl_Interp *ip, int argc, char *argv[])
{
int n;
if (argc != 2)
{
log(L_ERROR, "[vbox_get_nr_new_messages] usage: vbox_get_nr_new_messages <path>\n");
printstring(ip->result, "0");
}
else
{
log(L_JUNK, "[vbox_get_nr_new_messages] counting new messages in \"%s\"...\n", argv[1]);
n = get_nr_messages(argv[1], TRUE);
log(L_DEBUG, "[vbox_get_nr_new_messages] result \"%d\".\n", n);
printstring(ip->result, "%d", n);
}
return(TCL_OK);
}
/*************************************************************************/
/** vbox_get_nr_all_messages(): Returns the number of messages. **/
/*************************************************************************/
int vbox_get_nr_all_messages(ClientData cd, Tcl_Interp *ip, int argc, char *argv[])
{
int n;
if (argc != 2)
{
log(L_ERROR, "[vbox_get_nr_all_messages] usage: vbox_get_nr_all_messages <path>\n");
printstring(ip->result, "0");
}
else
{
log(L_JUNK, "[vbox_get_nr_all_messages] counting all messages in \"%s\"...\n", argv[1]);
n = get_nr_messages(argv[1], FALSE);
log(L_DEBUG, "[vbox_get_nr_all_messages] result \"%d\".\n", n);
printstring(ip->result, "%d", n);
}
return(TCL_OK);
}