2014-02-28 10:15:24 +00:00
/**
\ file env_universal_common . c
2005-09-20 13:26:39 +00:00
The utility library for universal variables . Used both by the
client library and by the daemon .
*/
2006-01-30 16:58:00 +00:00
# include "config.h"
2006-02-28 13:17:16 +00:00
2005-09-20 13:26:39 +00:00
# include <stdlib.h>
# include <stdio.h>
# include <wchar.h>
2006-08-09 22:34:52 +00:00
# include <string.h>
2005-09-20 13:26:39 +00:00
# include <unistd.h>
# include <sys/types.h>
# include <sys/socket.h>
# include <sys/un.h>
# include <pwd.h>
# include <errno.h>
# include <sys/stat.h>
# include <dirent.h>
# include <wctype.h>
# include <errno.h>
# include <locale.h>
# include <dirent.h>
# include <signal.h>
# include <sys/stat.h>
2012-02-17 18:52:30 +00:00
# include <map>
2005-09-20 13:26:39 +00:00
2006-08-09 22:26:05 +00:00
# ifdef HAVE_SYS_SELECT_H
# include <sys/select.h>
# endif
2006-02-28 13:17:16 +00:00
# include "fallback.h"
2005-09-20 13:26:39 +00:00
# include "util.h"
2006-02-28 13:17:16 +00:00
2005-09-20 13:26:39 +00:00
# include "common.h"
# include "wutil.h"
2014-03-23 20:06:24 +00:00
# include "utf8.h"
2005-09-20 13:26:39 +00:00
# include "env_universal_common.h"
/**
Non - wide version of the set command
*/
# define SET_MBS "SET"
2005-09-22 20:16:52 +00:00
/**
Non - wide version of the set_export command
*/
# define SET_EXPORT_MBS "SET_EXPORT"
2005-09-20 13:26:39 +00:00
/**
Non - wide version of the erase command
*/
# define ERASE_MBS "ERASE"
2005-09-22 20:16:52 +00:00
/**
Non - wide version of the barrier command
*/
2005-09-20 13:26:39 +00:00
# define BARRIER_MBS "BARRIER"
2005-09-22 20:16:52 +00:00
/**
Non - wide version of the barrier_reply command
*/
2005-09-20 13:26:39 +00:00
# define BARRIER_REPLY_MBS "BARRIER_REPLY"
/**
Error message
*/
# define PARSE_ERR L"Unable to parse universal variable message: '%ls'"
2006-10-06 18:45:39 +00:00
/**
ERROR string for internal buffered reader
*/
# define ENV_UNIVERSAL_ERROR 0x100
/**
EAGAIN string for internal buffered reader
*/
# define ENV_UNIVERSAL_AGAIN 0x101
/**
EOF string for internal buffered reader
*/
# define ENV_UNIVERSAL_EOF 0x102
2012-11-19 00:30:30 +00:00
static void parse_message ( wchar_t * msg ,
connection_t * src ) ;
2005-09-20 13:26:39 +00:00
/**
The table of all universal variables
*/
2014-04-25 23:09:26 +00:00
static env_universal_t s_env_universal_var ;
2005-09-20 13:26:39 +00:00
2005-10-24 15:26:25 +00:00
/**
Callback function , should be called on all events
*/
2012-11-19 00:30:30 +00:00
static void ( * callback ) ( fish_message_type_t type ,
const wchar_t * key ,
const wchar_t * val ) ;
2005-09-20 13:26:39 +00:00
2014-03-23 20:06:24 +00:00
/* UTF <-> wchar conversions. These return a string allocated with malloc. These call sites could be cleaned up substantially to eliminate the dependence on malloc. */
static wchar_t * utf2wcs ( const char * input )
2006-10-17 21:11:29 +00:00
{
2014-03-23 20:06:24 +00:00
wchar_t * result = NULL ;
wcstring converted ;
if ( utf8_to_wchar_string ( input , & converted ) )
2012-11-19 00:30:30 +00:00
{
2014-03-23 20:06:24 +00:00
result = wcsdup ( converted . c_str ( ) ) ;
2012-11-19 00:30:30 +00:00
}
2014-03-23 20:06:24 +00:00
return result ;
2006-10-17 21:11:29 +00:00
}
2014-03-23 20:06:24 +00:00
static char * wcs2utf ( const wchar_t * input )
2006-10-17 21:11:29 +00:00
{
2014-03-23 20:06:24 +00:00
char * result = NULL ;
std : : string converted ;
if ( wchar_to_utf8_string ( input , & converted ) )
2012-11-19 00:30:30 +00:00
{
2014-03-23 20:06:24 +00:00
result = strdup ( converted . c_str ( ) ) ;
2012-11-19 00:30:30 +00:00
}
2014-03-23 20:06:24 +00:00
return result ;
2006-10-17 21:11:29 +00:00
}
2012-11-19 00:30:30 +00:00
void env_universal_common_init ( void ( * cb ) ( fish_message_type_t type , const wchar_t * key , const wchar_t * val ) )
2005-09-20 13:26:39 +00:00
{
2012-11-19 00:30:30 +00:00
callback = cb ;
2005-09-20 13:26:39 +00:00
}
2008-01-13 16:47:47 +00:00
/**
Read one byte of date form the specified connection
*/
2012-11-19 00:30:30 +00:00
static int read_byte ( connection_t * src )
2006-10-06 18:45:39 +00:00
{
2013-02-16 09:28:46 +00:00
if ( src - > buffer_consumed > = src - > read_buffer . size ( ) )
2012-11-19 00:30:30 +00:00
{
2013-02-16 09:28:46 +00:00
char local [ ENV_UNIVERSAL_BUFFER_SIZE ] ;
2013-02-20 01:48:51 +00:00
2013-02-16 09:28:46 +00:00
ssize_t res = read ( src - > fd , local , sizeof local ) ;
2012-11-18 10:23:22 +00:00
// debug(4, L"Read chunk '%.*s'", res, src->buffer );
2012-11-19 00:30:30 +00:00
if ( res < 0 )
{
2012-11-18 10:23:22 +00:00
2012-11-19 00:30:30 +00:00
if ( errno = = EAGAIN | |
errno = = EINTR )
{
return ENV_UNIVERSAL_AGAIN ;
}
2012-11-18 10:23:22 +00:00
2012-11-19 00:30:30 +00:00
return ENV_UNIVERSAL_ERROR ;
2012-11-18 10:23:22 +00:00
2012-11-19 00:30:30 +00:00
}
2013-02-16 09:28:46 +00:00
else if ( res = = 0 )
2012-11-19 00:30:30 +00:00
{
return ENV_UNIVERSAL_EOF ;
}
2013-02-16 09:28:46 +00:00
else
{
src - > read_buffer . clear ( ) ;
src - > read_buffer . insert ( src - > read_buffer . begin ( ) , local , local + res ) ;
src - > buffer_consumed = 0 ;
}
2012-11-19 00:30:30 +00:00
}
2012-11-18 10:23:22 +00:00
2013-02-16 09:28:46 +00:00
return src - > read_buffer . at ( src - > buffer_consumed + + ) ;
2006-10-06 18:45:39 +00:00
}
2005-09-20 13:26:39 +00:00
2012-11-19 00:30:30 +00:00
void read_message ( connection_t * src )
2005-09-20 13:26:39 +00:00
{
2012-11-19 00:30:30 +00:00
while ( 1 )
{
2012-11-18 10:23:22 +00:00
2012-11-19 00:30:30 +00:00
int ib = read_byte ( src ) ;
char b ;
2012-11-18 10:23:22 +00:00
2012-11-19 00:30:30 +00:00
switch ( ib )
{
2012-11-19 08:31:03 +00:00
case ENV_UNIVERSAL_AGAIN :
{
return ;
}
2012-11-18 10:23:22 +00:00
2012-11-19 08:31:03 +00:00
case ENV_UNIVERSAL_ERROR :
{
debug ( 2 , L " Read error on fd %d, set killme flag " , src - > fd ) ;
if ( debug_level > 2 )
wperror ( L " read " ) ;
src - > killme = 1 ;
return ;
}
2012-11-18 10:23:22 +00:00
2012-11-19 08:31:03 +00:00
case ENV_UNIVERSAL_EOF :
2012-11-19 00:30:30 +00:00
{
2012-11-19 08:31:03 +00:00
src - > killme = 1 ;
debug ( 3 , L " Fd %d has reached eof, set killme flag " , src - > fd ) ;
2013-02-16 10:38:13 +00:00
if ( ! src - > input . empty ( ) )
2012-11-19 08:31:03 +00:00
{
char c = 0 ;
src - > input . push_back ( c ) ;
debug ( 1 ,
L " Universal variable connection closed while reading command. Partial command recieved: '%s' " ,
& src - > input . at ( 0 ) ) ;
}
return ;
2012-11-19 00:30:30 +00:00
}
}
2012-11-18 10:23:22 +00:00
2012-11-19 00:30:30 +00:00
b = ( char ) ib ;
if ( b = = ' \n ' )
{
wchar_t * msg ;
2012-11-18 10:23:22 +00:00
2012-11-19 00:30:30 +00:00
b = 0 ;
2012-03-04 07:01:42 +00:00
src - > input . push_back ( b ) ;
2012-11-18 10:23:22 +00:00
2012-11-19 00:30:30 +00:00
msg = utf2wcs ( & src - > input . at ( 0 ) ) ;
2012-11-18 10:23:22 +00:00
2012-11-19 00:30:30 +00:00
/*
Before calling parse_message , we must empty reset
everything , since the callback function could
potentially call read_message .
*/
src - > input . clear ( ) ;
2012-11-18 10:23:22 +00:00
2012-11-19 00:30:30 +00:00
if ( msg )
{
parse_message ( msg , src ) ;
}
else
{
debug ( 0 , _ ( L " Could not convert message '%s' to wide character string " ) , & src - > input . at ( 0 ) ) ;
}
2012-11-18 10:23:22 +00:00
2012-11-19 00:30:30 +00:00
free ( msg ) ;
2012-11-18 10:23:22 +00:00
2012-11-19 00:30:30 +00:00
}
else
{
2012-03-04 07:01:42 +00:00
src - > input . push_back ( b ) ;
2012-11-19 00:30:30 +00:00
}
2012-11-18 10:23:22 +00:00
}
2005-09-20 13:26:39 +00:00
}
2005-10-24 15:26:25 +00:00
/**
Remove variable with specified name
*/
2012-11-19 00:30:30 +00:00
void env_universal_common_remove ( const wcstring & name )
2005-09-20 13:26:39 +00:00
{
2014-04-25 23:09:26 +00:00
s_env_universal_var . remove ( name ) ;
2005-09-20 13:26:39 +00:00
}
2005-10-24 15:26:25 +00:00
/**
Test if the message msg contains the command cmd
*/
2013-01-19 21:16:21 +00:00
static bool match ( const wchar_t * msg , const wchar_t * cmd )
2005-09-20 13:26:39 +00:00
{
2012-11-19 00:30:30 +00:00
size_t len = wcslen ( cmd ) ;
if ( wcsncasecmp ( msg , cmd , len ) ! = 0 )
2013-01-19 21:16:21 +00:00
return false ;
2012-11-18 10:23:22 +00:00
2012-11-19 00:30:30 +00:00
if ( msg [ len ] & & msg [ len ] ! = L ' ' & & msg [ len ] ! = L ' \t ' )
2013-01-19 21:16:21 +00:00
return false ;
2012-11-18 10:23:22 +00:00
2013-01-19 21:16:21 +00:00
return true ;
2005-09-20 13:26:39 +00:00
}
2013-01-19 21:16:21 +00:00
void env_universal_common_set ( const wchar_t * key , const wchar_t * val , bool exportv )
2006-11-15 12:34:47 +00:00
{
2012-11-19 00:30:30 +00:00
CHECK ( key , ) ;
CHECK ( val , ) ;
2014-04-25 23:09:26 +00:00
s_env_universal_var . set ( key , val , exportv ) ;
2012-02-17 18:52:30 +00:00
2012-11-19 00:30:30 +00:00
if ( callback )
{
callback ( exportv ? SET_EXPORT : SET , key , val ) ;
}
2006-11-15 12:34:47 +00:00
}
2005-10-24 15:26:25 +00:00
/**
Parse message msg
*/
2012-11-19 00:30:30 +00:00
static void parse_message ( wchar_t * msg ,
connection_t * src )
2005-09-20 13:26:39 +00:00
{
2012-11-18 10:23:22 +00:00
// debug( 3, L"parse_message( %ls );", msg );
2012-11-19 00:30:30 +00:00
if ( msg [ 0 ] = = L ' # ' )
return ;
2012-11-18 10:23:22 +00:00
2012-11-19 00:30:30 +00:00
if ( match ( msg , SET_STR ) | | match ( msg , SET_EXPORT_STR ) )
{
wchar_t * name , * tmp ;
2013-01-19 21:16:21 +00:00
bool exportv = match ( msg , SET_EXPORT_STR ) ;
2012-11-18 10:23:22 +00:00
2012-11-19 00:30:30 +00:00
name = msg + ( exportv ? wcslen ( SET_EXPORT_STR ) : wcslen ( SET_STR ) ) ;
while ( wcschr ( L " \t " , * name ) )
name + + ;
2012-11-18 10:23:22 +00:00
2012-11-19 00:30:30 +00:00
tmp = wcschr ( name , L ' : ' ) ;
if ( tmp )
{
2013-02-16 08:02:40 +00:00
const wcstring key ( name , tmp - name ) ;
2013-02-20 01:48:51 +00:00
2013-11-25 06:57:49 +00:00
wcstring val ;
if ( unescape_string ( tmp + 1 , & val , 0 ) )
{
env_universal_common_set ( key . c_str ( ) , val . c_str ( ) , exportv ) ;
}
2012-11-19 00:30:30 +00:00
}
else
{
debug ( 1 , PARSE_ERR , msg ) ;
}
2012-11-18 10:23:22 +00:00
}
2012-11-19 00:30:30 +00:00
else if ( match ( msg , ERASE_STR ) )
2012-11-18 10:23:22 +00:00
{
2012-11-19 00:30:30 +00:00
wchar_t * name , * tmp ;
2012-11-18 10:23:22 +00:00
2012-11-19 00:30:30 +00:00
name = msg + wcslen ( ERASE_STR ) ;
while ( wcschr ( L " \t " , * name ) )
name + + ;
2012-11-18 10:23:22 +00:00
2012-11-19 00:30:30 +00:00
tmp = name ;
while ( iswalnum ( * tmp ) | | * tmp = = L ' _ ' )
tmp + + ;
2012-11-18 10:23:22 +00:00
2012-11-19 00:30:30 +00:00
* tmp = 0 ;
2012-11-18 10:23:22 +00:00
2012-11-19 00:30:30 +00:00
if ( ! wcslen ( name ) )
{
debug ( 1 , PARSE_ERR , msg ) ;
}
2012-11-18 10:23:22 +00:00
2012-11-19 00:30:30 +00:00
env_universal_common_remove ( name ) ;
2012-11-18 10:23:22 +00:00
2012-11-19 00:30:30 +00:00
if ( callback )
{
callback ( ERASE , name , 0 ) ;
}
2012-11-18 10:23:22 +00:00
}
2012-11-19 00:30:30 +00:00
else if ( match ( msg , BARRIER_STR ) )
{
message_t * msg = create_message ( BARRIER_REPLY , 0 , 0 ) ;
msg - > count = 1 ;
2013-02-16 08:02:40 +00:00
src - > unsent . push ( msg ) ;
2012-11-19 00:30:30 +00:00
try_send_all ( src ) ;
}
else if ( match ( msg , BARRIER_REPLY_STR ) )
{
if ( callback )
{
callback ( BARRIER_REPLY , 0 , 0 ) ;
}
}
else
{
debug ( 1 , PARSE_ERR , msg ) ;
}
2005-09-20 13:26:39 +00:00
}
2005-10-24 15:26:25 +00:00
/**
Attempt to send the specified message to the specified file descriptor
\ return 1 on sucess , 0 if the message could not be sent without blocking and - 1 on error
*/
2012-11-19 00:30:30 +00:00
static int try_send ( message_t * msg ,
int fd )
2005-09-20 13:26:39 +00:00
{
2012-11-19 00:30:30 +00:00
debug ( 3 ,
L " before write of %d chars to fd %d " , msg - > body . size ( ) , fd ) ;
2012-11-18 10:23:22 +00:00
2012-11-19 00:30:30 +00:00
ssize_t res = write ( fd , msg - > body . c_str ( ) , msg - > body . size ( ) ) ;
2012-11-18 10:23:22 +00:00
2012-11-19 00:30:30 +00:00
if ( res ! = - 1 )
{
debug ( 4 , L " Wrote message '%s' " , msg - > body . c_str ( ) ) ;
}
else
{
debug ( 4 , L " Failed to write message '%s' " , msg - > body . c_str ( ) ) ;
}
2012-11-18 10:23:22 +00:00
2012-11-19 00:30:30 +00:00
if ( res = = - 1 )
2012-11-18 10:23:22 +00:00
{
2012-11-19 00:30:30 +00:00
switch ( errno )
{
2012-11-19 08:31:03 +00:00
case EAGAIN :
return 0 ;
2012-11-18 10:23:22 +00:00
2012-11-19 08:31:03 +00:00
default :
debug ( 2 ,
L " Error while sending universal variable message to fd %d. Closing connection " ,
fd ) ;
if ( debug_level > 2 )
wperror ( L " write " ) ;
2012-11-18 10:23:22 +00:00
2012-11-19 08:31:03 +00:00
return - 1 ;
2012-11-19 00:30:30 +00:00
}
2012-11-18 10:23:22 +00:00
}
2012-11-19 00:30:30 +00:00
msg - > count - - ;
2012-11-18 10:23:22 +00:00
2012-11-19 00:30:30 +00:00
if ( ! msg - > count )
{
delete msg ;
}
return 1 ;
2005-09-20 13:26:39 +00:00
}
2012-11-19 00:30:30 +00:00
void try_send_all ( connection_t * c )
2005-09-20 13:26:39 +00:00
{
2012-11-19 00:30:30 +00:00
/* debug( 3,
L " Send all updates to connection on fd %d " ,
c - > fd ) ; */
2013-02-16 08:02:40 +00:00
while ( ! c - > unsent . empty ( ) )
2012-11-19 00:30:30 +00:00
{
2013-02-16 08:02:40 +00:00
switch ( try_send ( c - > unsent . front ( ) , c - > fd ) )
2012-11-19 00:30:30 +00:00
{
2012-11-19 08:31:03 +00:00
case 1 :
2013-02-16 08:02:40 +00:00
c - > unsent . pop ( ) ;
2012-11-19 08:31:03 +00:00
break ;
case 0 :
debug ( 4 ,
L " Socket full, send rest later " ) ;
return ;
case - 1 :
c - > killme = 1 ;
return ;
2012-11-19 00:30:30 +00:00
}
2012-11-18 10:23:22 +00:00
}
2005-09-20 13:26:39 +00:00
}
2012-10-08 21:47:25 +00:00
/* The universal variable format has some funny escaping requirements; here we try to be safe */
static bool is_universal_safe_to_encode_directly ( wchar_t c )
{
if ( c < 32 | | c > 128 )
return false ;
2012-11-18 10:23:22 +00:00
2012-10-08 21:47:25 +00:00
return iswalnum ( c ) | | wcschr ( L " / " , c ) ;
}
2008-01-13 16:47:47 +00:00
/**
Escape specified string
*/
2012-11-19 00:30:30 +00:00
static wcstring full_escape ( const wchar_t * in )
2006-10-17 21:11:29 +00:00
{
2012-11-19 00:30:30 +00:00
wcstring out ;
for ( ; * in ; in + + )
{
2012-10-08 21:47:25 +00:00
wchar_t c = * in ;
if ( is_universal_safe_to_encode_directly ( c ) )
{
out . push_back ( c ) ;
}
2014-04-28 00:23:19 +00:00
else if ( c < = ( wchar_t ) ASCII_MAX )
2012-11-19 00:30:30 +00:00
{
2014-03-22 21:46:23 +00:00
// See #1225 for discussion of use of ASCII_MAX here
2012-11-19 00:30:30 +00:00
append_format ( out , L " \\ x%.2x " , c ) ;
}
else if ( c < 65536 )
{
append_format ( out , L " \\ u%.4x " , c ) ;
}
else
{
append_format ( out , L " \\ U%.8x " , c ) ;
}
2012-11-18 10:23:22 +00:00
}
2012-11-19 00:30:30 +00:00
return out ;
2006-10-17 21:11:29 +00:00
}
2012-08-05 18:58:17 +00:00
/* Sets the body of a message to the null-terminated list of null terminated const char *. */
void set_body ( message_t * msg , . . . )
{
/* Start by counting the length of all the strings */
size_t body_len = 0 ;
const char * arg ;
va_list arg_list ;
2012-11-19 00:30:30 +00:00
va_start ( arg_list , msg ) ;
while ( ( arg = va_arg ( arg_list , const char * ) ) ! = NULL )
body_len + = strlen ( arg ) ;
va_end ( arg_list ) ;
2012-11-18 10:23:22 +00:00
2012-08-05 18:58:17 +00:00
/* Reserve that length in the string */
msg - > body . reserve ( body_len + 1 ) ; //+1 for trailing NULL? Do I need that?
2012-11-18 10:23:22 +00:00
2012-08-05 18:58:17 +00:00
/* Set the string contents */
2012-11-19 00:30:30 +00:00
va_start ( arg_list , msg ) ;
while ( ( arg = va_arg ( arg_list , const char * ) ) ! = NULL )
msg - > body . append ( arg ) ;
va_end ( arg_list ) ;
2012-08-05 18:58:17 +00:00
}
2006-10-17 21:11:29 +00:00
2012-08-05 18:58:17 +00:00
/* Returns an instance of message_t allocated via new */
2012-11-19 00:30:30 +00:00
message_t * create_message ( fish_message_type_t type ,
2012-08-05 18:58:17 +00:00
const wchar_t * key_in ,
2012-11-19 00:30:30 +00:00
const wchar_t * val_in )
2005-09-20 13:26:39 +00:00
{
2013-02-16 10:38:13 +00:00
char * key = NULL ;
2012-11-18 10:23:22 +00:00
// debug( 4, L"Crete message of type %d", type );
2012-11-19 00:30:30 +00:00
if ( key_in )
2012-11-18 10:23:22 +00:00
{
2012-11-19 00:30:30 +00:00
if ( wcsvarname ( key_in ) )
{
debug ( 0 , L " Illegal variable name: '%ls' " , key_in ) ;
2013-02-16 10:38:13 +00:00
return NULL ;
2012-11-19 00:30:30 +00:00
}
2012-11-18 10:23:22 +00:00
2012-11-19 00:30:30 +00:00
key = wcs2utf ( key_in ) ;
if ( ! key )
{
debug ( 0 ,
2012-08-05 18:58:17 +00:00
L " Could not convert %ls to narrow character string " ,
2012-11-19 00:30:30 +00:00
key_in ) ;
2013-02-16 10:38:13 +00:00
return NULL ;
2012-11-19 00:30:30 +00:00
}
2012-11-18 10:23:22 +00:00
}
2013-02-16 10:38:13 +00:00
message_t * msg = new message_t ;
msg - > count = 0 ;
2012-11-18 10:23:22 +00:00
2012-11-19 00:30:30 +00:00
switch ( type )
{
2012-11-19 08:31:03 +00:00
case SET :
case SET_EXPORT :
2012-11-19 00:30:30 +00:00
{
2012-11-19 08:31:03 +00:00
if ( ! val_in )
{
val_in = L " " ;
}
2012-11-18 10:23:22 +00:00
2012-11-19 08:31:03 +00:00
wcstring esc = full_escape ( val_in ) ;
char * val = wcs2utf ( esc . c_str ( ) ) ;
set_body ( msg , ( type = = SET ? SET_MBS : SET_EXPORT_MBS ) , " " , key , " : " , val , " \n " , NULL ) ;
free ( val ) ;
break ;
}
2012-11-18 10:23:22 +00:00
2012-11-19 08:31:03 +00:00
case ERASE :
{
set_body ( msg , ERASE_MBS , " " , key , " \n " , NULL ) ;
break ;
}
2012-11-18 10:23:22 +00:00
2012-11-19 08:31:03 +00:00
case BARRIER :
{
set_body ( msg , BARRIER_MBS , " \n " , NULL ) ;
break ;
}
2012-11-18 10:23:22 +00:00
2012-11-19 08:31:03 +00:00
case BARRIER_REPLY :
{
set_body ( msg , BARRIER_REPLY_MBS , " \n " , NULL ) ;
break ;
}
2012-11-18 10:23:22 +00:00
2012-11-19 08:31:03 +00:00
default :
{
debug ( 0 , L " create_message: Unknown message type " ) ;
}
2012-11-18 10:23:22 +00:00
}
2012-11-19 00:30:30 +00:00
free ( key ) ;
2012-11-18 10:23:22 +00:00
// debug( 4, L"Message body is '%s'", msg->body );
2012-11-19 00:30:30 +00:00
return msg ;
2005-09-20 13:26:39 +00:00
}
2005-09-22 20:16:52 +00:00
/**
2012-11-18 10:23:22 +00:00
Put exported or unexported variables in a string list
*/
2014-04-25 23:09:26 +00:00
void env_universal_common_get_names ( wcstring_list_t & lst , bool show_exported , bool show_unexported )
2011-12-28 02:41:38 +00:00
{
2014-04-25 23:09:26 +00:00
wcstring_list_t names = s_env_universal_var . get_names ( show_exported , show_unexported ) ;
lst . insert ( lst . end ( ) , names . begin ( ) , names . end ( ) ) ;
2011-12-28 02:41:38 +00:00
}
2014-04-25 23:09:26 +00:00
env_var_t env_universal_common_get ( const wcstring & name )
2005-09-22 20:16:52 +00:00
{
2014-04-25 23:09:26 +00:00
return s_env_universal_var . get ( name ) ;
2005-09-22 20:16:52 +00:00
}
2013-01-19 21:16:21 +00:00
bool env_universal_common_get_export ( const wcstring & name )
2005-09-22 20:16:52 +00:00
{
2014-04-25 23:09:26 +00:00
return s_env_universal_var . get_export ( name ) ;
2005-09-22 20:16:52 +00:00
}
2012-11-19 00:30:30 +00:00
void enqueue_all ( connection_t * c )
2005-09-22 20:16:52 +00:00
{
2014-04-25 23:09:26 +00:00
s_env_universal_var . enqueue_all ( c ) ;
2012-11-19 00:30:30 +00:00
try_send_all ( c ) ;
2005-09-22 20:16:52 +00:00
}
2013-02-16 08:32:15 +00:00
connection_t : : connection_t ( int input_fd ) :
2013-02-16 08:02:40 +00:00
fd ( input_fd ) ,
killme ( false ) ,
2013-02-16 09:28:46 +00:00
buffer_consumed ( 0 )
2006-10-18 16:44:38 +00:00
{
}
2012-11-19 00:30:30 +00:00
void connection_destroy ( connection_t * c )
2006-10-18 16:44:38 +00:00
{
2012-11-19 00:30:30 +00:00
/*
A connection need not always be open - we only try to close it
if it is open .
*/
if ( c - > fd > = 0 )
2012-11-18 10:23:22 +00:00
{
2012-11-19 00:30:30 +00:00
if ( close ( c - > fd ) )
{
wperror ( L " close " ) ;
}
2012-11-18 10:23:22 +00:00
}
2006-10-18 16:44:38 +00:00
}
2014-04-25 23:09:26 +00:00
env_universal_t : : env_universal_t ( )
{
VOMIT_ON_FAILURE ( pthread_mutex_init ( & lock , NULL ) ) ;
}
env_universal_t : : ~ env_universal_t ( )
{
pthread_mutex_destroy ( & lock ) ;
}
env_var_t env_universal_t : : get ( const wcstring & name ) const
{
env_var_t result = env_var_t : : missing_var ( ) ;
var_table_t : : const_iterator where = vars . find ( name ) ;
if ( where ! = vars . end ( ) )
{
result = where - > second . val ;
}
return result ;
}
bool env_universal_t : : get_export ( const wcstring & name ) const
{
bool result = false ;
var_table_t : : const_iterator where = vars . find ( name ) ;
if ( where ! = vars . end ( ) )
{
result = where - > second . exportv ;
}
return result ;
}
void env_universal_t : : set ( const wcstring & key , const wcstring & val , bool exportv )
{
scoped_lock locker ( lock ) ;
var_entry_t * entry = & vars [ key ] ;
entry - > val = val ;
entry - > exportv = exportv ;
}
void env_universal_t : : remove ( const wcstring & key )
{
scoped_lock locker ( lock ) ;
vars . erase ( key ) ;
}
wcstring_list_t env_universal_t : : get_names ( bool show_exported , bool show_unexported ) const
{
wcstring_list_t result ;
scoped_lock locker ( lock ) ;
var_table_t : : const_iterator iter ;
for ( iter = vars . begin ( ) ; iter ! = vars . end ( ) ; + + iter )
{
const wcstring & key = iter - > first ;
const var_entry_t & e = iter - > second ;
if ( ( e . exportv & & show_exported ) | | ( ! e . exportv & & show_unexported ) )
{
result . push_back ( key ) ;
}
}
return result ;
}
void env_universal_t : : enqueue_all ( connection_t * c ) const
{
scoped_lock locker ( lock ) ;
var_table_t : : const_iterator iter ;
for ( iter = vars . begin ( ) ; iter ! = vars . end ( ) ; + + iter )
{
const wcstring & key = iter - > first ;
const var_entry_t & entry = iter - > second ;
message_t * msg = create_message ( entry . exportv ? SET_EXPORT : SET , key . c_str ( ) , entry . val . c_str ( ) ) ;
msg - > count = 1 ;
c - > unsent . push ( msg ) ;
}
}