@ -1057,30 +1057,13 @@ int ast_wait_for_input(int fd, int ms)
return poll ( pfd , 1 , ms ) ;
}
/*!
* Try to write string , but wait no more than ms milliseconds before timing out .
*
* \ note The code assumes that the file descriptor has NONBLOCK set ,
* so there is only one system call made to do a write , unless we actually
* have a need to wait . This way , we get better performance .
* If the descriptor is blocking , all assumptions on the guaranteed
* detail do not apply anymore .
* Also note that in the current implementation , the delay is per - write ,
* so you still have no guarantees , anyways .
* Fortunately the routine is only used in a few places ( cli . c , manager . c ,
* res_agi . c ) so it is reasonably easy to check how it behaves there .
*
* XXX We either need to fix the code , or fix the documentation .
*/
int ast_carefulwrite ( int fd , char * s , int len , int timeoutms )
static int ast_wait_for_output ( int fd , int timeoutms )
{
int res = 0 ;
while ( len ) {
struct pollfd pfd = {
. fd = fd ,
. events = POLLOUT ,
} ;
int res ;
/* poll() until the fd is writable without blocking */
while ( ( res = poll ( & pfd , 1 , timeoutms ) ) < = 0 ) {
@ -1103,6 +1086,33 @@ int ast_carefulwrite(int fd, char *s, int len, int timeoutms)
}
}
return 0 ;
}
/*!
* Try to write string , but wait no more than ms milliseconds before timing out .
*
* \ note The code assumes that the file descriptor has NONBLOCK set ,
* so there is only one system call made to do a write , unless we actually
* have a need to wait . This way , we get better performance .
* If the descriptor is blocking , all assumptions on the guaranteed
* detail do not apply anymore .
* Also note that in the current implementation , the delay is per - write ,
* so you still have no guarantees , anyways .
* Fortunately the routine is only used in a few places ( cli . c , manager . c ,
* res_agi . c ) so it is reasonably easy to check how it behaves there .
*
* XXX We either need to fix the code , or fix the documentation .
*/
int ast_carefulwrite ( int fd , char * s , int len , int timeoutms )
{
int res = 0 ;
while ( len ) {
if ( ast_wait_for_output ( fd , timeoutms ) ) {
return - 1 ;
}
res = write ( fd , s , len ) ;
if ( res < 0 & & errno ! = EAGAIN & & errno ! = EINTR ) {
@ -1125,6 +1135,62 @@ int ast_carefulwrite(int fd, char *s, int len, int timeoutms)
return res ;
}
int ast_careful_fwrite ( FILE * f , int fd , const char * src , size_t len , int timeoutms )
{
struct timeval start = ast_tvnow ( ) ;
int n = 0 ;
while ( len ) {
int elapsed ;
if ( ast_wait_for_output ( fd , timeoutms ) ) {
/* poll returned a fatal error, so bail out immediately. */
return - 1 ;
}
/* Clear any errors from a previous write */
clearerr ( f ) ;
n = fwrite ( src , 1 , len , f ) ;
if ( ferror ( f ) & & errno ! = EINTR & & errno ! = EAGAIN ) {
/* fatal error from fwrite() */
if ( ! feof ( f ) ) {
/* Don't spam the logs if it was just that the connection is closed. */
ast_log ( LOG_ERROR , " fwrite() returned error: %s \n " , strerror ( errno ) ) ;
}
n = - 1 ;
break ;
}
/* Update for data already written to the socket */
len - = n ;
src + = n ;
elapsed = ast_tvdiff_ms ( ast_tvnow ( ) , start ) ;
if ( elapsed > timeoutms ) {
/* We've taken too long to write
* This is only an error condition if we haven ' t finished writing . */
n = len ? - 1 : 0 ;
break ;
}
}
while ( fflush ( f ) ) {
if ( errno = = EAGAIN | | errno = = EINTR ) {
continue ;
}
if ( ! feof ( f ) ) {
/* Don't spam the logs if it was just that the connection is closed. */
ast_log ( LOG_ERROR , " fflush() returned error: %s \n " , strerror ( errno ) ) ;
}
n = - 1 ;
break ;
}
return n < 0 ? - 1 : 0 ;
}
char * ast_strip_quoted ( char * s , const char * beg_quotes , const char * end_quotes )
{
char * e ;