Tue Aug 20 16:34:41 2013

Asterisk developer's documentation


app_adsiprog.c File Reference

Program Asterisk ADSI Scripts into phone. More...

#include "asterisk.h"
#include <netinet/in.h>
#include <ctype.h>
#include "asterisk/paths.h"
#include "asterisk/file.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/adsi.h"
#include "asterisk/utils.h"
#include "asterisk/lock.h"

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, const char *data)
static int adsi_process (struct adsi_script *state, char *buf, const char *script, int lineno)
static int adsi_prog (struct ast_channel *chan, const char *script)
 AST_MODULE_INFO (ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT,"Asterisk ADSI Programming Application",.load=load_module,.unload=unload_module,.nonoptreq="res_adsi",)
static int clearcbone (char *buf, char *name, int id, char *args, struct adsi_script *istate, const char *script, int lineno)
static int cleardisplay (char *buf, char *name, int id, char *args, struct adsi_script *istate, const char *script, int lineno)
static int clearflag (char *buf, char *name, int id, char *args, struct adsi_script *state, const char *script, int lineno)
static int cleartimer (char *buf, char *name, int id, char *args, struct adsi_script *istate, const char *script, int lineno)
static struct adsi_scriptcompile_script (const char *script)
static int digitcollect (char *buf, char *name, int id, char *args, struct adsi_script *istate, const char *script, int lineno)
static int digitdirect (char *buf, char *name, int id, char *args, struct adsi_script *istate, const char *script, int lineno)
static char * get_token (char **buf, const char *script, int lineno)
static struct adsi_displaygetdisplaybyname (struct adsi_script *state, char *name, const char *script, int lineno, int create)
static int geteventbyname (char *name)
static struct adsi_flaggetflagbyname (struct adsi_script *state, char *name, const char *script, int lineno, int create)
static int getjustifybyname (char *name)
static struct adsi_soft_keygetkeybyname (struct adsi_script *state, char *name, const char *script, int lineno)
static struct adsi_stategetstatebyname (struct adsi_script *state, char *name, const char *script, int lineno, int create)
static struct adsi_subscriptgetsubbyname (struct adsi_script *state, char *name, const char *script, int lineno)
static int goto_line (char *buf, char *name, int id, char *args, struct adsi_script *state, const char *script, int lineno)
static int goto_line_rel (char *buf, char *name, int id, char *args, struct adsi_script *state, const char *script, int lineno)
static int load_module (void)
static int onevent (char *buf, char *name, int id, char *args, struct adsi_script *state, const char *script, int lineno)
static int process_opcode (struct adsi_subscript *sub, char *code, char *args, struct adsi_script *state, const char *script, int lineno)
static int process_returncode (struct adsi_soft_key *key, char *code, char *args, struct adsi_script *state, const 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, const char *script, int lineno)
static int send_dtmf (char *buf, char *name, int id, char *args, struct adsi_script *state, const char *script, int lineno)
static int set_state (char *buf, char *name, int id, char *args, struct adsi_script *istate, const char *script, int lineno)
static int setflag (char *buf, char *name, int id, char *args, struct adsi_script *state, const char *script, int lineno)
static int showdisplay (char *buf, char *name, int id, char *args, struct adsi_script *state, const char *script, int lineno)
static int showkeys (char *buf, char *name, int id, char *args, struct adsi_script *state, const char *script, int lineno)
static int starttimer (char *buf, char *name, int id, char *args, struct adsi_script *istate, const char *script, int lineno)
static int subscript (char *buf, char *name, int id, char *args, struct adsi_script *state, const char *script, int lineno)
static int unload_module (void)

Variables

static const char app [] = "ADSIProg"
static struct adsi_event events []
static struct adsi_event justify []
static struct adsi_key_cmd kcmds []
static struct adsi_key_cmd opcmds []
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)
#define ARG_STRING   (1 << 0)
#define MAX_MAIN_LEN   1600

Definition at line 119 of file app_adsiprog.c.

Referenced by process_opcode().

#define MAX_RET_CODE   20

Definition at line 117 of file app_adsiprog.c.

Referenced by process_returncode().

#define MAX_SUB_LEN   255

Definition at line 118 of file app_adsiprog.c.

Referenced by process_opcode().

#define STATE_INIF   3

Definition at line 115 of file app_adsiprog.c.

Referenced by adsi_process().

#define STATE_INKEY   1

Definition at line 113 of file app_adsiprog.c.

Referenced by adsi_process(), and compile_script().

#define STATE_INSUB   2

Definition at line 114 of file app_adsiprog.c.

Referenced by adsi_process(), and compile_script().

#define STATE_NORMAL   0

Definition at line 112 of file app_adsiprog.c.

Referenced by adsi_process(), and compile_script().


Function Documentation

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

Definition at line 1566 of file app_adsiprog.c.

References adsi_prog(), ast_adsi_available(), ast_strlen_zero(), and ast_verb.

Referenced by load_module().

01567 {
01568    int res = 0;
01569    
01570    if (ast_strlen_zero(data))
01571       data = "asterisk.adsi";
01572 
01573    if (!ast_adsi_available(chan)) {
01574       ast_verb(3, "ADSI Unavailable on CPE.  Not bothering to try.\n");
01575    } else {
01576       ast_verb(3, "ADSI Available on CPE.  Attempting Upload.\n");
01577       res = adsi_prog(chan, data);
01578    }
01579 
01580    return res;
01581 }

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

Definition at line 1014 of file app_adsiprog.c.

References ARG_NUMBER, ARG_STRING, args, ast_copy_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, 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().

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

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

Definition at line 1455 of file app_adsiprog.c.

References ADSI_INFO_PAGE, ADSI_JUST_LEFT, ADSI_MSG_DISPLAY, ADSI_MSG_DOWNLOAD, ast_adsi_begin_download(), ast_adsi_display(), ast_adsi_end_download(), ast_adsi_load_session(), ast_adsi_set_line(), ast_adsi_transmit_message(), ast_adsi_unload_session(), ast_free, ast_log(), ast_verb, compile_script(), adsi_subscript::data, adsi_display::data, adsi_subscript::datalen, adsi_display::datalen, adsi_script::desc, adsi_script::displays, adsi_script::fdn, adsi_script::keys, LOG_NOTICE, LOG_WARNING, adsi_script::numdisplays, adsi_script::numkeys, adsi_script::numsubs, adsi_soft_key::retstr, adsi_soft_key::retstrlen, adsi_script::sec, adsi_script::subs, adsi_script::ver, adsi_subscript::vname, adsi_display::vname, and adsi_soft_key::vname.

Referenced by adsi_exec().

01456 {
01457    struct adsi_script *scr;
01458    int x, bytes;
01459    unsigned char buf[1024];
01460 
01461    if (!(scr = compile_script(script)))
01462       return -1;
01463 
01464    /* Start an empty ADSI Session */
01465    if (ast_adsi_load_session(chan, NULL, 0, 1) < 1)
01466       return -1;
01467 
01468    /* Now begin the download attempt */
01469    if (ast_adsi_begin_download(chan, scr->desc, scr->fdn, scr->sec, scr->ver)) {
01470       /* User rejected us for some reason */
01471       ast_verb(3, "User rejected download attempt\n");
01472       ast_log(LOG_NOTICE, "User rejected download on channel %s\n", chan->name);
01473       ast_free(scr);
01474       return -1;
01475    }
01476 
01477    bytes = 0;
01478    /* Start with key definitions */
01479    for (x = 0; x < scr->numkeys; x++) {
01480       if (bytes + scr->keys[x].retstrlen > 253) {
01481          /* Send what we've collected so far */
01482          if (ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD)) {
01483             ast_log(LOG_WARNING, "Unable to send chunk ending at %d\n", x);
01484             return -1;
01485          }
01486          bytes =0;
01487       }
01488       memcpy(buf + bytes, scr->keys[x].retstr, scr->keys[x].retstrlen);
01489       bytes += scr->keys[x].retstrlen;
01490 #ifdef DUMP_MESSAGES
01491       dump_message("Key", scr->keys[x].vname, scr->keys[x].retstr, scr->keys[x].retstrlen);
01492 #endif
01493    }
01494    if (bytes) {
01495       if (ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD)) {
01496          ast_log(LOG_WARNING, "Unable to send chunk ending at %d\n", x);
01497          return -1;
01498       }
01499    }
01500 
01501    bytes = 0;
01502    /* Continue with the display messages */
01503    for (x = 0; x < scr->numdisplays; x++) {
01504       if (bytes + scr->displays[x].datalen > 253) {
01505          /* Send what we've collected so far */
01506          if (ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD)) {
01507             ast_log(LOG_WARNING, "Unable to send chunk ending at %d\n", x);
01508             return -1;
01509          }
01510          bytes =0;
01511       }
01512       memcpy(buf + bytes, scr->displays[x].data, scr->displays[x].datalen);
01513       bytes += scr->displays[x].datalen;
01514 #ifdef DUMP_MESSAGES
01515       dump_message("Display", scr->displays[x].vname, scr->displays[x].data, scr->displays[x].datalen);
01516 #endif
01517    }
01518    if (bytes) {
01519       if (ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD)) {
01520          ast_log(LOG_WARNING, "Unable to send chunk ending at %d\n", x);
01521          return -1;
01522       }
01523    }
01524 
01525    bytes = 0;
01526    /* Send subroutines */
01527    for (x = 0; x < scr->numsubs; x++) {
01528       if (bytes + scr->subs[x].datalen > 253) {
01529          /* Send what we've collected so far */
01530          if (ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD)) {
01531             ast_log(LOG_WARNING, "Unable to send chunk ending at %d\n", x);
01532             return -1;
01533          }
01534          bytes =0;
01535       }
01536       memcpy(buf + bytes, scr->subs[x].data, scr->subs[x].datalen);
01537       bytes += scr->subs[x].datalen;
01538 #ifdef DUMP_MESSAGES
01539       dump_message("Sub", scr->subs[x].vname, scr->subs[x].data, scr->subs[x].datalen);
01540 #endif
01541    }
01542    if (bytes) {
01543       if (ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD)) {
01544          ast_log(LOG_WARNING, "Unable to send chunk ending at %d\n", x);
01545          return -1;
01546       }
01547    }
01548 
01549    bytes = 0;
01550    bytes += ast_adsi_display(buf, ADSI_INFO_PAGE, 1, ADSI_JUST_LEFT, 0, "Download complete.", "");
01551    bytes += ast_adsi_set_line(buf, ADSI_INFO_PAGE, 1);
01552    if (ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY) < 0)
01553       return -1;
01554    if (ast_adsi_end_download(chan)) {
01555       /* Download failed for some reason */
01556       ast_verb(3, "Download attempt failed\n");
01557       ast_log(LOG_NOTICE, "Download failed on %s\n", chan->name);
01558       ast_free(scr);
01559       return -1;
01560    }
01561    ast_free(scr);
01562    ast_adsi_unload_session(chan);
01563    return 0;
01564 }

AST_MODULE_INFO ( ASTERISK_GPL_KEY  ,
AST_MODFLAG_DEFAULT  ,
"Asterisk ADSI Programming Application"  ,
load = load_module,
unload = unload_module,
nonoptreq = "res_adsi" 
)
static int clearcbone ( char *  buf,
char *  name,
int  id,
char *  args,
struct adsi_script istate,
const char *  script,
int  lineno 
) [static]

Definition at line 767 of file app_adsiprog.c.

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

00768 {
00769    char *tok = get_token(&args, script, lineno);
00770 
00771    if (tok)
00772       ast_log(LOG_WARNING, "CLEARCB1 requires no arguments ('%s') at line %d of %s\n", tok, lineno, script);
00773 
00774    buf[0] = id;
00775    buf[1] = 0;
00776    return 2;
00777 }

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

Definition at line 743 of file app_adsiprog.c.

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

00744 {
00745    char *tok = get_token(&args, script, lineno);
00746 
00747    if (tok)
00748       ast_log(LOG_WARNING, "Clearing display requires no arguments ('%s') at line %d of %s\n", tok, lineno, script);
00749 
00750    buf[0] = id;
00751    buf[1] = 0x00;
00752    return 2;
00753 }

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

Definition at line 480 of file app_adsiprog.c.

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

00481 {
00482    char *tok = get_token(&args, script, lineno);
00483    struct adsi_flag *flag;
00484    char sname[80];
00485 
00486    if (!tok) {
00487       ast_log(LOG_WARNING, "Clearing flag requires a flag number at line %d of %s\n", lineno, script);
00488       return 0;
00489    }
00490 
00491    if (process_token(sname, tok, sizeof(sname) - 1, ARG_STRING)) {
00492       ast_log(LOG_WARNING, "Invalid flag '%s' at line %d of %s\n", tok, lineno, script);
00493       return 0;
00494    }
00495 
00496    if (!(flag = getflagbyname(state, sname, script, lineno, 0))) {
00497       ast_log(LOG_WARNING, "Flag '%s' is undeclared at line %d of %s\n", sname, lineno, script);
00498       return 0;
00499    }
00500 
00501    buf[0] = id;
00502    buf[1] = ((flag->id & 0x7) << 4);
00503 
00504    return 2;
00505 }

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

Definition at line 410 of file app_adsiprog.c.

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

00411 {
00412    char *tok = get_token(&args, script, lineno);
00413 
00414    if (tok)
00415       ast_log(LOG_WARNING, "Clearing timer requires no arguments ('%s') at line %d of %s\n", tok, lineno, script);
00416 
00417    buf[0] = id;
00418 
00419    /* For some reason the clear code is different slightly */
00420    if (id == 7)
00421       buf[1] = 0x10;
00422    else
00423       buf[1] = 0x00;
00424 
00425    return 2;
00426 }

static struct adsi_script* compile_script ( const char *  script  )  [static, read]

Definition at line 1362 of file app_adsiprog.c.

References adsi_process(), ast_calloc, ast_config_AST_CONFIG_DIR, ast_copy_string(), ast_free, ast_log(), ast_strlen_zero(), adsi_subscript::data, adsi_subscript::defined, adsi_soft_key::defined, f, getsubbyname(), adsi_script::keys, LOG_WARNING, adsi_script::numkeys, adsi_script::numsubs, adsi_script::state, STATE_INKEY, STATE_INSUB, STATE_NORMAL, adsi_script::subs, adsi_subscript::vname, and adsi_soft_key::vname.

Referenced by adsi_prog().

01363 {
01364    FILE *f;
01365    char fn[256], buf[256], *c;
01366    int lineno = 0, x, err;
01367    struct adsi_script *scr;
01368 
01369    if (script[0] == '/')
01370       ast_copy_string(fn, script, sizeof(fn));
01371    else
01372       snprintf(fn, sizeof(fn), "%s/%s", ast_config_AST_CONFIG_DIR, script);
01373 
01374    if (!(f = fopen(fn, "r"))) {
01375       ast_log(LOG_WARNING, "Can't open file '%s'\n", fn);
01376       return NULL;
01377    }
01378 
01379    if (!(scr = ast_calloc(1, sizeof(*scr)))) {
01380       fclose(f);
01381       return NULL;
01382    }
01383 
01384    /* Create "main" as first subroutine */
01385    getsubbyname(scr, "main", NULL, 0);
01386    while (!feof(f)) {
01387       if (!fgets(buf, sizeof(buf), f)) {
01388          continue;
01389       }
01390       if (!feof(f)) {
01391          lineno++;
01392          /* Trim off trailing return */
01393          buf[strlen(buf) - 1] = '\0';
01394          /* Strip comments */
01395          if ((c = strchr(buf, ';')))
01396             *c = '\0';
01397          if (!ast_strlen_zero(buf))
01398             adsi_process(scr, buf, script, lineno);
01399       }
01400    }
01401    fclose(f);
01402    /* Make sure we're in the main routine again */
01403    switch(scr->state) {
01404    case STATE_NORMAL:
01405       break;
01406    case STATE_INSUB:
01407       ast_log(LOG_WARNING, "Missing ENDSUB at end of file %s\n", script);
01408       ast_free(scr);
01409       return NULL;
01410    case STATE_INKEY:
01411       ast_log(LOG_WARNING, "Missing ENDKEY at end of file %s\n", script);
01412       ast_free(scr);
01413       return NULL;
01414    }
01415    err = 0;
01416 
01417    /* Resolve all keys and record their lengths */
01418    for (x = 0; x < scr->numkeys; x++) {
01419       if (!scr->keys[x].defined) {
01420          ast_log(LOG_WARNING, "Key '%s' referenced but never defined in file %s\n", scr->keys[x].vname, fn);
01421          err++;
01422       }
01423    }
01424 
01425    /* Resolve all subs */
01426    for (x = 0; x < scr->numsubs; x++) {
01427       if (!scr->subs[x].defined) {
01428          ast_log(LOG_WARNING, "Subscript '%s' referenced but never defined in file %s\n", scr->subs[x].vname, fn);
01429          err++;
01430       }
01431       if (x == (scr->numsubs - 1)) {
01432          /* Clear out extension bit on last message */
01433          scr->subs[x].data[2] = 0x80;
01434       }
01435    }
01436 
01437    if (err) {
01438       ast_free(scr);
01439       return NULL;
01440    }
01441    return scr;
01442 }

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

Definition at line 779 of file app_adsiprog.c.

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

00780 {
00781    char *tok = get_token(&args, script, lineno);
00782 
00783    if (tok)
00784       ast_log(LOG_WARNING, "Digitcollect requires no arguments ('%s') at line %d of %s\n", tok, lineno, script);
00785 
00786    buf[0] = id;
00787    buf[1] = 0xf;
00788    return 2;
00789 }

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

Definition at line 755 of file app_adsiprog.c.

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

00756 {
00757    char *tok = get_token(&args, script, lineno);
00758 
00759    if (tok)
00760       ast_log(LOG_WARNING, "Digitdirect requires no arguments ('%s') at line %d of %s\n", tok, lineno, script);
00761 
00762    buf[0] = id;
00763    buf[1] = 0x7;
00764    return 2;
00765 }

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

Definition at line 236 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().

00237 {
00238    char *tmp = *buf, *keyword;
00239    int quoted = 0;
00240 
00241    /* Advance past any white space */
00242    while(*tmp && (*tmp < 33))
00243       tmp++;
00244    if (!*tmp)
00245       return NULL;
00246    keyword = tmp;
00247    while(*tmp && ((*tmp > 32)  || quoted)) {
00248       if (*tmp == '\"') {
00249          quoted = !quoted;
00250       }
00251       tmp++;
00252    }
00253    if (quoted) {
00254       ast_log(LOG_WARNING, "Mismatched quotes at line %d of %s\n", lineno, script);
00255       return NULL;
00256    }
00257    *tmp = '\0';
00258    tmp++;
00259    while(*tmp && (*tmp < 33))
00260       tmp++;
00261    /* Note where we left off */
00262    *buf = tmp;
00263    return keyword;
00264 }

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

Definition at line 620 of file app_adsiprog.c.

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

Referenced by adsi_process(), and showdisplay().

00621 {
00622    int x;
00623 
00624    for (x = 0; x < state->numdisplays; x++) {
00625       if (!strcasecmp(state->displays[x].vname, name))
00626          return &state->displays[x];
00627    }
00628 
00629    /* Return now if we're not allowed to create */
00630    if (!create)
00631       return NULL;
00632 
00633    if (state->numdisplays > 61) {
00634       ast_log(LOG_WARNING, "No more display space at line %d of %s\n", lineno, script);
00635       return NULL;
00636    }
00637 
00638    ast_copy_string(state->displays[state->numdisplays].vname, name, sizeof(state->displays[state->numdisplays].vname));
00639    state->displays[state->numdisplays].id = state->numdisplays + 1;
00640    state->numdisplays++;
00641 
00642    return &state->displays[state->numdisplays-1];
00643 }

static int geteventbyname ( char *  name  )  [static]

Definition at line 529 of file app_adsiprog.c.

References ARRAY_LEN.

Referenced by adsi_process(), and onevent().

00530 {
00531    int x;
00532 
00533    for (x = 0; x < ARRAY_LEN(events); x++) {
00534       if (!strcasecmp(events[x].name, name))
00535          return events[x].id;
00536    }
00537 
00538    return 0;
00539 }

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

Definition at line 428 of file app_adsiprog.c.

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

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

00429 {
00430    int x;
00431 
00432    for (x = 0; x < state->numflags; x++) {
00433       if (!strcasecmp(state->flags[x].vname, name))
00434          return &state->flags[x];
00435    }
00436 
00437    /* Return now if we're not allowed to create */
00438    if (!create)
00439       return NULL;
00440 
00441    if (state->numflags > 6) {
00442       ast_log(LOG_WARNING, "No more flag space at line %d of %s\n", lineno, script);
00443       return NULL;
00444    }
00445 
00446    ast_copy_string(state->flags[state->numflags].vname, name, sizeof(state->flags[state->numflags].vname));
00447    state->flags[state->numflags].id = state->numflags + 1;
00448    state->numflags++;
00449 
00450    return &state->flags[state->numflags-1];
00451 }

static int getjustifybyname ( char *  name  )  [static]

Definition at line 541 of file app_adsiprog.c.

References ARRAY_LEN.

Referenced by adsi_process().

00542 {
00543    int x;
00544 
00545    for (x = 0; x < ARRAY_LEN(justify); x++) {
00546       if (!strcasecmp(justify[x].name, name))
00547          return justify[x].id;
00548    }
00549 
00550    return -1;
00551 }

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

Definition at line 553 of file app_adsiprog.c.

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

Referenced by adsi_process(), and showkeys().

00554 {
00555    int x;
00556 
00557    for (x = 0; x < state->numkeys; x++) {
00558       if (!strcasecmp(state->keys[x].vname, name))
00559          return &state->keys[x];
00560    }
00561 
00562    if (state->numkeys > 61) {
00563       ast_log(LOG_WARNING, "No more key space at line %d of %s\n", lineno, script);
00564       return NULL;
00565    }
00566 
00567    ast_copy_string(state->keys[state->numkeys].vname, name, sizeof(state->keys[state->numkeys].vname));
00568    state->keys[state->numkeys].id = state->numkeys + 2;
00569    state->numkeys++;
00570 
00571    return &state->keys[state->numkeys-1];
00572 }

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

Definition at line 595 of file app_adsiprog.c.

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

Referenced by adsi_process(), and onevent().

00596 {
00597    int x;
00598 
00599    for (x = 0; x <state->numstates; x++) {
00600       if (!strcasecmp(state->states[x].vname, name))
00601          return &state->states[x];
00602    }
00603 
00604    /* Return now if we're not allowed to create */
00605    if (!create)
00606       return NULL;
00607 
00608    if (state->numstates > 253) {
00609       ast_log(LOG_WARNING, "No more state space at line %d of %s\n", lineno, script);
00610       return NULL;
00611    }
00612 
00613    ast_copy_string(state->states[state->numstates].vname, name, sizeof(state->states[state->numstates].vname));
00614    state->states[state->numstates].id = state->numstates + 1;
00615    state->numstates++;
00616 
00617    return &state->states[state->numstates-1];
00618 }

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

Definition at line 574 of file app_adsiprog.c.

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

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

00575 {
00576    int x;
00577 
00578    for (x = 0; x < state->numsubs; x++) {
00579       if (!strcasecmp(state->subs[x].vname, name))
00580          return &state->subs[x];
00581    }
00582 
00583    if (state->numsubs > 127) {
00584       ast_log(LOG_WARNING, "No more subscript space at line %d of %s\n", lineno, script);
00585       return NULL;
00586    }
00587 
00588    ast_copy_string(state->subs[state->numsubs].vname, name, sizeof(state->subs[state->numsubs].vname));
00589    state->subs[state->numsubs].id = state->numsubs;
00590    state->numsubs++;
00591 
00592    return &state->subs[state->numsubs-1];
00593 }

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

Definition at line 298 of file app_adsiprog.c.

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

00299 {
00300    char *page = get_token(&args, script, lineno);
00301    char *gline = get_token(&args, script, lineno);
00302    int line;
00303    unsigned char cmd;
00304 
00305    if (!page || !gline) {
00306       ast_log(LOG_WARNING, "Expecting page and line number for GOTOLINE at line %d of %s\n", lineno, script);
00307       return 0;
00308    }
00309 
00310    if (!strcasecmp(page, "INFO"))
00311       cmd = 0;
00312    else if (!strcasecmp(page, "COMM"))
00313       cmd = 0x80;
00314    else {
00315       ast_log(LOG_WARNING, "Expecting either 'INFO' or 'COMM' page, got got '%s' at line %d of %s\n", page, lineno, script);
00316       return 0;
00317    }
00318 
00319    if (process_token(&line, gline, sizeof(line), ARG_NUMBER)) {
00320       ast_log(LOG_WARNING, "Invalid line number '%s' at line %d of %s\n", gline, lineno, script);
00321       return 0;
00322    }
00323 
00324    cmd |= line;
00325    buf[0] = 0x8b;
00326    buf[1] = cmd;
00327 
00328    return 2;
00329 }

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

Definition at line 331 of file app_adsiprog.c.

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

00332 {
00333    char *dir = get_token(&args, script, lineno);
00334    char *gline = get_token(&args, script, lineno);
00335    int line;
00336    unsigned char cmd;
00337 
00338    if (!dir || !gline) {
00339       ast_log(LOG_WARNING, "Expecting direction and number of lines for GOTOLINEREL at line %d of %s\n", lineno, script);
00340       return 0;
00341    }
00342 
00343    if (!strcasecmp(dir, "UP"))
00344       cmd = 0;
00345    else if (!strcasecmp(dir, "DOWN"))
00346       cmd = 0x20;
00347    else {
00348       ast_log(LOG_WARNING, "Expecting either 'UP' or 'DOWN' direction, got '%s' at line %d of %s\n", dir, lineno, script);
00349       return 0;
00350    }
00351 
00352    if (process_token(&line, gline, sizeof(line), ARG_NUMBER)) {
00353       ast_log(LOG_WARNING, "Invalid line number '%s' at line %d of %s\n", gline, lineno, script);
00354       return 0;
00355    }
00356 
00357    cmd |= line;
00358    buf[0] = 0x8c;
00359    buf[1] = cmd;
00360 
00361    return 2;
00362 }

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

Definition at line 816 of file app_adsiprog.c.

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

00817 {
00818    char *tok = get_token(&args, script, lineno);
00819    char subscr[80], sname[80];
00820    int sawin = 0, event, snums[8], scnt = 0, x;
00821    struct adsi_subscript *sub;
00822 
00823    if (!tok) {
00824       ast_log(LOG_WARNING, "Missing event for 'ONEVENT' at line %d of %s\n", lineno, script);
00825       return 0;
00826    }
00827 
00828    if ((event = geteventbyname(tok)) < 1) {
00829       ast_log(LOG_WARNING, "'%s' is not a valid event name, at line %d of %s\n", args, lineno, script);
00830       return 0;
00831    }
00832 
00833    tok = get_token(&args, script, lineno);
00834    while ((!sawin && !strcasecmp(tok, "IN")) || (sawin && !strcasecmp(tok, "OR"))) {
00835       sawin = 1;
00836       if (scnt > 7) {
00837          ast_log(LOG_WARNING, "No more than 8 states may be specified for inclusion at line %d of %s\n", lineno, script);
00838          return 0;
00839       }
00840       /* Process 'in' things */
00841       tok = get_token(&args, script, lineno);
00842       if (process_token(sname, tok, sizeof(sname), ARG_STRING)) {
00843          ast_log(LOG_WARNING, "'%s' is not a valid state name at line %d of %s\n", tok, lineno, script);
00844          return 0;
00845       }
00846       if ((snums[scnt] = getstatebyname(state, sname, script, lineno, 0) == NULL)) {
00847          ast_log(LOG_WARNING, "State '%s' not declared at line %d of %s\n", sname, lineno, script);
00848          return 0;
00849       }
00850       scnt++;
00851       if (!(tok = get_token(&args, script, lineno)))
00852          break;
00853    }
00854    if (!tok || strcasecmp(tok, "GOTO")) {
00855       if (!tok)
00856          tok = "<nothing>";
00857       if (sawin)
00858          ast_log(LOG_WARNING, "Got '%s' while looking for 'GOTO' or 'OR' at line %d of %s\n", tok, lineno, script);
00859       else
00860          ast_log(LOG_WARNING, "Got '%s' while looking for 'GOTO' or 'IN' at line %d of %s\n", tok, lineno, script);
00861    }
00862    if (!(tok = get_token(&args, script, lineno))) {
00863       ast_log(LOG_WARNING, "Missing subscript to call at line %d of %s\n", lineno, script);
00864       return 0;
00865    }
00866    if (process_token(subscr, tok, sizeof(subscr) - 1, ARG_STRING)) {
00867       ast_log(LOG_WARNING, "Invalid subscript '%s' at line %d of %s\n", tok, lineno, script);
00868       return 0;
00869    }
00870    if (!(sub = getsubbyname(state, subscr, script, lineno)))
00871       return 0;
00872    buf[0] = 8;
00873    buf[1] = event;
00874    buf[2] = sub->id | 0x80;
00875    for (x = 0; x < scnt; x++)
00876       buf[3 + x] = snums[x];
00877    return 3 + scnt;
00878 }

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

Definition at line 977 of file app_adsiprog.c.

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

Referenced by adsi_process().

00978 {
00979    int x, res, max = sub->id ? MAX_SUB_LEN : MAX_MAIN_LEN;
00980    char *unused;
00981 
00982    for (x = 0; x < ARRAY_LEN(opcmds); x++) {
00983       if ((opcmds[x].id > -1) && !strcasecmp(opcmds[x].name, code)) {
00984          if (opcmds[x].add_args) {
00985             res = opcmds[x].add_args(sub->data + sub->datalen,
00986                   code, opcmds[x].id, args, state, script, lineno);
00987             if ((sub->datalen + res + 1) <= max)
00988                sub->datalen += res;
00989             else {
00990                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);
00991                return -1;
00992             }
00993          } else {
00994             if ((unused = get_token(&args, script, lineno)))
00995                ast_log(LOG_WARNING, "'%s' takes no arguments at line %d of %s (token is '%s')\n", opcmds[x].name, lineno, script, unused);
00996             if ((sub->datalen + 2) <= max) {
00997                sub->data[sub->datalen] = opcmds[x].id;
00998                sub->datalen++;
00999             } else {
01000                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);
01001                return -1;
01002             }
01003          }
01004          /* Separate commands with 0xff */
01005          sub->data[sub->datalen] = 0xff;
01006          sub->datalen++;
01007          sub->inscount++;
01008          return 0;
01009       }
01010    }
01011    return -1;
01012 }

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

Definition at line 948 of file app_adsiprog.c.

References adsi_key_cmd::add_args, ARRAY_LEN, ast_log(), get_token(), adsi_key_cmd::id, adsi_soft_key::initlen, LOG_WARNING, MAX_RET_CODE, name, adsi_soft_key::retstr, adsi_soft_key::retstrlen, and adsi_soft_key::vname.

Referenced by adsi_process().

00949 {
00950    int x, res;
00951    char *unused;
00952 
00953    for (x = 0; x < ARRAY_LEN(kcmds); x++) {
00954       if ((kcmds[x].id > -1) && !strcasecmp(kcmds[x].name, code)) {
00955          if (kcmds[x].add_args) {
00956             res = kcmds[x].add_args(key->retstr + key->retstrlen,
00957                   code, kcmds[x].id, args, state, script, lineno);
00958             if ((key->retstrlen + res - key->initlen) <= MAX_RET_CODE)
00959                key->retstrlen += res;
00960             else
00961                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);
00962          } else {
00963             if ((unused = get_token(&args, script, lineno)))
00964                ast_log(LOG_WARNING, "'%s' takes no arguments at line %d of %s (token is '%s')\n", kcmds[x].name, lineno, script, unused);
00965             if ((key->retstrlen + 1 - key->initlen) <= MAX_RET_CODE) {
00966                key->retstr[key->retstrlen] = kcmds[x].id;
00967                key->retstrlen++;
00968             } else
00969                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);
00970          }
00971          return 0;
00972       }
00973    }
00974    return -1;
00975 }

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

Definition at line 189 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().

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

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

Definition at line 364 of file app_adsiprog.c.

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

00365 {
00366    char *gtime = get_token(&args, script, lineno);
00367    int ms;
00368 
00369    if (!gtime) {
00370       ast_log(LOG_WARNING, "Expecting number of milliseconds to wait at line %d of %s\n", lineno, script);
00371       return 0;
00372    }
00373 
00374    if (process_token(&ms, gtime, sizeof(ms), ARG_NUMBER)) {
00375       ast_log(LOG_WARNING, "Invalid delay milliseconds '%s' at line %d of %s\n", gtime, lineno, script);
00376       return 0;
00377    }
00378 
00379    buf[0] = 0x90;
00380 
00381    if (id == 11)
00382       buf[1] = ms / 100;
00383    else
00384       buf[1] = ms / 10;
00385 
00386    return 2;
00387 }

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

Definition at line 268 of file app_adsiprog.c.

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

00269 {
00270    char dtmfstr[80], *a;
00271    int bytes = 0;
00272 
00273    if (!(a = get_token(&args, script, lineno))) {
00274       ast_log(LOG_WARNING, "Expecting something to send for SENDDTMF at line %d of %s\n", lineno, script);
00275       return 0;
00276    }
00277 
00278    if (process_token(dtmfstr, a, sizeof(dtmfstr) - 1, ARG_STRING)) {
00279       ast_log(LOG_WARNING, "Invalid token for SENDDTMF at line %d of %s\n", lineno, script);
00280       return 0;
00281    }
00282 
00283    a = dtmfstr;
00284 
00285    while (*a) {
00286       if (strchr(validdtmf, *a)) {
00287          *buf = *a;
00288          buf++;
00289          bytes++;
00290       } else
00291          ast_log(LOG_WARNING, "'%c' is not a valid DTMF tone at line %d of %s\n", *a, lineno, script);
00292       a++;
00293    }
00294 
00295    return bytes;
00296 }

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

Definition at line 389 of file app_adsiprog.c.

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

00390 {
00391    char *gstate = get_token(&args, script, lineno);
00392    int state;
00393 
00394    if (!gstate) {
00395       ast_log(LOG_WARNING, "Expecting state number at line %d of %s\n", lineno, script);
00396       return 0;
00397    }
00398 
00399    if (process_token(&state, gstate, sizeof(state), ARG_NUMBER)) {
00400       ast_log(LOG_WARNING, "Invalid state number '%s' at line %d of %s\n", gstate, lineno, script);
00401       return 0;
00402    }
00403 
00404    buf[0] = id;
00405    buf[1] = state;
00406 
00407    return 2;
00408 }

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

Definition at line 453 of file app_adsiprog.c.

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

00454 {
00455    char *tok = get_token(&args, script, lineno);
00456    char sname[80];
00457    struct adsi_flag *flag;
00458 
00459    if (!tok) {
00460       ast_log(LOG_WARNING, "Setting flag requires a flag number at line %d of %s\n", lineno, script);
00461       return 0;
00462    }
00463 
00464    if (process_token(sname, tok, sizeof(sname) - 1, ARG_STRING)) {
00465       ast_log(LOG_WARNING, "Invalid flag '%s' at line %d of %s\n", tok, lineno, script);
00466       return 0;
00467    }
00468 
00469    if (!(flag = getflagbyname(state, sname, script, lineno, 0))) {
00470       ast_log(LOG_WARNING, "Flag '%s' is undeclared at line %d of %s\n", sname, lineno, script);
00471       return 0;
00472    }
00473 
00474    buf[0] = id;
00475    buf[1] = ((flag->id & 0x7) << 4) | 1;
00476 
00477    return 2;
00478 }

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

Definition at line 692 of file app_adsiprog.c.

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

00693 {
00694    char *tok, dispname[80];
00695    int line = 0, flag = 0, cmd = 3;
00696    struct adsi_display *disp;
00697 
00698    /* Get display */
00699    if (!(tok = get_token(&args, script, lineno)) || process_token(dispname, tok, sizeof(dispname) - 1, ARG_STRING)) {
00700       ast_log(LOG_WARNING, "Invalid display name: %s at line %d of %s\n", tok ? tok : "<nothing>", lineno, script);
00701       return 0;
00702    }
00703 
00704    if (!(disp = getdisplaybyname(state, dispname, script, lineno, 0))) {
00705       ast_log(LOG_WARNING, "Display '%s' is undefined at line %d of %s\n", dispname, lineno, script);
00706       return 0;
00707    }
00708 
00709    if (!(tok = get_token(&args, script, lineno)) || strcasecmp(tok, "AT")) {
00710       ast_log(LOG_WARNING, "Missing token 'AT' at line %d of %s\n", lineno, script);
00711       return 0;
00712    }
00713 
00714    /* Get line number */
00715    if (!(tok = get_token(&args, script, lineno)) || process_token(&line, tok, sizeof(line), ARG_NUMBER)) {
00716       ast_log(LOG_WARNING, "Invalid line: '%s' at line %d of %s\n", tok ? tok : "<nothing>", lineno, script);
00717       return 0;
00718    }
00719 
00720    if ((tok = get_token(&args, script, lineno)) && !strcasecmp(tok, "NOUPDATE")) {
00721       cmd = 1;
00722       tok = get_token(&args, script, lineno);
00723    }
00724 
00725    if (tok && !strcasecmp(tok, "UNLESS")) {
00726       /* Check for trailing UNLESS flag */
00727       if (!(tok = get_token(&args, script, lineno)))
00728          ast_log(LOG_WARNING, "Missing argument for UNLESS clause at line %d of %s\n", lineno, script);
00729       else if (process_token(&flag, tok, sizeof(flag), ARG_NUMBER))
00730          ast_log(LOG_WARNING, "Invalid flag number '%s' at line %d of %s\n", tok, lineno, script);
00731 
00732       if ((tok = get_token(&args, script, lineno)))
00733          ast_log(LOG_WARNING, "Extra arguments after UNLESS clause: '%s' at line %d of %s\n", tok, lineno, script);
00734    }
00735 
00736    buf[0] = id;
00737    buf[1] = (cmd << 6) | (disp->id & 0x3f);
00738    buf[2] = ((line & 0x1f) << 3) | (flag & 0x7);
00739 
00740    return 3;
00741 }

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

Definition at line 645 of file app_adsiprog.c.

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

00646 {
00647    char *tok, newkey[80];
00648    int bytes, x, flagid = 0;
00649    unsigned char keyid[6];
00650    struct adsi_soft_key *key;
00651    struct adsi_flag *flag;
00652 
00653    for (x = 0; x < 7; x++) {
00654       /* Up to 6 key arguments */
00655       if (!(tok = get_token(&args, script, lineno)))
00656          break;
00657       if (!strcasecmp(tok, "UNLESS")) {
00658          /* Check for trailing UNLESS flag */
00659          if (!(tok = get_token(&args, script, lineno)))
00660             ast_log(LOG_WARNING, "Missing argument for UNLESS clause at line %d of %s\n", lineno, script);
00661          else if (process_token(newkey, tok, sizeof(newkey) - 1, ARG_STRING))
00662             ast_log(LOG_WARNING, "Invalid flag name '%s' at line %d of %s\n", tok, lineno, script);
00663          else if (!(flag = getflagbyname(state, newkey, script, lineno, 0)))
00664             ast_log(LOG_WARNING, "Flag '%s' is undeclared at line %d of %s\n", newkey, lineno, script);
00665          else
00666             flagid = flag->id;
00667          if ((tok = get_token(&args, script, lineno)))
00668             ast_log(LOG_WARNING, "Extra arguments after UNLESS clause: '%s' at line %d of %s\n", tok, lineno, script);
00669          break;
00670       }
00671       if (x > 5) {
00672          ast_log(LOG_WARNING, "Only 6 keys can be defined, ignoring '%s' at line %d of %s\n", tok, lineno, script);
00673          break;
00674       }
00675       if (process_token(newkey, tok, sizeof(newkey) - 1, ARG_STRING)) {
00676          ast_log(LOG_WARNING, "Invalid token for key name: %s\n", tok);
00677          continue;
00678       }
00679 
00680       if (!(key = getkeybyname(state, newkey, script, lineno)))
00681          break;
00682       keyid[x] = key->id;
00683    }
00684    buf[0] = id;
00685    buf[1] = (flagid & 0x7) << 3 | (x & 0x7);
00686    for (bytes = 0; bytes < x; bytes++)
00687       buf[bytes + 2] = keyid[bytes];
00688 
00689    return 2 + x;
00690 }

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

Definition at line 507 of file app_adsiprog.c.

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

00508 {
00509    char *tok = get_token(&args, script, lineno);
00510    int secs;
00511 
00512    if (!tok) {
00513       ast_log(LOG_WARNING, "Missing number of seconds at line %d of %s\n", lineno, script);
00514       return 0;
00515    }
00516 
00517    if (process_token(&secs, tok, sizeof(secs), ARG_NUMBER)) {
00518       ast_log(LOG_WARNING, "Invalid number of seconds '%s' at line %d of %s\n", tok, lineno, script);
00519       return 0;
00520    }
00521 
00522    buf[0] = id;
00523    buf[1] = 0x1;
00524    buf[2] = secs;
00525 
00526    return 3;
00527 }

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

Definition at line 791 of file app_adsiprog.c.

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

00792 {
00793    char *tok = get_token(&args, script, lineno);
00794    char subscr[80];
00795    struct adsi_subscript *sub;
00796 
00797    if (!tok) {
00798       ast_log(LOG_WARNING, "Missing subscript to call at line %d of %s\n", lineno, script);
00799       return 0;
00800    }
00801 
00802    if (process_token(subscr, tok, sizeof(subscr) - 1, ARG_STRING)) {
00803       ast_log(LOG_WARNING, "Invalid number of seconds '%s' at line %d of %s\n", tok, lineno, script);
00804       return 0;
00805    }
00806 
00807    if (!(sub = getsubbyname(state, subscr, script, lineno)))
00808       return 0;
00809 
00810    buf[0] = 0x9d;
00811    buf[1] = sub->id;
00812 
00813    return 2;
00814 }

static int unload_module ( void   )  [static]

Definition at line 1583 of file app_adsiprog.c.

References ast_unregister_application().

01584 {
01585    return ast_unregister_application(app);
01586 }


Variable Documentation

const char app[] = "ADSIProg" [static]
struct adsi_event events[] [static]
struct adsi_event justify[] [static]

Definition at line 105 of file app_adsiprog.c.

Referenced by adsi_announce_park(), and cpeid_setstatus().

struct adsi_key_cmd kcmds[] [static]

Definition at line 886 of file app_adsiprog.c.

struct adsi_key_cmd opcmds[] [static]

Definition at line 928 of file app_adsiprog.c.

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

Definition at line 266 of file app_adsiprog.c.


Generated on 20 Aug 2013 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1