[asterisk-users] use dial plan passed arg value in C agi code

Steve Edwards asterisk.org at sedwards.com
Tue Nov 6 19:41:39 CST 2007


On Tue, 6 Nov 2007, Arpit Mehta wrote:

> Hi,
> 
> thanks for the replies although i am still confused.

The first one is always the hardest :)

> On Nov 2, 2007 5:24 PM, Steve Edwards <asterisk.org at sedwards.com> wrote:
> > 
> > The AGI variables are passed via stdin (similar to an HTTP GET request)
> > and can be observed using "agi debug" at the Asterisk prompt. It's a
> > fixed
------------------------------^^^^^^^^^

"agi debug" is your new best friend.

AGI Rx << --> agi_accountcode:
AGI Tx >> 510 Invalid or unknown command
AGI Rx << -->
AGI Tx >> 510 Invalid or unknown command
AGI Rx << am1000(null)SET VARIABLE AGIVAR 1000
AGI Tx >> 510 Invalid or unknown command

You are confusing Asterisk by printing to stdout. Don't do that. I use the 
AGI command VERBOSE or syslog() when I want to see what's going on in an 
AGI. When your AGI is totally hosed, syslog() is a better choice since it 
doesn't interfere with the Asterisk/AGI control path (stdin and stdout).

Also, you are setting AGIVAR in your AGI, but displaying MYAGIVAR in your 
dialplan.

I'm guessing you're fairly new to C. In the interest of speeding up your 
learning process, let's go over your AGI in detail. My comments to your 
code are preceded with "////."

#include <stdio.h>

#include	<stdlib.h>
//// defines a bunch of cool stuff. We need it for EXIT_SUCCESS
//// further down.

#include	<syslog.h>
//// this will come in handy further down.

int main(int argc, char *argv[])
{

  char        line[80];
//// while this is sufficient for this agi, the agi set variable
//// command can be much longer. I didn't take the time to read the
//// code, but setting a variable with a value of 1,000 bytes worked
//// fine.

  int i;

  /* use line buffering */
  setlinebuf(stdout);
  setlinebuf(stderr);

//  while (1) {
//    /*gives me all the agi env var*/
//    fgets(line,80,stdin);
// //  //prints the variables
//    printf("--> %s",line);
//    if (strlen(line) <= 1) break;
//  }

//// Aside from the printing that is confusing Asterisk, this would be
//// better as:

 	while	(0 != (int)fgets(line, sizeof(line), stdin))
//// fgets returns a value -- use it. Also, note the "sizeof()"
//// instead of the constant "80." You already told the compiler how
//// big line was. Using "80" again only invites bugs when something
//// changes. "sizeof()" is an operator, not a function so there is no
//// additional overhead. Also, your intent is more obvious. Using the
//// "sizeof()" makes it obvious that the entire line is available to
//// "fgets()." It would be valid (but obtuse) to limit "fgets()" to
//// some substring of line.
 		{
 		syslog(LOG_ERR, "%s", line);
//// since you don't have the AGI stuff working yet, let's use syslog.
 		if	('\n' == *line)
//// if the first byte of line is a newline, we are done
 			{
 			break;
 			}
 		}

//according to me the passed variable should be available here but i
//am not getting anything here
//nothing gets printed on the agi debug command
//  for(i=0 ;i<=argc ;i++)
 	for	(i = 0; i <= argc; i++)
//// whitespace is free, use it in the right places.
    {
//      printf("%s", argv[i]);
 	syslog(LOG_ERR, "%s", argv[i]);
//// since you don't have the AGI stuff working yet, let's use syslog.
    }

  /* Send asterisk a command */
//// don't mix commenting styles -- /**/ is so last century.
//	printf("SET VARIABLE AGIVAR %s",argv[1] );
 	printf("SET VARIABLE AGIVAR %s\n", argv[1]);
//// printf does not append a newline for you so you have to
//// explicitly add it.

  /* Read response from Asterisk and show on console */
//	fgets(line,80,stdin);
 	fgets(line, sizeof(line), stdin);
//// same as above.

//	fputs(line,stderr);
 	syslog(LOG_ERR, "%s", line);
//// same as above.

 	return(EXIT_SUCCESS);
//// every non-void function (main() included) should end with a
//// return statement. While Asterisk currently ignores the return
//// value, return something meaningful. Maybe someday Asterisk will
//// use it and your AGI's will still work.

}

Strip out most of my comments and your code that I commented out and you 
should have a better view of what's going on.

While this "printf/fgets" cycle works for getting a good understanding of 
how the Asterisk Gateway Interface works, most people write a library (or 
use someone else's) to hide the ugly details.

Also, it's a good idea for AGI's to trap SIGHUP and do something 
appropriate. This is how Asterisk will tell your AGI that the caller has 
hung up before your AGI is finished.

And, adding the compiler flags "-Wall -Wstrict-prototypes 
-Wno-unknown-pragmas" will help keep you honest.

Good luck in your journey :)
------------------------------------------------------------------------
Steve Edwards      sedwards at sedwards.com      Voice: +1-760-468-3867 PST
Newline                                             Fax: +1-760-731-3000



More information about the asterisk-users mailing list