Discussion:
[asterisk-users] carefulwrite: write() returned error: Broken pipe
Josip Djuricic
2009-10-22 14:30:58 UTC
Permalink
Dear,



I am getting this in CLI on release candidate version of Asterisk. Any
ideas, or points where to look?



-- Launched AGI Script /var/lib/asterisk/agi-bin/rad-auth.agi

[Oct 22 18:21:45] ERROR[9853]: utils.c:1126 ast_carefulwrite: write()
returned error: Broken pipe

-- <SIP/916-fc001968>AGI Script rad-auth.agi completed, returning 0



Best regards,



Josip
Danny Nicholas
2009-10-22 14:42:29 UTC
Permalink
In main/utils.c there is a line (1126) that reads like this -

ast_log(LOG_ERROR, "write() returned error: %s\n", strerror(errno));



change ERROR to NOTICE -

ast_log(LOG_NOTICE, "write() returned error: %s\n", strerror(errno));



and do make && make install. This will remove this message.



_____

From: asterisk-users-***@lists.digium.com
[mailto:asterisk-users-***@lists.digium.com] On Behalf Of Josip Djuricic
Sent: Thursday, October 22, 2009 9:31 AM
To: 'Asterisk Users Mailing List - Non-Commercial Discussion'
Subject: [asterisk-users] carefulwrite: write() returned error: Broken pipe
Importance: High



Dear,



I am getting this in CLI on release candidate version of Asterisk. Any
ideas, or points where to look?



-- Launched AGI Script /var/lib/asterisk/agi-bin/rad-auth.agi

[Oct 22 18:21:45] ERROR[9853]: utils.c:1126 ast_carefulwrite: write()
returned error: Broken pipe

-- <SIP/916-fc001968>AGI Script rad-auth.agi completed, returning 0



Best regards,



Josip
Tilghman Lesher
2009-10-22 14:57:55 UTC
Permalink
Post by Josip Djuricic
I am getting this in CLI on release candidate version of Asterisk. Any
ideas, or points where to look?
-- Launched AGI Script /var/lib/asterisk/agi-bin/rad-auth.agi
[Oct 22 18:21:45] ERROR[9853]: utils.c:1126 ast_carefulwrite: write()
returned error: Broken pipe
-- <SIP/916-fc001968>AGI Script rad-auth.agi completed, returning 0
Generally, that means that your AGI exited early, before the AGI controller
had a chance to output responses. You could ignore the error, or you could
fix your AGI script to ensure that it receives full responses before exiting.
--
Tilghman Lesher
Digium, Inc. | Senior Software Developer
twitter: Corydon76 | IRC: Corydon76-dig (Freenode)
Check us out at: www.digium.com & www.asterisk.org
Danny Nicholas
2009-10-22 16:09:00 UTC
Permalink
I have some simple PERL scripts that worked fine with 1.4 SVN, but returned
this error when I went to 1.4.26.2. It seemed easier to change the ERROR to
a NOTIFY than try to "Fix my bad code".

Here is the "failing" code
#!/usr/local/bin/perl
use strict;
use warnings;

sub setvar {
my ($var, $val) = @_;
print STDOUT "SET VARIABLE $var \"$val\" \r\n";
my $rv=<STDIN>;
return;
}

# turn off I/O buffering
$| = 1;

# get trunk information
$SIG{'PIPE'} = 'IGNORE';
my $images='TRUE';
my $checks='TRUE';
&setvar("TEST_RETURN", "OK");
&setvar("CHECKS", $checks);
&setvar("IMAGES", $images);
exit;

-----Original Message-----
From: asterisk-users-***@lists.digium.com
[mailto:asterisk-users-***@lists.digium.com] On Behalf Of Tilghman
Lesher
Sent: Thursday, October 22, 2009 9:58 AM
To: Asterisk Users Mailing List - Non-Commercial Discussion
Subject: Re: [asterisk-users] carefulwrite: write() returned error:
Brokenpipe
Post by Josip Djuricic
I am getting this in CLI on release candidate version of Asterisk. Any
ideas, or points where to look?
-- Launched AGI Script /var/lib/asterisk/agi-bin/rad-auth.agi
[Oct 22 18:21:45] ERROR[9853]: utils.c:1126 ast_carefulwrite: write()
returned error: Broken pipe
-- <SIP/916-fc001968>AGI Script rad-auth.agi completed, returning 0
Generally, that means that your AGI exited early, before the AGI controller
had a chance to output responses. You could ignore the error, or you could
fix your AGI script to ensure that it receives full responses before
exiting.
--
Tilghman Lesher
Digium, Inc. | Senior Software Developer
twitter: Corydon76 | IRC: Corydon76-dig (Freenode)
Check us out at: www.digium.com & www.asterisk.org

_______________________________________________
-- Bandwidth and Colocation Provided by http://www.api-digital.com --

asterisk-users mailing list
To UNSUBSCRIBE or update options visit:
http://lists.digium.com/mailman/listinfo/asterisk-users
Tilghman Lesher
2009-10-22 16:43:22 UTC
Permalink
Post by Danny Nicholas
I have some simple PERL scripts that worked fine with 1.4 SVN, but returned
this error when I went to 1.4.26.2. It seemed easier to change the ERROR
to a NOTIFY than try to "Fix my bad code".
Here is the "failing" code
#!/usr/local/bin/perl
use strict;
use warnings;
sub setvar {
print STDOUT "SET VARIABLE $var \"$val\" \r\n";
my $rv=<STDIN>;
return;
}
# turn off I/O buffering
$| = 1;
# get trunk information
$SIG{'PIPE'} = 'IGNORE';
my $images='TRUE';
my $checks='TRUE';
&setvar("TEST_RETURN", "OK");
&setvar("CHECKS", $checks);
&setvar("IMAGES", $images);
exit;
What is clearly wrong with your script is that you're failing to retrieve all
of the setup information that is sent when the script first starts up. Each
"response" that you're getting is actually setup information, and you exit
early, which is why the final response is not able to be sent.
--
Tilghman Lesher
Digium, Inc. | Senior Software Developer
twitter: Corydon76 | IRC: Corydon76-dig (Freenode)
Check us out at: www.digium.com & www.asterisk.org
Danny Nicholas
2009-10-22 17:34:07 UTC
Permalink
If it was clear, I wouldn't be writing; You are suggesting something like
this?
Post by Danny Nicholas
sub setvar {
print STDOUT "SET VARIABLE $var \"$val\" \r\n";
my $rv=<STDIN>;
while(<STDIN>) {
m/200 result=0/ && last;
}
return;
}
-----Original Message-----
From: asterisk-users-***@lists.digium.com
[mailto:asterisk-users-***@lists.digium.com] On Behalf Of Tilghman
Lesher
Sent: Thursday, October 22, 2009 11:43 AM
To: Asterisk Users Mailing List - Non-Commercial Discussion
Subject: Re: [asterisk-users] carefulwrite: write() returned
error:Brokenpipe
Post by Danny Nicholas
I have some simple PERL scripts that worked fine with 1.4 SVN, but returned
this error when I went to 1.4.26.2. It seemed easier to change the ERROR
to a NOTIFY than try to "Fix my bad code".
Here is the "failing" code
#!/usr/local/bin/perl
use strict;
use warnings;
sub setvar {
print STDOUT "SET VARIABLE $var \"$val\" \r\n";
my $rv=<STDIN>;
return;
}
# turn off I/O buffering
$| = 1;
# get trunk information
$SIG{'PIPE'} = 'IGNORE';
my $images='TRUE';
my $checks='TRUE';
&setvar("TEST_RETURN", "OK");
&setvar("CHECKS", $checks);
&setvar("IMAGES", $images);
exit;
What is clearly wrong with your script is that you're failing to retrieve
all
of the setup information that is sent when the script first starts up. Each
"response" that you're getting is actually setup information, and you exit
early, which is why the final response is not able to be sent.
--
Tilghman Lesher
Digium, Inc. | Senior Software Developer
twitter: Corydon76 | IRC: Corydon76-dig (Freenode)
Check us out at: www.digium.com & www.asterisk.org

_______________________________________________
-- Bandwidth and Colocation Provided by http://www.api-digital.com --

asterisk-users mailing list
To UNSUBSCRIBE or update options visit:
http://lists.digium.com/mailman/listinfo/asterisk-users
Steve Edwards
2009-10-22 18:06:45 UTC
Permalink
Un-top-posting...
Post by Tilghman Lesher
Lesher
What is clearly wrong with your script is that you're failing to
retrieve all of the setup information that is sent when the script first
starts up. Each "response" that you're getting is actually setup
information, and you exit early, which is why the final response is not
able to be sent.
If it was clear, I wouldn't be writing; You are suggesting something like
this?
Post by Danny Nicholas
sub setvar {
print STDOUT "SET VARIABLE $var \"$val\" \r\n";
my $rv=<STDIN>;
while(<STDIN>) {
m/200 result=0/ && last;
}
return;
}
Your previous script violates the AGI protocol because it does not read
the AGI environment before issuing an AGI request.

So, when you issue a request and read a response, you are reading a piece
of the AGI environment, not the response to your request.

Then, when you exit, you haven't read all of the AGI environment or the
responses to your requests so, you get a "reprimand."
--
Thanks in advance,
-------------------------------------------------------------------------
Steve Edwards ***@sedwards.com Voice: +1-760-468-3867 PST
Newline Fax: +1-760-731-3000
Danny Nicholas
2009-10-22 18:14:47 UTC
Permalink
So this would actually be proper?
Here is the "failing" code
Post by Danny Nicholas
#!/usr/local/bin/perl
use strict;
use warnings;
sub setvar {
print STDOUT "SET VARIABLE $var \"$val\" \r\n";
while(<STDIN>) {
m/200 result=0/ && last;
}
return;
}
# turn off I/O buffering
$| = 1;
# get trunk information
$SIG{'PIPE'} = 'IGNORE';
my $images='TRUE';
my $checks='TRUE';
my $envvars = <STDIN>;
&setvar("TEST_RETURN", "OK");
&setvar("CHECKS", $checks);
&setvar("IMAGES", $images);
exit;
-----Original Message-----
From: asterisk-users-***@lists.digium.com
[mailto:asterisk-users-***@lists.digium.com] On Behalf Of Steve Edwards
Sent: Thursday, October 22, 2009 1:07 PM
To: Asterisk Users Mailing List - Non-Commercial Discussion
Subject: Re: [asterisk-users] carefulwrite: write() returned
error:Brokenpipe

Un-top-posting...
Post by Danny Nicholas
Lesher
What is clearly wrong with your script is that you're failing to
retrieve all of the setup information that is sent when the script first
starts up. Each "response" that you're getting is actually setup
information, and you exit early, which is why the final response is not
able to be sent.
If it was clear, I wouldn't be writing; You are suggesting something like
this?
Post by Danny Nicholas
sub setvar {
print STDOUT "SET VARIABLE $var \"$val\" \r\n";
my $rv=<STDIN>;
while(<STDIN>) {
m/200 result=0/ && last;
}
return;
}
Your previous script violates the AGI protocol because it does not read
the AGI environment before issuing an AGI request.

So, when you issue a request and read a response, you are reading a piece
of the AGI environment, not the response to your request.

Then, when you exit, you haven't read all of the AGI environment or the
responses to your requests so, you get a "reprimand."
--
Thanks in advance,
-------------------------------------------------------------------------
Steve Edwards ***@sedwards.com Voice: +1-760-468-3867 PST
Newline Fax: +1-760-731-3000

_______________________________________________
-- Bandwidth and Colocation Provided by http://www.api-digital.com --

asterisk-users mailing list
To UNSUBSCRIBE or update options visit:
http://lists.digium.com/mailman/listinfo/asterisk-users
Steve Edwards
2009-10-22 18:47:54 UTC
Permalink
Post by Danny Nicholas
So this would actually be proper?
[snip]
Post by Danny Nicholas
Post by Danny Nicholas
my $envvars = <STDIN>;
I don't "do" Perl, but if that statement reads everything buffered on
STDIN -- i.e., the AGI environment, then I would guess it would work.

"Proper" would be to read and parse the environment "properly." You could
make the argument that since you're not going to use anything from the AGI
environment, why waste the cycles.

I would counter that "best practice" would be to read and parse the
environment as well as setting up a SIGHUP handler, initializing syslog(),
setting a STATUS channel variable to FAILURE (and setting it to SUCCESS
upon successful completion), etc., etc., etc.

I find that "feeping creaturism" is easier to deal with if you start with
a good framework.

I could have said something about using a "real" language like C so you
could do everything you want and be finished way before you could even
load the Perl interpreter but I don't feel like ducking :)
--
Thanks in advance,
-------------------------------------------------------------------------
Steve Edwards ***@sedwards.com Voice: +1-760-468-3867 PST
Newline Fax: +1-760-731-3000
Danny Nicholas
2009-10-22 18:53:14 UTC
Permalink
For my (and any other lazy watchers) benefit, would you post how you would
do my snippet in C?

-----Original Message-----
From: asterisk-users-***@lists.digium.com
[mailto:asterisk-users-***@lists.digium.com] On Behalf Of Steve Edwards
Sent: Thursday, October 22, 2009 1:48 PM
To: Asterisk Users Mailing List - Non-Commercial Discussion
Subject: Re: [asterisk-users] carefulwrite: write() returned
error:Brokenpipe
Post by Danny Nicholas
So this would actually be proper?
[snip]
Post by Danny Nicholas
Post by Danny Nicholas
my $envvars = <STDIN>;
I don't "do" Perl, but if that statement reads everything buffered on
STDIN -- i.e., the AGI environment, then I would guess it would work.

"Proper" would be to read and parse the environment "properly." You could
make the argument that since you're not going to use anything from the AGI
environment, why waste the cycles.

I would counter that "best practice" would be to read and parse the
environment as well as setting up a SIGHUP handler, initializing syslog(),
setting a STATUS channel variable to FAILURE (and setting it to SUCCESS
upon successful completion), etc., etc., etc.

I find that "feeping creaturism" is easier to deal with if you start with
a good framework.

I could have said something about using a "real" language like C so you
could do everything you want and be finished way before you could even
load the Perl interpreter but I don't feel like ducking :)
--
Thanks in advance,
-------------------------------------------------------------------------
Steve Edwards ***@sedwards.com Voice: +1-760-468-3867 PST
Newline Fax: +1-760-731-3000

_______________________________________________
-- Bandwidth and Colocation Provided by http://www.api-digital.com --

asterisk-users mailing list
To UNSUBSCRIBE or update options visit:
http://lists.digium.com/mailman/listinfo/asterisk-users
Steve Edwards
2009-10-22 19:45:02 UTC
Permalink
Un-top-posting...
Post by Steve Edwards
Post by Danny Nicholas
So this would actually be proper?
[snip]
Post by Danny Nicholas
Post by Danny Nicholas
my $envvars = <STDIN>;
I don't "do" Perl, but if that statement reads everything buffered on
STDIN -- i.e., the AGI environment, then I would guess it would work.
"Proper" would be to read and parse the environment "properly." You could
make the argument that since you're not going to use anything from the AGI
environment, why waste the cycles.
I would counter that "best practice" would be to read and parse the
environment as well as setting up a SIGHUP handler, initializing syslog(),
setting a STATUS channel variable to FAILURE (and setting it to SUCCESS
upon successful completion), etc., etc., etc.
For my (and any other lazy watchers) benefit, would you post how you would
do my snippet in C?
I don't think it will do you much good since you don't have my AGI
library, but below is an AGI from a current project that reads a bunch
of stuff from a database and sets a bunch (hundreds) of variables.

I'm a big fan of using an established library so all the funky details
are taken care of for you and you don't get "bit" by changes like you
have. If I had found a C library when I started, I would have used it.

This wasn't written with "publication" in mind but it does show my
"framework" for all my AGIs.

Keep in mind the AGI below executes in less than a second, including the
database accesses.

My apologies to the list for the length :)

//
// Filename: lookup-dnis.c
//
#define Version "002"
//
// Edit date: 2009-10-16
//
// Facility: Asterisk
//
// Abstract: This AGI 'script' implements the lookup-dnis
// application.
//
// Environment: Asterisk
//
// Author: Steven L. Edwards
//
// Modified by
//
// 000 2009-03-23 SLE Create.
// 001 2009-10-16 SLE Log variables if debug.
// 002 2009-10-16 SLE Add flags.

////////////////////////////////////////|//////////////////////////////////////
// ANSI include files
////////////////////////////////////////|//////////////////////////////////////
#include <ctype.h>
#include <errno.h>
#include <signal.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

////////////////////////////////////////|//////////////////////////////////////
// Operating system include files
////////////////////////////////////////|//////////////////////////////////////
#include <syslog.h>

////////////////////////////////////////|//////////////////////////////////////
// Local include files
////////////////////////////////////////|//////////////////////////////////////
#include "agi.h"
#include "agi-mysql.h"
#include "all.h"
#include "getopt.h"
#include "mysql.h"

////////////////////////////////////////|//////////////////////////////////////
// Defines
////////////////////////////////////////|//////////////////////////////////////

////////////////////////////////////////|//////////////////////////////////////
// Macros
////////////////////////////////////////|//////////////////////////////////////

////////////////////////////////////////|//////////////////////////////////////
// Typedefs
////////////////////////////////////////|//////////////////////////////////////

////////////////////////////////////////|//////////////////////////////////////
// Global constants
////////////////////////////////////////|//////////////////////////////////////

////////////////////////////////////////|//////////////////////////////////////
// Global variables
////////////////////////////////////////|//////////////////////////////////////

////////////////////////////////////////|//////////////////////////////////////
// Global functions
////////////////////////////////////////|//////////////////////////////////////

////////////////////////////////////////|//////////////////////////////////////
// External constants
////////////////////////////////////////|//////////////////////////////////////

////////////////////////////////////////|//////////////////////////////////////
// External variables
////////////////////////////////////////|//////////////////////////////////////
extern char *optarg;

////////////////////////////////////////|//////////////////////////////////////
// External functions
////////////////////////////////////////|//////////////////////////////////////

////////////////////////////////////////|//////////////////////////////////////
// Static constants
////////////////////////////////////////|//////////////////////////////////////

////////////////////////////////////////|//////////////////////////////////////
// Static variables
////////////////////////////////////////|//////////////////////////////////////
static int debug_mode;
static MYSQL mysql;
static MYSQL_ROW mysql_row;
static int test_mode;
static int verbose_mode;

////////////////////////////////////////|//////////////////////////////////////
// Static functions
////////////////////////////////////////|//////////////////////////////////////
static int lookup_dnis
(
const char *dnis_pointer
);
static void hangup
(
void
);

////////////////////////////////////////|//////////////////////////////////////
// Main function
////////////////////////////////////////|//////////////////////////////////////
global int main
(
int argc
, char **argv
)
{
auto char dnis[256];
static struct option long_options[]
= {
{"debug-mode", no_argument, &debug_mode, 1}
, {"help", no_argument, 0, '?'}
, {"null", no_argument, 0, 0}
, {"test-mode", no_argument, &test_mode, 1}
, {"verbose-mode", no_argument, &verbose_mode, 1}
, {"version", no_argument, 0, 'v'}
, {0, 0, 0, 0}
};
auto int optchar;
auto char *pointer1;
auto char *pointer2;
auto int status;

// set the syslog ident
setlogmask(LOG_UPTO(LOG_NOTICE));
openlog(argv[0], LOG_PID, LOG_USER);

// read the AGI environment
agi_read_environment();

// assume failure
agi_set_status_failure();

// get the DNIS
memset(dnis, 0, sizeof(dnis));
agi_get_variable("DNIS", dnis);

// process the command line arguments
while (-1 != (optchar
= getopt_long(
argc
, argv
, ""
, long_options
, 0
)))
{
switch (optchar)
{
// help
case '?':
default:
puts("Usage:\tlookup-dnis\\");
puts("\t\t--debug-mode");
puts("\t\t--help\\");
puts("\t\t--null\\");
puts("\t\t--verbose-mode\\");
puts("\t\t--version");
exit(EXIT_SUCCESS);
break;
// version
case 'v':
printf("%s version %s\n"
, *argv
, Version
);
printf("Compiled on %s at %s\n"
, __DATE__
, __TIME__
);
exit(EXIT_SUCCESS);
break;

// something automagically handled by getopt_long()
case 0:
break;
}
}

// set verbose mode
if (0 != verbose_mode)
{
setlogmask(LOG_UPTO(LOG_INFO));
}

// set debug mode
if (0 != debug_mode)
{
setlogmask(LOG_UPTO(LOG_DEBUG));
}

// say who we are
syslog(LOG_DEBUG
, "Starting, version %s"
, Version
);

// trap SIGHUP -- caller hung up
signal(SIGHUP, (void (*)(int))(int)hangup);

// clean the DNIS
pointer1 = pointer2 = dnis;
--pointer1;
while (0 != *++pointer1)
{
// keep letters, forcing to lower case
if (0 != isalpha(*pointer1))
{
*pointer2++ = 32 | *pointer1;
continue;
}
// keep numbers
if (0 != isdigit(*pointer1))
{
*pointer2++ = *pointer1;
continue;
}
}
// terminate the DNIS
*pointer2 = 0;

// drop leading 1
if ('1' == *dnis)
{
auto char temp[256];
strcpy(temp, dnis + 1);
strcpy(dnis, temp);
}

// log the DNIS
syslog(LOG_DEBUG, "DNIS = %s", dnis);

// connect to the database
if (EXIT_FAILURE == (status = agi_connect_to_database(
&mysql // context
)))
{
syslog(LOG_ERR
, "%m, mysql_error = \"%s\""
, mysql_error(&mysql)
);
agi_verbose(
"Failed to connect to the database"
", mysql_error = \"%s\""
, mysql_error(&mysql)
);
exit(EXIT_FAILURE);
}

// lookup the DNIS
if (EXIT_FAILURE == (status = lookup_dnis(dnis)))
{
mysql_close(&mysql);
agi_set_status_failure();
return(EXIT_FAILURE);
}

// function exit
mysql_close(&mysql);
agi_set_status_success();
return(EXIT_SUCCESS);

}

////////////////////////////////////////|///////////////////////////////|//////
// hangup()
//
// Asterisk delivers a SIGHUP when the caller hangs up. Since we have
// already registered a process termination function, all we have to
// do is exit.
////////////////////////////////////////|///////////////////////////////|//////
static void hangup
(
void
)
{
mysql_close(&mysql);
exit(EXIT_SUCCESS);
}

////////////////////////////////////////|///////////////////////////////|//////
// lookup_dnis()
//
// Lookup the DNIS. Exit if successful.
////////////////////////////////////////|///////////////////////////////|//////
static int lookup_dnis
(
const char *dnis_pointer
)
{
auto int column;
auto MYSQL_FIELD *fields;
auto int index;
auto int num_fields;
auto int num_rows;
auto MYSQL_RES *result_pointer;
static const char recipes[]
= "select"
" client_id"
", confirm_prompt"
", goodbye"
", initial_language"
", outbound_dialstring"
", verification_prompt_a"
", verification_prompt_b"
", you_entered_prompt"
" from"
" dnises"
", recipes"
" where '%s' = dnis"
" and dnises.recipe = recipes.recipe"
;
auto int status;
static const char steps[]
= "select"
" steps.idx"
// idx must be the first column
", steps.active"
", steps.data"
", steps.flags"
", steps.max_length"
", steps.min_length"
", steps.prompt"
", steps.retry_prompt"
", steps.type"
" from"
" dnises"
", recipes"
", steps"
" where '%s' = dnis"
" and dnises.recipe = recipes.recipe"
" and recipes.recipe = steps.recipe"
" order by idx"
;

// look for the recipe parameters
exec_sql(&mysql
, &result_pointer
, recipes // select statement template
, dnis_pointer // dnis
);

// complain if not found
if ((1 != mysql_num_rows(result_pointer))
|| ((0 == (mysql_row = mysql_fetch_row(result_pointer)))))
{
syslog(LOG_ERR
, "No setup for DNIS %s in the DNISES"
" and RECIPES tables."
, dnis_pointer
);
return(EXIT_FAILURE);
}

// set the variables
num_fields = mysql_num_fields(result_pointer);
fields = mysql_fetch_fields(result_pointer);
for (column = 0; column < num_fields; ++column)
{
auto char *pointer;
auto char temp[256];
if ((0 == mysql_row[column])
|| ('(' == *mysql_row[column]))
{
continue;
}
strcpy(temp, fields[column].name);
pointer = temp;
while (0 != *pointer)
{
if (islower(*pointer))
{
*pointer = toupper(*pointer);
}
if ('_' == *pointer)
{
*pointer = '-';
}
++pointer;
}
syslog(LOG_DEBUG, "%s = \"%s\"", temp, mysql_row[column]);
agi_set_variable(temp, mysql_row[column]);
}

// look for the step parameters
status = exec_sql(&mysql
, &result_pointer
, steps // select statement template
, dnis_pointer // dnis
);
if (0 != status)
{
syslog(LOG_ERR
, "%m, mysql_error = \"%s\""
, mysql_error(&mysql)
);
}

// complain if not found
if (1 > (num_rows = mysql_num_rows(result_pointer)))
{
syslog(LOG_ERR
, "No setup for DNIS %s in the DNISES,"
" RECIPES, and STEPS tables."
, dnis_pointer
);
return(EXIT_FAILURE);
}

// walk through the rows
for (index = 0; ; ++index)
{
mysql_data_seek(result_pointer, index);
if (0 == (mysql_row = mysql_fetch_row(result_pointer)))
{
break;
}

// set the variables
num_fields = mysql_num_fields(result_pointer);
fields = mysql_fetch_fields(result_pointer);
for (column = 0; column < num_fields; ++column)
{
auto char *pointer;
auto char temp[256];
if ((0 == mysql_row[column])
|| ('(' == *mysql_row[column]))
{
continue;
}
sprintf(temp
, "STEP-%02d-%s"
, atoi(mysql_row[0])
, fields[column].name
);
pointer = temp + 5;
while (0 != *pointer)
{
if (islower(*pointer))
{
*pointer = toupper(*pointer);
}
if ('_' == *pointer)
{
*pointer = '-';
}
++pointer;
}
syslog(LOG_DEBUG, "%s = \"%s\"", temp, mysql_row[column]);
agi_set_variable(temp, mysql_row[column]);
}
}

// free the result set
mysql_free_result(result_pointer);

// set the agi status
agi_set_status_failure();

// function exit
return(EXIT_SUCCESS);

}

// (end of lookup-dnis.c)
--
Thanks in advance,
-------------------------------------------------------------------------
Steve Edwards ***@sedwards.com Voice: +1-760-468-3867 PST
Newline Fax: +1-760-731-3000
Danny Nicholas
2009-10-22 19:55:30 UTC
Permalink
Sorry about the "top post" (OUTLOOK) -
Thanks for the framework. It's easier to learn from a starting point than
scratch. I'm not crazy about writing 1000 lines of C to do 30 lines of
PERL, but if it makes my system fly, so be it.

-----Original Message-----
From: asterisk-users-***@lists.digium.com
[mailto:asterisk-users-***@lists.digium.com] On Behalf Of Steve Edwards
Sent: Thursday, October 22, 2009 2:45 PM
To: Asterisk Users Mailing List - Non-Commercial Discussion
Subject: Re: [asterisk-users] carefulwrite: write() returned
error:Brokenpipe

Un-top-posting...
Post by Steve Edwards
Post by Danny Nicholas
So this would actually be proper?
[snip]
Post by Danny Nicholas
Post by Danny Nicholas
my $envvars = <STDIN>;
I don't "do" Perl, but if that statement reads everything buffered on
STDIN -- i.e., the AGI environment, then I would guess it would work.
"Proper" would be to read and parse the environment "properly." You could
make the argument that since you're not going to use anything from the AGI
environment, why waste the cycles.
I would counter that "best practice" would be to read and parse the
environment as well as setting up a SIGHUP handler, initializing syslog(),
setting a STATUS channel variable to FAILURE (and setting it to SUCCESS
upon successful completion), etc., etc., etc.
For my (and any other lazy watchers) benefit, would you post how you would
do my snippet in C?
I don't think it will do you much good since you don't have my AGI
library, but below is an AGI from a current project that reads a bunch
of stuff from a database and sets a bunch (hundreds) of variables.

I'm a big fan of using an established library so all the funky details
are taken care of for you and you don't get "bit" by changes like you
have. If I had found a C library when I started, I would have used it.

This wasn't written with "publication" in mind but it does show my
"framework" for all my AGIs.

Keep in mind the AGI below executes in less than a second, including the
database accesses.

My apologies to the list for the length :)

//
// Filename: lookup-dnis.c
//

** SNIP **

** SNIP **
// (end of lookup-dnis.c)
--
Thanks in advance,
-------------------------------------------------------------------------
Steve Edwards ***@sedwards.com Voice: +1-760-468-3867 PST
Newline Fax: +1-760-731-3000

_______________________________________________
-- Bandwidth and Colocation Provided by http://www.api-digital.com --

asterisk-users mailing list
To UNSUBSCRIBE or update options visit:
http://lists.digium.com/mailman/listinfo/asterisk-users
Steve Edwards
2009-10-22 20:30:31 UTC
Permalink
Post by Danny Nicholas
Sorry about the "top post" (OUTLOOK) -
Thanks for the framework. It's easier to learn from a starting point
than scratch. I'm not crazy about writing 1000 lines of C to do 30
lines of PERL, but if it makes my system fly, so be it.
If you discard my comments and account for my "open and explicit" coding
style, it's less than 200, but yes, Perl is a bit more "dense."

I don't have any experience with them, but there are 2 C AGI libraries
available -- cagi and quivr.
--
Thanks in advance,
-------------------------------------------------------------------------
Steve Edwards ***@sedwards.com Voice: +1-760-468-3867 PST
Newline Fax: +1-760-731-3000
Tzafrir Cohen
2009-10-22 20:49:39 UTC
Permalink
Post by Steve Edwards
Post by Danny Nicholas
Sorry about the "top post" (OUTLOOK) -
Thanks for the framework. It's easier to learn from a starting point
than scratch. I'm not crazy about writing 1000 lines of C to do 30
lines of PERL, but if it makes my system fly, so be it.
If you discard my comments and account for my "open and explicit" coding
style, it's less than 200, but yes, Perl is a bit more "dense."
I don't have any experience with them, but there are 2 C AGI libraries
available -- cagi and quivr.
There's also Asterisk::AGI in CPAN.

http://search.cpan.org/perldoc?Asterisk::AGI
http://search.cpan.org/dist/asterisk-perl/

Tends to be packaged for distributions nowadays.
--
Tzafrir Cohen
icq#16849755 jabber:***@xorcom.com
+972-50-7952406 mailto:***@xorcom.com
http://www.xorcom.com iax:***@local.xorcom.com/tzafrir
Steve Edwards
2009-10-22 21:04:46 UTC
Permalink
Post by Tzafrir Cohen
Post by Steve Edwards
Post by Danny Nicholas
Sorry about the "top post" (OUTLOOK) -
Thanks for the framework. It's easier to learn from a starting point
than scratch. I'm not crazy about writing 1000 lines of C to do 30
lines of PERL, but if it makes my system fly, so be it.
If you discard my comments and account for my "open and explicit" coding
style, it's less than 200, but yes, Perl is a bit more "dense."
I don't have any experience with them, but there are 2 C AGI libraries
available -- cagi and quivr.
There's also Asterisk::AGI in CPAN.
Except, the OP expressed interest in writing AGIs in C.
--
Thanks in advance,
-------------------------------------------------------------------------
Steve Edwards ***@sedwards.com Voice: +1-760-468-3867 PST
Newline Fax: +1-760-731-3000
Josip Djuricic
2009-10-23 08:59:09 UTC
Permalink
Sorry it was the AGI STATUS variable, that I forgot to return.

Best regards,

Josip


-----Original Message-----
From: asterisk-users-***@lists.digium.com
[mailto:asterisk-users-***@lists.digium.com] On Behalf Of Steve Edwards
Sent: Thursday, October 22, 2009 11:05 PM
To: Asterisk Users Mailing List - Non-Commercial Discussion
Subject: Re: [asterisk-users] carefulwrite: write() returned
error:Brokenpipe
Post by Tzafrir Cohen
Post by Steve Edwards
Post by Danny Nicholas
Sorry about the "top post" (OUTLOOK) -
Thanks for the framework. It's easier to learn from a starting point
than scratch. I'm not crazy about writing 1000 lines of C to do 30
lines of PERL, but if it makes my system fly, so be it.
If you discard my comments and account for my "open and explicit" coding
style, it's less than 200, but yes, Perl is a bit more "dense."
I don't have any experience with them, but there are 2 C AGI libraries
available -- cagi and quivr.
There's also Asterisk::AGI in CPAN.
Except, the OP expressed interest in writing AGIs in C.
--
Thanks in advance,
-------------------------------------------------------------------------
Steve Edwards ***@sedwards.com Voice: +1-760-468-3867 PST
Newline Fax: +1-760-731-3000

_______________________________________________
-- Bandwidth and Colocation Provided by http://www.api-digital.com --

asterisk-users mailing list
To UNSUBSCRIBE or update options visit:
http://lists.digium.com/mailman/listinfo/asterisk-users
Loading...