Mon May 14 04:43:19 2007

Asterisk developer's documentation


app_adsiprog.c File Reference

Program Asterisk ADSI Scripts into phone. More...

#include "asterisk.h"
#include <sys/types.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <errno.h>
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/adsi.h"
#include "asterisk/options.h"
#include "asterisk/utils.h"
#include "asterisk/lock.h"

Include dependency graph for app_adsiprog.c:

Go to the source code of this file.

Data Structures

struct  adsi_display
struct  adsi_event
struct  adsi_flag
struct  adsi_key_cmd
struct  adsi_script
struct  adsi_soft_key
struct  adsi_state
struct  adsi_subscript

Defines

#define ARG_NUMBER   (1 << 1)
#define ARG_STRING   (1 << 0)
#define MAX_MAIN_LEN   1600
#define MAX_RET_CODE   20
#define MAX_SUB_LEN   255
#define STATE_INIF   3
#define STATE_INKEY   1
#define STATE_INSUB   2
#define STATE_NORMAL   0

Functions

static int adsi_exec (struct ast_channel *chan, void *data)
static int adsi_process (struct adsi_script *state, char *buf, char *script, int lineno)
static int adsi_prog (struct ast_channel *chan, char *script)
 AST_MODULE_INFO_STANDARD (ASTERISK_GPL_KEY,"Asterisk ADSI Programming Application")
static int clearcbone (char *buf, char *name, int id, char *args, struct adsi_script *istate, char *script, int lineno)
static int cleardisplay (char *buf, char *name, int id, char *args, struct adsi_script *istate, char *script, int lineno)
static int clearflag (char *buf, char *name, int id, char *args, struct adsi_script *state, char *script, int lineno)
static int cleartimer (char *buf, char *name, int id, char *args, struct adsi_script *istate, char *script, int lineno)
static struct adsi_scriptcompile_script (char *script)
static int digitcollect (char *buf, char *name, int id, char *args, struct adsi_script *istate, char *script, int lineno)
static int digitdirect (char *buf, char *name, int id, char *args, struct adsi_script *istate, char *script, int lineno)
static char * get_token (char **buf, char *script, int lineno)
static struct adsi_displaygetdisplaybyname (struct adsi_script *state, char *name, char *script, int lineno, int create)
static int geteventbyname (char *name)
static struct adsi_flaggetflagbyname (struct adsi_script *state, char *name, char *script, int lineno, int create)
static int getjustifybyname (char *name)
static struct adsi_soft_keygetkeybyname (struct adsi_script *state, char *name, char *script, int lineno)
static struct adsi_stategetstatebyname (struct adsi_script *state, char *name, char *script, int lineno, int create)
static struct adsi_subscriptgetsubbyname (struct adsi_script *state, char *name, char *script, int lineno)
static int goto_line (char *buf, char *name, int id, char *args, struct adsi_script *state, char *script, int lineno)
static int goto_line_rel (char *buf, char *name, int id, char *args, struct adsi_script *state, char *script, int lineno)
static int load_module (void)
static int onevent (char *buf, char *name, int id, char *args, struct adsi_script *state, char *script, int lineno)
static int process_opcode (struct adsi_subscript *sub, char *code, char *args, struct adsi_script *state, char *script, int lineno)
static int process_returncode (struct adsi_soft_key *key, char *code, char *args, struct adsi_script *state, char *script, int lineno)
static int process_token (void *out, char *src, int maxlen, int argtype)
static int send_delay (char *buf, char *name, int id, char *args, struct adsi_script *state, char *script, int lineno)
static int send_dtmf (char *buf, char *name, int id, char *args, struct adsi_script *state, char *script, int lineno)
static int set_state (char *buf, char *name, int id, char *args, struct adsi_script *istate, char *script, int lineno)
static int setflag (char *buf, char *name, int id, char *args, struct adsi_script *state, char *script, int lineno)
static int showdisplay (char *buf, char *name, int id, char *args, struct adsi_script *state, char *script, int lineno)
static int showkeys (char *buf, char *name, int id, char *args, struct adsi_script *state, char *script, int lineno)
static int starttimer (char *buf, char *name, int id, char *args, struct adsi_script *istate, char *script, int lineno)
static int subscript (char *buf, char *name, int id, char *args, struct adsi_script *state, char *script, int lineno)
static int unload_module (void)

Variables

static char * app = "ADSIProg"
static char * descrip
static struct adsi_event events []
static struct adsi_event justify []
static struct adsi_key_cmd kcmds []
static struct adsi_key_cmd opcmds []
static char * synopsis = "Load Asterisk ADSI Scripts into phone"
static char * validdtmf = "123456789*0#ABCD"


Detailed Description

Program Asterisk ADSI Scripts into phone.

Author:
Mark Spencer <markster@digium.com>

Definition in file app_adsiprog.c.


Define Documentation

#define ARG_NUMBER   (1 << 1)

Definition at line 111 of file app_adsiprog.c.

Referenced by adsi_process(), goto_line(), goto_line_rel(), process_token(), send_delay(), set_state(), showdisplay(), and starttimer().

#define ARG_STRING   (1 << 0)

Definition at line 110 of file app_adsiprog.c.

Referenced by adsi_process(), clearflag(), onevent(), process_token(), send_dtmf(), setflag(), showdisplay(), showkeys(), and subscript().

#define MAX_MAIN_LEN   1600

Definition at line 108 of file app_adsiprog.c.

Referenced by process_opcode().

#define MAX_RET_CODE   20

Definition at line 106 of file app_adsiprog.c.

Referenced by process_returncode().

#define MAX_SUB_LEN   255

Definition at line 107 of file app_adsiprog.c.

Referenced by process_opcode().

#define STATE_INIF   3

Definition at line 104 of file app_adsiprog.c.

Referenced by adsi_process().

#define STATE_INKEY   1

Definition at line 102 of file app_adsiprog.c.

Referenced by adsi_process(), and compile_script().

#define STATE_INSUB   2

Definition at line 103 of file app_adsiprog.c.

Referenced by adsi_process(), and compile_script().

#define STATE_NORMAL   0

Definition at line 101 of file app_adsiprog.c.

Referenced by adsi_process(), and compile_script().


Function Documentation

static int adsi_exec ( struct ast_channel chan,
void *  data 
) [static]

Definition at line 1545 of file app_adsiprog.c.

References adsi_prog(), ast_adsi_available(), ast_module_user_add, ast_module_user_remove, ast_strlen_zero(), ast_verbose(), ast_module_user::chan, option_verbose, and VERBOSE_PREFIX_3.

Referenced by load_module().

01546 {
01547    int res=0;
01548    struct ast_module_user *u;
01549 
01550    u = ast_module_user_add(chan);
01551    
01552    if (ast_strlen_zero(data))
01553       data = "asterisk.adsi";
01554    
01555    if (!ast_adsi_available(chan)) {
01556       if (option_verbose > 2)
01557          ast_verbose(VERBOSE_PREFIX_3 "ADSI Unavailable on CPE.  Not bothering to try.\n");
01558    } else {
01559       if (option_verbose > 2)
01560          ast_verbose(VERBOSE_PREFIX_3 "ADSI Available on CPE.  Attempting Upload.\n");
01561       res = adsi_prog(chan, data);
01562    }
01563 
01564    ast_module_user_remove(u);
01565    
01566    return res;
01567 }

static int adsi_process ( struct adsi_script state,
char *  buf,
char *  script,
int  lineno 
) [static]

Definition at line 960 of file app_adsiprog.c.

References ARG_NUMBER, ARG_STRING, ast_log(), adsi_display::data, adsi_subscript::data, adsi_display::datalen, adsi_subscript::datalen, adsi_subscript::defined, adsi_soft_key::defined, adsi_script::desc, event, adsi_script::fdn, get_token(), getdisplaybyname(), geteventbyname(), getflagbyname(), getjustifybyname(), getkeybyname(), getstatebyname(), getsubbyname(), adsi_display::id, adsi_subscript::id, adsi_soft_key::id, adsi_subscript::ifdata, adsi_subscript::ifinscount, adsi_soft_key::initlen, adsi_subscript::inscount, adsi_script::key, LOG_WARNING, process_opcode(), process_returncode(), process_token(), adsi_soft_key::retstr, adsi_soft_key::retstrlen, adsi_script::sec, adsi_script::state, STATE_INIF, STATE_INKEY, STATE_INSUB, STATE_NORMAL, adsi_script::sub, and adsi_script::ver.

Referenced by compile_script().

00961 {
00962    char *keyword;
00963    char *args;
00964    char vname[256];
00965    char tmp[80];
00966    char tmp2[80];
00967    int lrci;
00968    int wi;
00969    int event;
00970    struct adsi_display *disp;
00971    struct adsi_subscript *newsub;
00972    /* Find the first keyword */
00973    keyword = get_token(&buf, script, lineno);
00974    if (!keyword) 
00975       return 0;
00976    switch(state->state) {
00977    case STATE_NORMAL:
00978       if (!strcasecmp(keyword, "DESCRIPTION")) {
00979          args = get_token(&buf, script, lineno);
00980          if (args) {
00981             if (process_token(state->desc, args, sizeof(state->desc) - 1, ARG_STRING))
00982                ast_log(LOG_WARNING, "'%s' is not a valid token for DESCRIPTION at line %d of %s\n", args, lineno, script);
00983          } else
00984             ast_log(LOG_WARNING, "Missing argument for DESCRIPTION at line %d of %s\n", lineno, script);
00985       } else if (!strcasecmp(keyword, "VERSION")) {
00986          args = get_token(&buf, script, lineno);
00987          if (args) {
00988             if (process_token(&state->ver, args, sizeof(state->ver) - 1, ARG_NUMBER))
00989                ast_log(LOG_WARNING, "'%s' is not a valid token for VERSION at line %d of %s\n", args, lineno, script);
00990          } else
00991             ast_log(LOG_WARNING, "Missing argument for VERSION at line %d of %s\n", lineno, script);
00992       } else if (!strcasecmp(keyword, "SECURITY")) {
00993          args = get_token(&buf, script, lineno);
00994          if (args) {
00995             if (process_token(state->sec, args, sizeof(state->sec) - 1, ARG_STRING | ARG_NUMBER))
00996                ast_log(LOG_WARNING, "'%s' is not a valid token for SECURITY at line %d of %s\n", args, lineno, script);
00997          } else
00998             ast_log(LOG_WARNING, "Missing argument for SECURITY at line %d of %s\n", lineno, script);
00999       } else if (!strcasecmp(keyword, "FDN")) {
01000          args = get_token(&buf, script, lineno);
01001          if (args) {
01002             if (process_token(state->fdn, args, sizeof(state->fdn) - 1, ARG_STRING | ARG_NUMBER))
01003                ast_log(LOG_WARNING, "'%s' is not a valid token for FDN at line %d of %s\n", args, lineno, script);
01004          } else
01005             ast_log(LOG_WARNING, "Missing argument for FDN at line %d of %s\n", lineno, script);
01006       } else if (!strcasecmp(keyword, "KEY")) {
01007          args = get_token(&buf, script, lineno);
01008          if (!args) {
01009             ast_log(LOG_WARNING, "KEY definition missing name at line %d of %s\n", lineno, script);
01010             break;
01011          }
01012          if (process_token(vname, args, sizeof(vname) - 1, ARG_STRING)) {
01013             ast_log(LOG_WARNING, "'%s' is not a valid token for a KEY name at line %d of %s\n", args, lineno, script);
01014             break;
01015          }
01016          state->key = getkeybyname(state, vname, script, lineno);
01017          if (!state->key) {
01018             ast_log(LOG_WARNING, "Out of key space at line %d of %s\n", lineno, script);
01019             break;
01020          }
01021          if (state->key->defined) {
01022             ast_log(LOG_WARNING, "Cannot redefine key '%s' at line %d of %s\n", vname, lineno, script);
01023             break;
01024          }
01025          args = get_token(&buf, script, lineno);
01026          if (!args || strcasecmp(args, "IS")) {
01027             ast_log(LOG_WARNING, "Expecting 'IS', but got '%s' at line %d of %s\n", args ? args : "<nothing>", lineno, script);
01028             break;
01029          }
01030          args = get_token(&buf, script, lineno);
01031          if (!args) {
01032             ast_log(LOG_WARNING, "KEY definition missing short name at line %d of %s\n", lineno, script);
01033             break;
01034          }
01035          if (process_token(tmp, args, sizeof(tmp) - 1, ARG_STRING)) {
01036             ast_log(LOG_WARNING, "'%s' is not a valid token for a KEY short name at line %d of %s\n", args, lineno, script);
01037             break;
01038          }
01039          args = get_token(&buf, script, lineno);
01040          if (args) {
01041             if (strcasecmp(args, "OR")) {
01042                ast_log(LOG_WARNING, "Expecting 'OR' but got '%s' instead at line %d of %s\n", args, lineno, script);
01043                break;
01044             }
01045             args = get_token(&buf, script, lineno);
01046             if (!args) {
01047                ast_log(LOG_WARNING, "KEY definition missing optional long name at line %d of %s\n", lineno, script);
01048                break;
01049             }
01050             if (process_token(tmp2, args, sizeof(tmp2) - 1, ARG_STRING)) {
01051                ast_log(LOG_WARNING, "'%s' is not a valid token for a KEY long name at line %d of %s\n", args, lineno, script);
01052                break;
01053             }
01054          } else {
01055             ast_copy_string(tmp2, tmp, sizeof(tmp2));
01056          }
01057          if (strlen(tmp2) > 18) {
01058             ast_log(LOG_WARNING, "Truncating full name to 18 characters at line %d of %s\n", lineno, script);
01059             tmp2[18] = '\0';
01060          }
01061          if (strlen(tmp) > 7) {
01062             ast_log(LOG_WARNING, "Truncating short name to 7 bytes at line %d of %s\n", lineno, script);
01063             tmp[7] = '\0';
01064          }
01065          /* Setup initial stuff */
01066          state->key->retstr[0] = 128;
01067          /* 1 has the length */
01068          state->key->retstr[2] = state->key->id;
01069          /* Put the Full name in */
01070          memcpy(state->key->retstr + 3, tmp2, strlen(tmp2));
01071          /* Update length */
01072          state->key->retstrlen = strlen(tmp2) + 3;
01073          /* Put trailing 0xff */
01074          state->key->retstr[state->key->retstrlen++] = 0xff;
01075          /* Put the short name */
01076          memcpy(state->key->retstr + state->key->retstrlen, tmp, strlen(tmp));
01077          /* Update length */
01078          state->key->retstrlen += strlen(tmp);
01079          /* Put trailing 0xff */
01080          state->key->retstr[state->key->retstrlen++] = 0xff;
01081          /* Record initial length */
01082          state->key->initlen = state->key->retstrlen;
01083          state->state = STATE_INKEY;
01084       } else if (!strcasecmp(keyword, "SUB")) {
01085          args = get_token(&buf, script, lineno);
01086          if (!args) {
01087             ast_log(LOG_WARNING, "SUB definition missing name at line %d of %s\n", lineno, script);
01088             break;
01089          }
01090          if (process_token(vname, args, sizeof(vname) - 1, ARG_STRING)) {
01091             ast_log(LOG_WARNING, "'%s' is not a valid token for a KEY name at line %d of %s\n", args, lineno, script);
01092             break;
01093          }
01094          state->sub = getsubbyname(state, vname, script, lineno);
01095          if (!state->sub) {
01096             ast_log(LOG_WARNING, "Out of subroutine space at line %d of %s\n", lineno, script);
01097             break;
01098          }
01099          if (state->sub->defined) {
01100             ast_log(LOG_WARNING, "Cannot redefine subroutine '%s' at line %d of %s\n", vname, lineno, script);
01101             break;
01102          }
01103          /* Setup sub */
01104          state->sub->data[0] = 130;
01105          /* 1 is the length */
01106          state->sub->data[2] = 0x0; /* Clear extensibility bit */
01107          state->sub->datalen = 3;
01108          if (state->sub->id) {
01109             /* If this isn't the main subroutine, make a subroutine label for it */
01110             state->sub->data[3] = 9;
01111             state->sub->data[4] = state->sub->id;
01112             /* 5 is length */
01113             state->sub->data[6] = 0xff;
01114             state->sub->datalen = 7;
01115          }
01116          args = get_token(&buf, script, lineno);
01117          if (!args || strcasecmp(args, "IS")) {
01118             ast_log(LOG_WARNING, "Expecting 'IS', but got '%s' at line %d of %s\n", args ? args : "<nothing>", lineno, script);
01119             break;
01120          }
01121          state->state = STATE_INSUB;
01122       } else if (!strcasecmp(keyword, "STATE")) {
01123          args = get_token(&buf, script, lineno);
01124          if (!args) {
01125             ast_log(LOG_WARNING, "STATE definition missing name at line %d of %s\n", lineno, script);
01126             break;
01127          }
01128          if (process_token(vname, args, sizeof(vname) - 1, ARG_STRING)) {
01129             ast_log(LOG_WARNING, "'%s' is not a valid token for a STATE name at line %d of %s\n", args, lineno, script);
01130             break;
01131          }
01132          if (getstatebyname(state, vname, script, lineno, 0)) {
01133             ast_log(LOG_WARNING, "State '%s' is already defined at line %d of %s\n", vname, lineno, script);
01134             break;
01135          }
01136          getstatebyname(state, vname, script, lineno, 1);
01137       } else if (!strcasecmp(keyword, "FLAG")) {
01138          args = get_token(&buf, script, lineno);
01139          if (!args) {
01140             ast_log(LOG_WARNING, "FLAG definition missing name at line %d of %s\n", lineno, script);
01141             break;
01142          }
01143          if (process_token(vname, args, sizeof(vname) - 1, ARG_STRING)) {
01144             ast_log(LOG_WARNING, "'%s' is not a valid token for a FLAG name at line %d of %s\n", args, lineno, script);
01145             break;
01146          }
01147          if (getflagbyname(state, vname, script, lineno, 0)) {
01148             ast_log(LOG_WARNING, "Flag '%s' is already defined\n", vname);
01149             break;
01150          }
01151          getflagbyname(state, vname, script, lineno, 1);
01152       } else if (!strcasecmp(keyword, "DISPLAY")) {
01153          lrci = 0;
01154          wi = 0;
01155          args = get_token(&buf, script, lineno);
01156          if (!args) {
01157             ast_log(LOG_WARNING, "SUB definition missing name at line %d of %s\n", lineno, script);
01158             break;
01159          }
01160          if (process_token(vname, args, sizeof(vname) - 1, ARG_STRING)) {
01161             ast_log(LOG_WARNING, "'%s' is not a valid token for a KEY name at line %d of %s\n", args, lineno, script);
01162             break;
01163          }
01164          if (getdisplaybyname(state, vname, script, lineno, 0)) {
01165             ast_log(LOG_WARNING, "State '%s' is already defined\n", vname);
01166             break;
01167          }
01168          disp = getdisplaybyname(state, vname, script, lineno, 1);
01169          if (!disp)
01170             break;
01171          args = get_token(&buf, script, lineno);
01172          if (!args || strcasecmp(args, "IS")) {
01173             ast_log(LOG_WARNING, "Missing 'IS' at line %d of %s\n", lineno, script);
01174             break;
01175          }
01176          args = get_token(&buf, script, lineno);
01177          if (!args) {
01178             ast_log(LOG_WARNING, "Missing Column 1 text at line %d of %s\n", lineno, script);
01179             break;
01180          }
01181          if (process_token(tmp, args, sizeof(tmp) - 1, ARG_STRING)) {
01182             ast_log(LOG_WARNING, "Token '%s' is not valid column 1 text at line %d of %s\n", args, lineno, script);
01183             break;
01184          }
01185          if (strlen(tmp) > 20) {
01186             ast_log(LOG_WARNING, "Truncating column one to 20 characters at line %d of %s\n", lineno, script);
01187             tmp[20] = '\0';
01188          }
01189          memcpy(disp->data + 5, tmp, strlen(tmp));
01190          disp->datalen = strlen(tmp) + 5;
01191          disp->data[disp->datalen++] = 0xff;
01192 
01193          args = get_token(&buf, script, lineno);
01194          if (args && !process_token(tmp, args, sizeof(tmp) - 1, ARG_STRING)) {
01195             /* Got a column two */
01196             if (strlen(tmp) > 20) {
01197                ast_log(LOG_WARNING, "Truncating column two to 20 characters at line %d of %s\n", lineno, script);
01198                tmp[20] = '\0';
01199             }
01200             memcpy(disp->data + disp->datalen, tmp, strlen(tmp));
01201             disp->datalen += strlen(tmp);
01202             args = get_token(&buf, script, lineno);
01203          }
01204          while(args) {
01205             if (!strcasecmp(args, "JUSTIFY")) {
01206                args = get_token(&buf, script, lineno);
01207                if (!args) {
01208                   ast_log(LOG_WARNING, "Qualifier 'JUSTIFY' requires an argument at line %d of %s\n", lineno, script);
01209                   break;
01210                }
01211                lrci = getjustifybyname(args);
01212                if (lrci < 0) {
01213                   ast_log(LOG_WARNING, "'%s' is not a valid justification at line %d of %s\n", args, lineno, script);
01214                   break;
01215                }
01216             } else if (!strcasecmp(args, "WRAP")) {
01217                wi = 0x80;
01218             } else {
01219                ast_log(LOG_WARNING, "'%s' is not a known qualifier at line %d of %s\n", args, lineno, script);
01220                break;
01221             }
01222             args = get_token(&buf, script, lineno);
01223          }
01224          if (args) {
01225             /* Something bad happened */
01226             break;
01227          }
01228          disp->data[0] = 129;
01229          disp->data[1] = disp->datalen - 2;
01230          disp->data[2] = ((lrci & 0x3) << 6) | disp->id;
01231          disp->data[3] = wi;
01232          disp->data[4] = 0xff;
01233       } else {
01234          ast_log(LOG_WARNING, "Invalid or Unknown keyword '%s' in PROGRAM\n", keyword);
01235       }
01236       break;
01237    case STATE_INKEY:
01238       if (process_returncode(state->key, keyword, buf, state, script, lineno)) {
01239          if (!strcasecmp(keyword, "ENDKEY")) {
01240             /* Return to normal operation and increment current key */
01241             state->state = STATE_NORMAL;
01242             state->key->defined = 1;
01243             state->key->retstr[1] = state->key->retstrlen - 2;
01244             state->key = NULL;
01245          } else {
01246             ast_log(LOG_WARNING, "Invalid or Unknown keyword '%s' in SOFTKEY definition at line %d of %s\n", keyword, lineno, script);
01247          }
01248       }
01249       break;
01250    case STATE_INIF:
01251       if (process_opcode(state->sub, keyword, buf, state, script, lineno)) {
01252          if (!strcasecmp(keyword, "ENDIF")) {
01253             /* Return to normal SUB operation and increment current key */
01254             state->state = STATE_INSUB;
01255             state->sub->defined = 1;
01256             /* Store the proper number of instructions */
01257             state->sub->ifdata[2] = state->sub->ifinscount;
01258          } else if (!strcasecmp(keyword, "GOTO")) {
01259             args = get_token(&buf, script, lineno);
01260             if (!args) {
01261                ast_log(LOG_WARNING, "GOTO clause missing Subscript name at line %d of %s\n", lineno, script);
01262                break;
01263             }
01264             if (process_token(tmp, args, sizeof(tmp) - 1, ARG_STRING)) {
01265                ast_log(LOG_WARNING, "'%s' is not a valid subscript name token at line %d of %s\n", args, lineno, script);
01266                break;
01267             }
01268             newsub = getsubbyname(state, tmp, script, lineno);
01269             if (!newsub) 
01270                break;
01271             /* Somehow you use GOTO to go to another place */
01272             state->sub->data[state->sub->datalen++] = 0x8;
01273             state->sub->data[state->sub->datalen++] = state->sub->ifdata[1];
01274             state->sub->data[state->sub->datalen++] = newsub->id;
01275             /* Terminate */
01276             state->sub->data[state->sub->datalen++] = 0xff;
01277             /* Increment counters */
01278             state->sub->inscount++;
01279             state->sub->ifinscount++;
01280          } else {
01281             ast_log(LOG_WARNING, "Invalid or Unknown keyword '%s' in IF clause at line %d of %s\n", keyword, lineno, script);
01282          }
01283       } else
01284          state->sub->ifinscount++;
01285       break;
01286    case STATE_INSUB:
01287       if (process_opcode(state->sub, keyword, buf, state, script, lineno)) {
01288          if (!strcasecmp(keyword, "ENDSUB")) {
01289             /* Return to normal operation and increment current key */
01290             state->state = STATE_NORMAL;
01291             state->sub->defined = 1;
01292             /* Store the proper length */
01293             state->sub->data[1] = state->sub->datalen - 2;
01294             if (state->sub->id) {
01295                /* if this isn't main, store number of instructions, too */
01296                state->sub->data[5] = state->sub->inscount;
01297             }
01298             state->sub = NULL;
01299          } else if (!strcasecmp(keyword, "IFEVENT")) {
01300             args = get_token(&buf, script, lineno);
01301             if (!args) {
01302                ast_log(LOG_WARNING, "IFEVENT clause missing Event name at line %d of %s\n", lineno, script);
01303                break;
01304             }
01305             event = geteventbyname(args);
01306             if (event < 1) {
01307                ast_log(LOG_WARNING, "'%s' is not a valid event\n", args);
01308                break;
01309             }
01310             args = get_token(&buf, script, lineno);
01311             if (!args || strcasecmp(args, "THEN")) {
01312                ast_log(LOG_WARNING, "IFEVENT clause missing 'THEN' at line %d of %s\n", lineno, script);
01313                break;
01314             }
01315             state->sub->ifinscount = 0;
01316             state->sub->ifdata = state->sub->data + 
01317                   state->sub->datalen;
01318             /* Reserve header and insert op codes */
01319             state->sub->ifdata[0] = 0x1;
01320             state->sub->ifdata[1] = event;
01321             /* 2 is for the number of instructions */
01322             state->sub->ifdata[3] = 0xff;
01323             state->sub->datalen += 4;
01324             /* Update Subscript instruction count */
01325             state->sub->inscount++;
01326             state->state = STATE_INIF;
01327          } else {
01328             ast_log(LOG_WARNING, "Invalid or Unknown keyword '%s' in SUB definition at line %d of %s\n", keyword, lineno, script);
01329          }
01330       }
01331       break;
01332    default:
01333       ast_log(LOG_WARNING, "Can't process keyword '%s' in weird state %d\n", keyword, state->state);
01334    }
01335    return 0;
01336 }

static int adsi_prog ( struct ast_channel chan,
char *  script 
) [static]

Definition at line 1430 of file app_adsiprog.c.

References ADSI_MSG_DOWNLOAD, ast_adsi_begin_download(), ast_adsi_load_session(), ast_adsi_transmit_message(), ast_log(), ast_verbose(), compile_script(), adsi_script::desc, adsi_script::fdn, free, adsi_script::keys, LOG_NOTICE, LOG_WARNING, adsi_script::numkeys, option_verbose, adsi_soft_key::retstr, adsi_soft_key::retstrlen, adsi_script::sec, adsi_script::ver, VERBOSE_PREFIX_3, and adsi_soft_key::vname.

Referenced by adsi_exec().

01431 {
01432    struct adsi_script *scr;
01433    int x;
01434    unsigned char buf[1024];
01435    int bytes;
01436    scr = compile_script(script);
01437    if (!scr) 
01438       return -1;
01439 
01440    /* Start an empty ADSI Session */
01441    if (ast_adsi_load_session(chan, NULL, 0, 1) < 1) 
01442       return -1;
01443 
01444    /* Now begin the download attempt */
01445    if (ast_adsi_begin_download(chan, scr->desc, scr->fdn, scr->sec, scr->ver)) {
01446       /* User rejected us for some reason */
01447       if (option_verbose > 2)
01448          ast_verbose(VERBOSE_PREFIX_3 "User rejected download attempt\n");
01449       ast_log(LOG_NOTICE, "User rejected download on channel %s\n", chan->name);
01450       free(scr);
01451       return -1;
01452    }
01453 
01454    bytes = 0;
01455    /* Start with key definitions */
01456    for (x=0;x<scr->numkeys;x++) {
01457       if (bytes + scr->keys[x].retstrlen > 253) {
01458          /* Send what we've collected so far */
01459          if (ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD)) {
01460             ast_log(LOG_WARNING, "Unable to send chunk ending at %d\n", x);
01461             return -1;
01462          }
01463          bytes =0;
01464       }
01465       memcpy(buf + bytes, scr->keys[x].retstr, scr->keys[x].retstrlen);
01466       bytes += scr->keys[x].retstrlen;
01467 #ifdef DUMP_MESSAGES
01468       dump_message("Key", scr->keys[x].vname, scr->keys[x].retstr, scr->keys[x].retstrlen);
01469 #endif
01470    }
01471    if (bytes) {
01472       if (ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD)) {
01473          ast_log(LOG_WARNING, "Unable to send chunk ending at %d\n", x);
01474          return -1;
01475       }
01476    }
01477 
01478    bytes = 0;
01479    /* Continue with the display messages */
01480    for (x=0;x<scr->numdisplays;x++) {
01481       if (bytes + scr->displays[x].datalen > 253) {
01482          /* Send what we've collected so far */
01483          if (ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD)) {
01484             ast_log(LOG_WARNING, "Unable to send chunk ending at %d\n", x);
01485             return -1;
01486          }
01487          bytes =0;
01488       }
01489       memcpy(buf + bytes, scr->displays[x].data, scr->displays[x].datalen);
01490       bytes += scr->displays[x].datalen;
01491 #ifdef DUMP_MESSAGES
01492       dump_message("Display", scr->displays[x].vname, scr->displays[x].data, scr->displays[x].datalen);
01493 #endif
01494    }
01495    if (bytes) {
01496       if (ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD)) {
01497          ast_log(LOG_WARNING, "Unable to send chunk ending at %d\n", x);
01498          return -1;
01499       }
01500    }
01501 
01502    bytes = 0;
01503    /* Send subroutines */
01504    for (x=0;x<scr->numsubs;x++) {
01505       if (bytes + scr->subs[x].datalen > 253) {
01506          /* Send what we've collected so far */
01507          if (ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD)) {
01508             ast_log(LOG_WARNING, "Unable to send chunk ending at %d\n", x);
01509             return -1;
01510          }
01511          bytes =0;
01512       }
01513       memcpy(buf + bytes, scr->subs[x].data, scr->subs[x].datalen);
01514       bytes += scr->subs[x].datalen;
01515 #ifdef DUMP_MESSAGES
01516       dump_message("Sub", scr->subs[x].vname, scr->subs[x].data, scr->subs[x].datalen);
01517 #endif
01518    }
01519    if (bytes) {
01520       if (ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD)) {
01521          ast_log(LOG_WARNING, "Unable to send chunk ending at %d\n", x);
01522          return -1;
01523       }
01524    }
01525 
01526 
01527    bytes = 0;
01528    bytes += ast_adsi_display(buf, ADSI_INFO_PAGE, 1, ADSI_JUST_LEFT, 0, "Download complete.", "");
01529    bytes += ast_adsi_set_line(buf, ADSI_INFO_PAGE, 1);
01530    if (ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY) < 0)
01531       return -1;
01532    if (ast_adsi_end_download(chan)) {
01533       /* Download failed for some reason */
01534       if (option_verbose > 2)
01535          ast_verbose(VERBOSE_PREFIX_3 "Download attempt failed\n");
01536       ast_log(LOG_NOTICE, "Download failed on %s\n", chan->name);
01537       free(scr);
01538       return -1;
01539    }
01540    free(scr);
01541    ast_adsi_unload_session(chan);
01542    return 0;
01543 }

AST_MODULE_INFO_STANDARD ( ASTERISK_GPL_KEY  ,
"Asterisk ADSI Programming Application"   
)

static int clearcbone ( char *  buf,
char *  name,
int  id,
char *  args,
struct adsi_script istate,
char *  script,
int  lineno 
) [static]

Definition at line 707 of file app_adsiprog.c.

References ast_log(), get_token(), and LOG_WARNING.

00708 {
00709    char *tok;
00710    tok = get_token(&args, script, lineno);
00711    if (tok)
00712       ast_log(LOG_WARNING, "CLEARCB1 requires no arguments ('%s') at line %d of %s\n", tok, lineno, script);
00713 
00714    buf[0] = id;
00715    buf[1] = 0;
00716    return 2;
00717 }

static int cleardisplay ( char *  buf,
char *  name,
int  id,
char *  args,
struct adsi_script istate,
char *  script,
int  lineno 
) [static]

Definition at line 683 of file app_adsiprog.c.

References ast_log(), get_token(), and LOG_WARNING.

00684 {
00685    char *tok;
00686    tok = get_token(&args, script, lineno);
00687    if (tok) 
00688       ast_log(LOG_WARNING, "Clearing display requires no arguments ('%s') at line %d of %s\n", tok, lineno, script);
00689 
00690    buf[0] = id;
00691    buf[1] = 0x00;
00692    return 2;
00693 }

static int clearflag ( char *  buf,
char *  name,
int  id,
char *  args,
struct adsi_script state,
char *  script,
int  lineno 
) [static]

Definition at line 442 of file app_adsiprog.c.

References ARG_STRING, ast_log(), get_token(), getflagbyname(), adsi_flag::id, LOG_WARNING, and process_token().

00443 {
00444    char *tok;
00445    struct adsi_flag *flag;
00446    char sname[80];
00447    tok = get_token(&args, script, lineno);
00448    if (!tok) {
00449       ast_log(LOG_WARNING, "Clearing flag requires a flag number at line %d of %s\n", lineno, script);
00450       return 0;
00451    }
00452    if (process_token(sname, tok, sizeof(sname) - 1, ARG_STRING)) {
00453       ast_log(LOG_WARNING, "Invalid flag '%s' at line %d of %s\n", tok, lineno, script);
00454       return 0;
00455    }
00456    flag = getflagbyname(state, sname, script, lineno, 0);
00457    if (!flag) {
00458       ast_log(LOG_WARNING, "Flag '%s' is undeclared at line %d of %s\n", sname, lineno, script);
00459       return 0;
00460    }
00461    buf[0] = id;
00462    buf[1] = ((flag->id & 0x7) << 4);
00463    return 2;
00464 }

static int cleartimer ( char *  buf,
char *  name,
int  id,
char *  args,
struct adsi_script istate,
char *  script,
int  lineno 
) [static]

Definition at line 383 of file app_adsiprog.c.

References ast_log(), get_token(), and LOG_WARNING.

00384 {
00385    char *tok;
00386    tok = get_token(&args, script, lineno);
00387    if (tok) 
00388       ast_log(LOG_WARNING, "Clearing timer requires no arguments ('%s') at line %d of %s\n", tok, lineno, script);
00389 
00390    buf[0] = id;
00391    /* For some reason the clear code is different slightly */
00392    if (id == 7)
00393       buf[1] = 0x10;
00394    else
00395       buf[1] = 0x00;
00396    return 2;
00397 }

static struct adsi_script* compile_script ( char *  script  )  [static]

Definition at line 1338 of file app_adsiprog.c.

References adsi_process(), ast_calloc, ast_config_AST_CONFIG_DIR, ast_log(), ast_strlen_zero(), f, free, getsubbyname(), lineno, LOG_WARNING, STATE_INKEY, STATE_INSUB, and STATE_NORMAL.

Referenced by adsi_prog().

01339 {
01340    FILE *f;
01341    char fn[256];
01342    char buf[256];
01343    char *c;
01344    int lineno=0;
01345    int x, err;
01346    struct adsi_script *scr;
01347    if (script[0] == '/')
01348       ast_copy_string(fn, script, sizeof(fn));
01349    else
01350       snprintf(fn, sizeof(fn), "%s/%s", (char *)ast_config_AST_CONFIG_DIR, script);
01351    f = fopen(fn, "r");
01352    if (!f) {
01353       ast_log(LOG_WARNING, "Can't open file '%s'\n", fn);
01354       return NULL;
01355    }
01356    if (!(scr = ast_calloc(1, sizeof(*scr)))) {
01357       fclose(f);
01358       return NULL;
01359    }
01360    /* Create "main" as first subroutine */
01361    getsubbyname(scr, "main", NULL, 0);
01362    while(!feof(f)) {
01363       fgets(buf, sizeof(buf), f);
01364       if (!feof(f)) {
01365          lineno++;
01366          /* Trim off trailing return */
01367          buf[strlen(buf) - 1] = '\0';
01368          c = strchr(buf, ';');
01369          /* Strip comments */
01370          if (c)
01371             *c = '\0';
01372          if (!ast_strlen_zero(buf))
01373             adsi_process(scr, buf, script, lineno);
01374       }
01375    }
01376    fclose(f);
01377    /* Make sure we're in the main routine again */
01378    switch(scr->state) {
01379    case STATE_NORMAL:
01380       break;
01381    case STATE_INSUB:
01382       ast_log(LOG_WARNING, "Missing ENDSUB at end of file %s\n", script);
01383       free(scr);
01384       return NULL;
01385    case STATE_INKEY:
01386       ast_log(LOG_WARNING, "Missing ENDKEY at end of file %s\n", script);
01387       free(scr);
01388       return NULL;
01389    }
01390    err = 0;
01391 
01392    /* Resolve all keys and record their lengths */
01393    for (x=0;x<scr->numkeys;x++) {
01394       if (!scr->keys[x].defined) {
01395          ast_log(LOG_WARNING, "Key '%s' referenced but never defined in file %s\n", scr->keys[x].vname, fn);
01396          err++;
01397       }
01398    }
01399 
01400    /* Resolve all subs */
01401    for (x=0;x<scr->numsubs;x++) {
01402       if (!scr->subs[x].defined) {
01403          ast_log(LOG_WARNING, "Subscript '%s' referenced but never defined in file %s\n", scr->subs[x].vname, fn);
01404          err++;
01405       }
01406       if (x == (scr->numsubs - 1)) {
01407          /* Clear out extension bit on last message */
01408          scr->subs[x].data[2] = 0x80;
01409       }
01410    }
01411 
01412    if (err) {
01413       free(scr);
01414       return NULL;
01415    }
01416    return scr;
01417 }

static int digitcollect ( char *  buf,
char *  name,
int  id,
char *  args,
struct adsi_script istate,
char *  script,
int  lineno 
) [static]

Definition at line 719 of file app_adsiprog.c.

References ast_log(), get_token(), and LOG_WARNING.

00720 {
00721    char *tok;
00722    tok = get_token(&args, script, lineno);
00723    if (tok) 
00724       ast_log(LOG_WARNING, "Digitcollect requires no arguments ('%s') at line %d of %s\n", tok, lineno, script);
00725 
00726    buf[0] = id;
00727    buf[1] = 0xf;
00728    return 2;
00729 }

static int digitdirect ( char *  buf,
char *  name,
int  id,
char *  args,
struct adsi_script istate,
char *  script,
int  lineno 
) [static]

Definition at line 695 of file app_adsiprog.c.

References ast_log(), get_token(), and LOG_WARNING.

00696 {
00697    char *tok;
00698    tok = get_token(&args, script, lineno);
00699    if (tok) 
00700       ast_log(LOG_WARNING, "Digitdirect requires no arguments ('%s') at line %d of %s\n", tok, lineno, script);
00701 
00702    buf[0] = id;
00703    buf[1] = 0x7;
00704    return 2;
00705 }

static char* get_token ( char **  buf,
char *  script,
int  lineno 
) [static]

Definition at line 225 of file app_adsiprog.c.

References ast_log(), and LOG_WARNING.

Referenced by adsi_process(), clearcbone(), cleardisplay(), clearflag(), cleartimer(), digitcollect(), digitdirect(), goto_line(), goto_line_rel(), onevent(), process_opcode(), process_returncode(), send_delay(), send_dtmf(), set_state(), setflag(), showdisplay(), showkeys(), starttimer(), and subscript().

00226 {
00227    char *tmp = *buf;
00228    char *keyword;
00229    int quoted = 0;
00230    /* Advance past any white space */
00231    while(*tmp && (*tmp < 33))
00232       tmp++;
00233    if (!*tmp)
00234       return NULL;
00235    keyword = tmp;
00236    while(*tmp && ((*tmp > 32)  || quoted)) {
00237       if (*tmp == '\"') {
00238          quoted = !quoted;
00239       }
00240       tmp++;
00241    }
00242    if (quoted) {
00243       ast_log(LOG_WARNING, "Mismatched quotes at line %d of %s\n", lineno, script);
00244       return NULL;
00245    }
00246    *tmp = '\0';
00247    tmp++;
00248    while(*tmp && (*tmp < 33))
00249       tmp++;
00250    /* Note where we left off */
00251    *buf = tmp;
00252    return keyword;
00253 }

static struct adsi_display* getdisplaybyname ( struct adsi_script state,
char *  name,
char *  script,
int  lineno,
int  create 
) [static]

Definition at line 556 of file app_adsiprog.c.

References ast_log(), adsi_script::displays, LOG_WARNING, adsi_script::numdisplays, and adsi_display::vname.

Referenced by adsi_process(), and showdisplay().

00557 {
00558    int x;
00559    for (x=0;x<state->numdisplays;x++) 
00560       if (!strcasecmp(state->displays[x].vname, name)) 
00561          return &state->displays[x];
00562    /* Return now if we're not allowed to create */
00563    if (!create)
00564       return NULL;
00565    if (state->numdisplays > 61) {
00566       ast_log(LOG_WARNING, "No more display space at line %d of %s\n", lineno, script);
00567       return NULL;
00568    }
00569    ast_copy_string(state->displays[state->numdisplays].vname, name, sizeof(state->displays[state->numdisplays].vname));
00570    state->displays[state->numdisplays].id = state->numdisplays + 1;
00571    state->numdisplays++;
00572    return &state->displays[state->numdisplays-1];
00573 }

static int geteventbyname ( char *  name  )  [static]

Definition at line 485 of file app_adsiprog.c.

References events.

Referenced by adsi_process(), and onevent().

00486 {
00487    int x;
00488    for (x=0;x<sizeof(events) / sizeof(events[0]); x++) {
00489       if (!strcasecmp(events[x].name, name))
00490          return events[x].id;
00491    }
00492    return 0;
00493 }

static struct adsi_flag* getflagbyname ( struct adsi_script state,
char *  name,
char *  script,
int  lineno,
int  create 
) [static]

Definition at line 399 of file app_adsiprog.c.

References ast_log(), adsi_script::flags, LOG_WARNING, adsi_script::numflags, and adsi_flag::vname.

Referenced by adsi_process(), clearflag(), setflag(), and showkeys().

00400 {
00401    int x;
00402    for (x=0;x<state->numflags;x++) 
00403       if (!strcasecmp(state->flags[x].vname, name)) 
00404          return &state->flags[x];
00405    /* Return now if we're not allowed to create */
00406    if (!create)
00407       return NULL;
00408    if (state->numflags > 6) {
00409       ast_log(LOG_WARNING, "No more flag space at line %d of %s\n", lineno, script);
00410       return NULL;
00411    }
00412    ast_copy_string(state->flags[state->numflags].vname, name, sizeof(state->flags[state->numflags].vname));
00413    state->flags[state->numflags].id = state->numflags + 1;
00414    state->numflags++;
00415    return &state->flags[state->numflags-1];
00416 }

static int getjustifybyname ( char *  name  )  [static]

Definition at line 495 of file app_adsiprog.c.

References justify.

Referenced by adsi_process().

00496 {
00497    int x;
00498    for (x=0;x<sizeof(justify) / sizeof(justify[0]); x++) {
00499       if (!strcasecmp(justify[x].name, name))
00500          return justify[x].id;
00501    }
00502    return -1;
00503 }

static struct adsi_soft_key* getkeybyname ( struct adsi_script state,
char *  name,
char *  script,
int  lineno 
) [static]

Definition at line 505 of file app_adsiprog.c.

References ast_log(), adsi_script::keys, LOG_WARNING, adsi_script::numkeys, and adsi_soft_key::vname.

Referenced by adsi_process(), and showkeys().

00506 {
00507    int x;
00508    for (x=0;x<state->numkeys;x++) 
00509       if (!strcasecmp(state->keys[x].vname, name)) 
00510          return &state->keys[x];
00511    if (state->numkeys > 61) {
00512       ast_log(LOG_WARNING, "No more key space at line %d of %s\n", lineno, script);
00513       return NULL;
00514    }
00515    ast_copy_string(state->keys[state->numkeys].vname, name, sizeof(state->keys[state->numkeys].vname));
00516    state->keys[state->numkeys].id = state->numkeys + 2;
00517    state->numkeys++;
00518    return &state->keys[state->numkeys-1];
00519 }

static struct adsi_state* getstatebyname ( struct adsi_script state,
char *  name,
char *  script,
int  lineno,
int  create 
) [static]

Definition at line 537 of file app_adsiprog.c.

References ast_log(), LOG_WARNING, adsi_script::numstates, adsi_script::states, and adsi_state::vname.

Referenced by adsi_process(), and onevent().

00538 {
00539    int x;
00540    for (x=0;x<state->numstates;x++) 
00541       if (!strcasecmp(state->states[x].vname, name)) 
00542          return &state->states[x];
00543    /* Return now if we're not allowed to create */
00544    if (!create)
00545       return NULL;
00546    if (state->numstates > 253) {
00547       ast_log(LOG_WARNING, "No more state space at line %d of %s\n", lineno, script);
00548       return NULL;
00549    }
00550    ast_copy_string(state->states[state->numstates].vname, name, sizeof(state->states[state->numstates].vname));
00551    state->states[state->numstates].id = state->numstates + 1;
00552    state->numstates++;
00553    return &state->states[state->numstates-1];
00554 }

static struct adsi_subscript* getsubbyname ( struct adsi_script state,
char *  name,
char *  script,
int  lineno 
) [static]

Definition at line 521 of file app_adsiprog.c.

References ast_log(), LOG_WARNING, adsi_script::numsubs, adsi_script::subs, and adsi_subscript::vname.

Referenced by adsi_process(), compile_script(), onevent(), and subscript().

00522 {
00523    int x;
00524    for (x=0;x<state->numsubs;x++) 
00525       if (!strcasecmp(state->subs[x].vname, name)) 
00526          return &state->subs[x];
00527    if (state->numsubs > 127) {
00528       ast_log(LOG_WARNING, "No more subscript space at line %d of %s\n", lineno, script);
00529       return NULL;
00530    }
00531    ast_copy_string(state->subs[state->numsubs].vname, name, sizeof(state->subs[state->numsubs].vname));
00532    state->subs[state->numsubs].id = state->numsubs;
00533    state->numsubs++;
00534    return &state->subs[state->numsubs-1];
00535 }

static int goto_line ( char *  buf,
char *  name,
int  id,
char *  args,
struct adsi_script state,
char *  script,
int  lineno 
) [static]

Definition at line 284 of file app_adsiprog.c.

References ARG_NUMBER, ast_log(), get_token(), LOG_WARNING, and process_token().

00285 {
00286    char *page;
00287    char *gline;
00288    int line;
00289    unsigned char cmd;
00290    page = get_token(&args, script, lineno);
00291    gline = get_token(&args, script, lineno);
00292    if (!page || !gline) {
00293       ast_log(LOG_WARNING, "Expecting page and line number for GOTOLINE at line %d of %s\n", lineno, script);
00294       return 0;
00295    }
00296    if (!strcasecmp(page, "INFO")) {
00297       cmd = 0;
00298    } else if (!strcasecmp(page, "COMM")) {
00299       cmd = 0x80;
00300    } else {
00301       ast_log(LOG_WARNING, "Expecting either 'INFO' or 'COMM' page, got got '%s' at line %d of %s\n", page, lineno, script);
00302       return 0;
00303    }
00304    if (process_token(&line, gline, sizeof(line), ARG_NUMBER)) {
00305       ast_log(LOG_WARNING, "Invalid line number '%s' at line %d of %s\n", gline, lineno, script);
00306       return 0;
00307    }
00308    cmd |= line;
00309    buf[0] = 0x8b;
00310    buf[1] = cmd;
00311    return 2;
00312 }

static int goto_line_rel ( char *  buf,
char *  name,
int  id,
char *  args,
struct adsi_script state,
char *  script,
int  lineno 
) [static]

Definition at line 314 of file app_adsiprog.c.

References ARG_NUMBER, ast_log(), get_token(), LOG_WARNING, and process_token().

00315 {
00316    char *dir;
00317    char *gline;
00318    int line;
00319    unsigned char cmd;
00320    dir = get_token(&args, script, lineno);
00321    gline = get_token(&args, script, lineno);
00322    if (!dir || !gline) {
00323       ast_log(LOG_WARNING, "Expecting direction and number of lines for GOTOLINEREL at line %d of %s\n", lineno, script);
00324       return 0;
00325    }
00326    if (!strcasecmp(dir, "UP")) {
00327       cmd = 0;
00328    } else if (!strcasecmp(dir, "DOWN")) {
00329       cmd = 0x20;
00330    } else {
00331       ast_log(LOG_WARNING, "Expecting either 'UP' or 'DOWN' direction, got '%s' at line %d of %s\n", dir, lineno, script);
00332       return 0;
00333    }
00334    if (process_token(&line, gline, sizeof(line), ARG_NUMBER)) {
00335       ast_log(LOG_WARNING, "Invalid line number '%s' at line %d of %s\n", gline, lineno, script);
00336       return 0;
00337    }
00338    cmd |= line;
00339    buf[0] = 0x8c;
00340    buf[1] = cmd;
00341    return 2;
00342 }

static int load_module ( void   )  [static]

Definition at line 1581 of file app_adsiprog.c.

References adsi_exec(), app, ast_register_application(), descrip, and synopsis.

01582 {
01583    return ast_register_application(app, adsi_exec, synopsis, descrip);
01584 }

static int onevent ( char *  buf,
char *  name,
int  id,
char *  args,
struct adsi_script state,
char *  script,
int  lineno 
) [static]

Definition at line 753 of file app_adsiprog.c.

References ARG_STRING, ast_log(), event, get_token(), geteventbyname(), getstatebyname(), getsubbyname(), adsi_subscript::id, LOG_WARNING, process_token(), and subscript().

00754 {
00755    char *tok;
00756    char subscript[80];
00757    char sname[80];
00758    int sawin=0;
00759    int event;
00760    int snums[8];
00761    int scnt = 0;
00762    int x;
00763    struct adsi_subscript *sub;
00764    tok = get_token(&args, script, lineno);
00765    if (!tok) {
00766       ast_log(LOG_WARNING, "Missing event for 'ONEVENT' at line %d of %s\n", lineno, script);
00767       return 0;
00768    }
00769    event = geteventbyname(tok);
00770    if (event < 1) {
00771       ast_log(LOG_WARNING, "'%s' is not a valid event name, at line %d of %s\n", args, lineno, script);
00772       return 0;
00773    }
00774    tok = get_token(&args, script, lineno);
00775    while ((!sawin && !strcasecmp(tok, "IN")) ||
00776           (sawin && !strcasecmp(tok, "OR"))) {
00777       sawin = 1;
00778       if (scnt > 7) {
00779          ast_log(LOG_WARNING, "No more than 8 states may be specified for inclusion at line %d of %s\n", lineno, script);
00780          return 0;
00781       }
00782       /* Process 'in' things */
00783       tok = get_token(&args, script, lineno);
00784       if (process_token(sname, tok, sizeof(sname), ARG_STRING)) {
00785          ast_log(LOG_WARNING, "'%s' is not a valid state name at line %d of %s\n", tok, lineno, script);
00786          return 0;
00787       }
00788       if ((snums[scnt] = getstatebyname(state, sname, script, lineno, 0) < 0)) {
00789          ast_log(LOG_WARNING, "State '%s' not declared at line %d of %s\n", sname, lineno, script);
00790          return 0;
00791       }
00792       scnt++;
00793       tok = get_token(&args, script, lineno);
00794       if (!tok)
00795          break;
00796    }
00797    if (!tok || strcasecmp(tok, "GOTO")) {
00798       if (!tok)
00799          tok = "<nothing>";
00800       if (sawin) 
00801          ast_log(LOG_WARNING, "Got '%s' while looking for 'GOTO' or 'OR' at line %d of %s\n", tok, lineno, script);
00802       else
00803          ast_log(LOG_WARNING, "Got '%s' while looking for 'GOTO' or 'IN' at line %d of %s\n", tok, lineno, script);
00804    }
00805    tok = get_token(&args, script, lineno);
00806    if (!tok) {
00807       ast_log(LOG_WARNING, "Missing subscript to call at line %d of %s\n", lineno, script);
00808       return 0;
00809    }
00810    if (process_token(subscript, tok, sizeof(subscript) - 1, ARG_STRING)) {
00811       ast_log(LOG_WARNING, "Invalid subscript '%s' at line %d of %s\n", tok, lineno, script);
00812       return 0;
00813    }
00814    sub = getsubbyname(state, subscript, script, lineno);
00815    if (!sub) 
00816       return 0;
00817    buf[0] = 8;
00818    buf[1] = event;
00819    buf[2] = sub->id | 0x80;
00820    for (x=0;x<scnt;x++)
00821       buf[3 + x] = snums[x];
00822    return 3 + scnt;
00823 }

static int process_opcode ( struct adsi_subscript sub,
char *  code,
char *  args,
struct adsi_script state,
char *  script,
int  lineno 
) [static]

Definition at line 922 of file app_adsiprog.c.

References adsi_key_cmd::add_args, ast_log(), adsi_subscript::data, adsi_subscript::datalen, get_token(), adsi_subscript::id, adsi_subscript::inscount, LOG_WARNING, MAX_MAIN_LEN, MAX_SUB_LEN, name, opcmds, and adsi_subscript::vname.

Referenced by adsi_process().

00923 {
00924    int x;
00925    char *unused;
00926    int res;
00927    int max = sub->id ? MAX_SUB_LEN : MAX_MAIN_LEN;
00928    for (x=0;x<sizeof(opcmds) / sizeof(opcmds[0]);x++) {
00929       if ((opcmds[x].id > -1) && !strcasecmp(opcmds[x].name, code)) {
00930          if (opcmds[x].add_args) {
00931             res = opcmds[x].add_args(sub->data + sub->datalen,
00932                   code, opcmds[x].id, args, state, script, lineno);
00933             if ((sub->datalen + res + 1) <= max) 
00934                sub->datalen += res;
00935             else {
00936                ast_log(LOG_WARNING, "No space for '%s' code in subscript '%s' at line %d of %s\n", opcmds[x].name, sub->vname, lineno, script);
00937                return -1;
00938             }
00939          } else {
00940             if ((unused = get_token(&args, script, lineno))) 
00941                ast_log(LOG_WARNING, "'%s' takes no arguments at line %d of %s (token is '%s')\n", opcmds[x].name, lineno, script, unused);
00942             if ((sub->datalen + 2) <= max) {
00943                sub->data[sub->datalen] = opcmds[x].id;
00944                sub->datalen++;
00945             } else {
00946                ast_log(LOG_WARNING, "No space for '%s' code in key '%s' at line %d of %s\n", opcmds[x].name, sub->vname, lineno, script);
00947                return -1;
00948             }
00949          }
00950          /* Separate commands with 0xff */
00951          sub->data[sub->datalen] = 0xff;
00952          sub->datalen++;
00953          sub->inscount++;
00954          return 0;
00955       }
00956    }
00957    return -1;
00958 }

static int process_returncode ( struct adsi_soft_key key,
char *  code,
char *  args,
struct adsi_script state,
char *  script,
int  lineno 
) [static]

Definition at line 893 of file app_adsiprog.c.

References adsi_key_cmd::add_args, ast_log(), get_token(), kcmds, key(), LOG_WARNING, MAX_RET_CODE, and name.

Referenced by adsi_process().

00894 {
00895    int x;
00896    char *unused;
00897    int res;
00898    for (x=0;x<sizeof(kcmds) / sizeof(kcmds[0]);x++) {
00899       if ((kcmds[x].id > -1) && !strcasecmp(kcmds[x].name, code)) {
00900          if (kcmds[x].add_args) {
00901             res = kcmds[x].add_args(key->retstr + key->retstrlen,
00902                   code, kcmds[x].id, args, state, script, lineno);
00903             if ((key->retstrlen + res - key->initlen) <= MAX_RET_CODE) 
00904                key->retstrlen += res;
00905             else 
00906                ast_log(LOG_WARNING, "No space for '%s' code in key '%s' at line %d of %s\n", kcmds[x].name, key->vname, lineno, script);
00907          } else {
00908             if ((unused = get_token(&args, script, lineno))) 
00909                ast_log(LOG_WARNING, "'%s' takes no arguments at line %d of %s (token is '%s')\n", kcmds[x].name, lineno, script, unused);
00910             if ((key->retstrlen + 1 - key->initlen) <= MAX_RET_CODE) {
00911                key->retstr[key->retstrlen] = kcmds[x].id;
00912                key->retstrlen++;
00913             } else 
00914                ast_log(LOG_WARNING, "No space for '%s' code in key '%s' at line %d of %s\n", kcmds[x].name, key->vname, lineno, script);
00915          }
00916          return 0;
00917       }
00918    }
00919    return -1;
00920 }

static int process_token ( void *  out,
char *  src,
int  maxlen,
int  argtype 
) [static]

Definition at line 178 of file app_adsiprog.c.

References ARG_NUMBER, ARG_STRING, and ast_strlen_zero().

Referenced by adsi_process(), clearflag(), goto_line(), goto_line_rel(), onevent(), send_delay(), send_dtmf(), set_state(), setflag(), showdisplay(), showkeys(), starttimer(), and subscript().

00179 {
00180    if ((strlen(src) > 1) && src[0] == '\"') {
00181       /* This is a quoted string */
00182       if (!(argtype & ARG_STRING))
00183          return -1;
00184       src++;
00185       /* Don't take more than what's there */
00186       if (maxlen > strlen(src) - 1)
00187          maxlen = strlen(src) - 1;
00188       memcpy(out, src, maxlen);
00189       ((char *)out)[maxlen] = '\0';
00190    } else if (!ast_strlen_zero(src) && (src[0] == '\\')) {
00191       if (!(argtype & ARG_NUMBER))
00192          return -1;
00193       /* Octal value */
00194       if (sscanf(src, "%o", (int *)out) != 1)
00195          return -1;
00196       if (argtype & ARG_STRING) {
00197          /* Convert */
00198          *((unsigned int *)out) = htonl(*((unsigned int *)out));
00199       }
00200    } else if ((strlen(src) > 2) && (src[0] == '0') && (tolower(src[1]) == 'x')) {
00201       if (!(argtype & ARG_NUMBER))
00202          return -1;
00203       /* Hex value */
00204       if (sscanf(src + 2, "%x", (unsigned int *)out) != 1)
00205          return -1;
00206       if (argtype & ARG_STRING) {
00207          /* Convert */
00208          *((unsigned int *)out) = htonl(*((unsigned int *)out));
00209       }
00210    } else if ((!ast_strlen_zero(src) && isdigit(src[0]))) {
00211       if (!(argtype & ARG_NUMBER))
00212          return -1;
00213       /* Hex value */
00214       if (sscanf(src, "%d", (int *)out) != 1)
00215          return -1;
00216       if (argtype & ARG_STRING) {
00217          /* Convert */
00218          *((unsigned int *)out) = htonl(*((unsigned int *)out));
00219       }
00220    } else
00221       return -1;
00222    return 0;
00223 }

static int send_delay ( char *  buf,
char *  name,
int  id,
char *  args,
struct adsi_script state,
char *  script,
int  lineno 
) [static]

Definition at line 344 of file app_adsiprog.c.

References ARG_NUMBER, ast_log(), get_token(), LOG_WARNING, and process_token().

00345 {
00346    char *gtime;
00347    int ms;
00348    gtime = get_token(&args, script, lineno);
00349    if (!gtime) {
00350       ast_log(LOG_WARNING, "Expecting number of milliseconds to wait at line %d of %s\n", lineno, script);
00351       return 0;
00352    }
00353    if (process_token(&ms, gtime, sizeof(ms), ARG_NUMBER)) {
00354       ast_log(LOG_WARNING, "Invalid delay milliseconds '%s' at line %d of %s\n", gtime, lineno, script);
00355       return 0;
00356    }
00357    buf[0] = 0x90;
00358    if (id == 11)
00359       buf[1] = ms / 100;
00360    else
00361       buf[1] = ms / 10;
00362    return 2;
00363 }

static int send_dtmf ( char *  buf,
char *  name,
int  id,
char *  args,
struct adsi_script state,
char *  script,
int  lineno 
) [static]

Definition at line 257 of file app_adsiprog.c.

References ARG_STRING, ast_log(), get_token(), LOG_WARNING, and process_token().

00258 {
00259    char dtmfstr[80];
00260    char *a;
00261    int bytes=0;
00262    a = get_token(&args, script, lineno);
00263    if (!a) {
00264       ast_log(LOG_WARNING, "Expecting something to send for SENDDTMF at line %d of %s\n", lineno, script);
00265       return 0;
00266    }
00267    if (process_token(dtmfstr, a, sizeof(dtmfstr) - 1, ARG_STRING)) {
00268       ast_log(LOG_WARNING, "Invalid token for SENDDTMF at line %d of %s\n", lineno, script);
00269       return 0;
00270    }
00271    a = dtmfstr;
00272    while(*a) {
00273       if (strchr(validdtmf, *a)) {
00274          *buf = *a;
00275          buf++;
00276          bytes++;
00277       } else
00278          ast_log(LOG_WARNING, "'%c' is not a valid DTMF tone at line %d of %s\n", *a, lineno, script);
00279       a++;
00280    }
00281    return bytes;
00282 }

static int set_state ( char *  buf,
char *  name,
int  id,
char *  args,
struct adsi_script istate,
char *  script,
int  lineno 
) [static]

Definition at line 365 of file app_adsiprog.c.

References ARG_NUMBER, ast_log(), get_token(), LOG_WARNING, and process_token().

00366 {
00367    char *gstate;
00368    int state;
00369    gstate = get_token(&args, script, lineno);
00370    if (!gstate) {
00371       ast_log(LOG_WARNING, "Expecting state number at line %d of %s\n", lineno, script);
00372       return 0;
00373    }
00374    if (process_token(&state, gstate, sizeof(state), ARG_NUMBER)) {
00375       ast_log(LOG_WARNING, "Invalid state number '%s' at line %d of %s\n", gstate, lineno, script);
00376       return 0;
00377    }
00378    buf[0] = id;
00379    buf[1] = state;
00380    return 2;
00381 }

static int setflag ( char *  buf,
char *  name,
int  id,
char *  args,
struct adsi_script state,
char *  script,
int  lineno 
) [static]

Definition at line 418 of file app_adsiprog.c.

References ARG_STRING, ast_log(), get_token(), getflagbyname(), adsi_flag::id, LOG_WARNING, and process_token().

00419 {
00420    char *tok;
00421    char sname[80];
00422    struct adsi_flag *flag;
00423    tok = get_token(&args, script, lineno);
00424    if (!tok) {
00425       ast_log(LOG_WARNING, "Setting flag requires a flag number at line %d of %s\n", lineno, script);
00426       return 0;
00427    }
00428    if (process_token(sname, tok, sizeof(sname) - 1, ARG_STRING)) {
00429       ast_log(LOG_WARNING, "Invalid flag '%s' at line %d of %s\n", tok, lineno, script);
00430       return 0;
00431    }
00432    flag = getflagbyname(state, sname, script, lineno, 0);
00433    if (!flag) {
00434       ast_log(LOG_WARNING, "Flag '%s' is undeclared at line %d of %s\n", sname, lineno, script);
00435       return 0;
00436    }
00437    buf[0] = id;
00438    buf[1] = ((flag->id & 0x7) << 4) | 1;
00439    return 2;
00440 }

static int showdisplay ( char *  buf,
char *  name,
int  id,
char *  args,
struct adsi_script state,
char *  script,
int  lineno 
) [static]

Definition at line 628 of file app_adsiprog.c.

References ARG_NUMBER, ARG_STRING, ast_log(), get_token(), getdisplaybyname(), adsi_display::id, LOG_WARNING, and process_token().

00629 {
00630    char *tok;
00631    char dispname[80];
00632    int line=0;
00633    int flag=0;
00634    int cmd = 3;
00635    struct adsi_display *disp;
00636 
00637    /* Get display */
00638    tok = get_token(&args, script, lineno);
00639    if (!tok || process_token(dispname, tok, sizeof(dispname) - 1, ARG_STRING)) {
00640       ast_log(LOG_WARNING, "Invalid display name: %s at line %d of %s\n", tok ? tok : "<nothing>", lineno, script);
00641       return 0;
00642    }
00643    disp = getdisplaybyname(state, dispname, script, lineno, 0);
00644    if (!disp) {
00645       ast_log(LOG_WARNING, "Display '%s' is undefined at line %d of %s\n", dispname, lineno, script);
00646       return 0;
00647    }
00648 
00649    tok = get_token(&args, script, lineno);
00650    if (!tok || strcasecmp(tok, "AT")) {
00651       ast_log(LOG_WARNING, "Missing token 'AT' at line %d of %s\n", lineno, script);
00652       return 0;
00653    }
00654    /* Get line number */
00655    tok = get_token(&args, script, lineno);
00656    if (!tok || process_token(&line, tok, sizeof(line), ARG_NUMBER)) {
00657       ast_log(LOG_WARNING, "Invalid line: '%s' at line %d of %s\n", tok ? tok : "<nothing>", lineno, script);
00658       return 0;
00659    }
00660    tok = get_token(&args, script, lineno);
00661    if (tok && !strcasecmp(tok, "NOUPDATE")) {
00662       cmd = 1;
00663       tok = get_token(&args, script, lineno);
00664    }
00665    if (tok && !strcasecmp(tok, "UNLESS")) {
00666       /* Check for trailing UNLESS flag */
00667       tok = get_token(&args, script, lineno);
00668       if (!tok) {
00669          ast_log(LOG_WARNING, "Missing argument for UNLESS clause at line %d of %s\n", lineno, script);
00670       } else if (process_token(&flag, tok, sizeof(flag), ARG_NUMBER)) {
00671          ast_log(LOG_WARNING, "Invalid flag number '%s' at line %d of %s\n", tok, lineno, script);
00672       }
00673       if ((tok = get_token(&args, script, lineno)))
00674          ast_log(LOG_WARNING, "Extra arguments after UNLESS clause: '%s' at line %d of %s\n", tok, lineno, script);
00675    }
00676                
00677    buf[0] = id;
00678    buf[1] = (cmd << 6) | (disp->id & 0x3f); 
00679    buf[2] = ((line & 0x1f) << 3) | (flag & 0x7);
00680    return 3;
00681 }

static int showkeys ( char *  buf,
char *  name,
int  id,
char *  args,
struct adsi_script state,
char *  script,
int  lineno 
) [static]

Definition at line 575 of file app_adsiprog.c.

References ARG_STRING, ast_log(), get_token(), getflagbyname(), getkeybyname(), adsi_flag::id, key(), LOG_WARNING, and process_token().

00576 {
00577    char *tok;
00578    char newkey[80];
00579    int bytes;
00580    unsigned char keyid[6];
00581    int x;
00582    int flagid=0;
00583    struct adsi_soft_key *key;
00584    struct adsi_flag *flag;
00585 
00586    for (x=0;x<7;x++) {
00587       /* Up to 6 key arguments */
00588       tok = get_token(&args, script, lineno);
00589       if (!tok)
00590          break;
00591       if (!strcasecmp(tok, "UNLESS")) {
00592          /* Check for trailing UNLESS flag */
00593          tok = get_token(&args, script, lineno);
00594          if (!tok) {
00595             ast_log(LOG_WARNING, "Missing argument for UNLESS clause at line %d of %s\n", lineno, script);
00596          } else if (process_token(newkey, tok, sizeof(newkey) - 1, ARG_STRING)) {
00597             ast_log(LOG_WARNING, "Invalid flag name '%s' at line %d of %s\n", tok, lineno, script);
00598          } else if (!(flag = getflagbyname(state, newkey, script, lineno, 0))) {
00599             ast_log(LOG_WARNING, "Flag '%s' is undeclared at line %d of %s\n", newkey, lineno, script);
00600          } else
00601             flagid = flag->id;
00602          if ((tok = get_token(&args, script, lineno)))
00603             ast_log(LOG_WARNING, "Extra arguments after UNLESS clause: '%s' at line %d of %s\n", tok, lineno, script);
00604          break;
00605       }
00606       if (x > 5) {
00607          ast_log(LOG_WARNING, "Only 6 keys can be defined, ignoring '%s' at line %d of %s\n", tok, lineno, script);
00608          break;
00609       }
00610       if (process_token(newkey, tok, sizeof(newkey) - 1, ARG_STRING)) {
00611          ast_log(LOG_WARNING, "Invalid token for key name: %s\n", tok); 
00612          continue;
00613       }
00614                
00615       key = getkeybyname(state, newkey, script, lineno);
00616       if (!key)
00617          break;
00618       keyid[x] = key->id;
00619    }
00620    buf[0] = id;
00621    buf[1] = (flagid & 0x7) << 3 | (x & 0x7);
00622    for (bytes=0;bytes<x;bytes++) {
00623       buf[bytes + 2] = keyid[bytes];
00624    }
00625    return 2 + x;
00626 }

static int starttimer ( char *  buf,
char *  name,
int  id,
char *  args,
struct adsi_script istate,
char *  script,
int  lineno 
) [static]

Definition at line 466 of file app_adsiprog.c.

References ARG_NUMBER, ast_log(), get_token(), LOG_WARNING, and process_token().

00467 {
00468    char *tok;
00469    int secs;
00470    tok = get_token(&args, script, lineno);
00471    if (!tok) {
00472       ast_log(LOG_WARNING, "Missing number of seconds at line %d of %s\n", lineno, script);
00473       return 0;
00474    }
00475    if (process_token(&secs, tok, sizeof(secs), ARG_NUMBER)) {
00476       ast_log(LOG_WARNING, "Invalid number of seconds '%s' at line %d of %s\n", tok, lineno, script);
00477       return 0;
00478    }
00479    buf[0] = id;
00480    buf[1] = 0x1;
00481    buf[2] = secs;
00482    return 3;
00483 }

static int subscript ( char *  buf,
char *  name,
int  id,
char *  args,
struct adsi_script state,
char *  script,
int  lineno 
) [static]

Definition at line 731 of file app_adsiprog.c.

References ARG_STRING, ast_log(), get_token(), getsubbyname(), adsi_subscript::id, LOG_WARNING, and process_token().

Referenced by onevent().

00732 {
00733    char *tok;
00734    char subscript[80];
00735    struct adsi_subscript *sub;
00736    tok = get_token(&args, script, lineno);
00737    if (!tok) {
00738       ast_log(LOG_WARNING, "Missing subscript to call at line %d of %s\n", lineno, script);
00739       return 0;
00740    }
00741    if (process_token(subscript, tok, sizeof(subscript) - 1, ARG_STRING)) {
00742       ast_log(LOG_WARNING, "Invalid number of seconds '%s' at line %d of %s\n", tok, lineno, script);
00743       return 0;
00744    }
00745    sub = getsubbyname(state, subscript, script, lineno);
00746    if (!sub) 
00747       return 0;
00748    buf[0] = 0x9d;
00749    buf[1] = sub->id;
00750    return 2;
00751 }

static int unload_module ( void   )  [static]

Definition at line 1569 of file app_adsiprog.c.

References app, ast_module_user_hangup_all, and ast_unregister_application().

01570 {
01571    int res;
01572 
01573    ast_module_user_hangup_all();
01574 
01575    res = ast_unregister_application(app); 
01576    
01577 
01578    return res;
01579 }


Variable Documentation

char* app = "ADSIProg" [static]

Definition at line 52 of file app_adsiprog.c.

char* descrip [static]

Initial value:

"  ADSIProg(script): This application programs an ADSI Phone with the given\n"
"script. If nothing is specified, the default script (asterisk.adsi) is used.\n"

Definition at line 58 of file app_adsiprog.c.

struct adsi_event events[] [static]

Definition at line 67 of file app_adsiprog.c.

struct adsi_event justify[] [static]

Definition at line 94 of file app_adsiprog.c.

Referenced by adsi_announce_park(), cpeid_setstatus(), and getjustifybyname().

struct adsi_key_cmd kcmds[] [static]

Definition at line 831 of file app_adsiprog.c.

Referenced by process_returncode().

struct adsi_key_cmd opcmds[] [static]

Definition at line 873 of file app_adsiprog.c.

Referenced by process_opcode().

char* synopsis = "Load Asterisk ADSI Scripts into phone" [static]

Definition at line 54 of file app_adsiprog.c.

char* validdtmf = "123456789*0#ABCD" [static]

Definition at line 255 of file app_adsiprog.c.


Generated on Mon May 14 04:43:20 2007 for Asterisk - the Open Source PBX by  doxygen 1.5.1