2005-09-20 23:26:39 +10:00
/**
\ file env_universal_common . c
The utility library for universal variables . Used both by the
client library and by the daemon .
*/
2006-01-31 02:58:00 +10:00
# include "config.h"
2006-02-28 23:17:16 +10:00
2005-09-20 23:26:39 +10:00
# include <stdlib.h>
# include <stdio.h>
# include <wchar.h>
2006-08-10 08:34:52 +10:00
# include <string.h>
2005-09-20 23:26:39 +10: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>
2006-10-18 07:11:29 +10:00
# include <iconv.h>
2005-09-20 23:26:39 +10:00
# include <errno.h>
# include <locale.h>
# include <dirent.h>
# include <signal.h>
# include <sys/stat.h>
2006-08-10 08:26:05 +10:00
# ifdef HAVE_SYS_SELECT_H
# include <sys/select.h>
# endif
2006-02-28 23:17:16 +10:00
# include "fallback.h"
2005-09-20 23:26:39 +10:00
# include "util.h"
2006-02-28 23:17:16 +10:00
2005-09-20 23:26:39 +10:00
# include "common.h"
# include "wutil.h"
# include "env_universal_common.h"
/**
Non - wide version of the set command
*/
# define SET_MBS "SET"
2005-09-23 06:16:52 +10:00
/**
Non - wide version of the set_export command
*/
# define SET_EXPORT_MBS "SET_EXPORT"
2005-09-20 23:26:39 +10:00
/**
Non - wide version of the erase command
*/
# define ERASE_MBS "ERASE"
2005-09-23 06:16:52 +10:00
/**
Non - wide version of the barrier command
*/
2005-09-20 23:26:39 +10:00
# define BARRIER_MBS "BARRIER"
2005-09-23 06:16:52 +10:00
/**
Non - wide version of the barrier_reply command
*/
2005-09-20 23:26:39 +10:00
# define BARRIER_REPLY_MBS "BARRIER_REPLY"
/**
Error message
*/
# define PARSE_ERR L"Unable to parse universal variable message: '%ls'"
2006-10-07 04:45:39 +10: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
2005-09-23 06:16:52 +10:00
/**
A variable entry . Stores the value of a variable and whether it
should be exported . Obviously , it needs to be allocated large
enough to fit the value string .
*/
2005-10-25 01:26:25 +10:00
typedef struct var_uni_entry
2005-09-23 06:16:52 +10:00
{
int export ; /**< Whether the variable should be exported */
wchar_t val [ 0 ] ; /**< The value of the variable */
}
2005-10-25 01:26:25 +10:00
var_uni_entry_t ;
2005-09-23 06:16:52 +10:00
2005-09-21 09:42:00 +10:00
static void parse_message ( wchar_t * msg ,
connection_t * src ) ;
2005-09-20 23:26:39 +10:00
/**
The table of all universal variables
*/
hash_table_t env_universal_var ;
2005-10-25 01:26:25 +10:00
/**
Callback function , should be called on all events
*/
2005-09-21 09:42:00 +10:00
void ( * callback ) ( int type ,
const wchar_t * key ,
const wchar_t * val ) ;
2005-09-20 23:26:39 +10:00
2005-09-23 06:16:52 +10:00
/**
Variable used by env_get_names to communicate auxiliary information
to add_key_to_hash
*/
static int get_names_show_exported ;
/**
Variable used by env_get_names to communicate auxiliary information
to add_key_to_hash
*/
static int get_names_show_unexported ;
2005-09-20 23:26:39 +10:00
2006-10-20 01:39:50 +10:00
wchar_t * utf2wcs ( const char * in )
2006-10-18 07:11:29 +10:00
{
iconv_t cd = ( iconv_t ) - 1 ;
int i , j ;
wchar_t * out ;
char * to_name [ ] =
{
" wchar_t " , " WCHAR_T " , " wchar " , " WCHAR " , 0
}
;
char * from_name [ ] =
{
" utf-8 " , " UTF-8 " , " utf8 " , " UTF8 " , 0
}
;
size_t in_len = strlen ( in ) ;
size_t out_len = sizeof ( wchar_t ) * ( in_len + 1 ) ;
size_t nconv ;
char * nout ;
out = malloc ( out_len ) ;
nout = ( char * ) out ;
if ( ! out )
return 0 ;
for ( i = 0 ; to_name [ i ] ; i + + )
{
for ( j = 0 ; from_name [ j ] ; j + + )
{
cd = iconv_open ( to_name [ i ] , from_name [ j ] ) ;
if ( cd ! = ( iconv_t ) - 1 )
{
goto start_conversion ;
}
}
}
start_conversion :
if ( cd = = ( iconv_t ) - 1 )
{
/* Something went wrong. */
debug ( 0 , L " Could not perform utf-8 conversion " ) ;
if ( errno ! = EINVAL )
wperror ( L " iconv_open " ) ;
/* Terminate the output string. */
free ( out ) ;
return 0 ;
}
2006-10-20 01:39:50 +10:00
nconv = iconv ( cd , ( char * * ) & in , & in_len , & nout , & out_len ) ;
2006-10-18 07:11:29 +10:00
if ( nconv = = ( size_t ) - 1 )
{
debug ( 0 , L " Error while converting from utf string " ) ;
return 0 ;
}
* ( ( wchar_t * ) nout ) = L ' \0 ' ;
if ( iconv_close ( cd ) ! = 0 )
wperror ( L " iconv_close " ) ;
return out ;
}
2006-10-20 01:39:50 +10:00
char * wcs2utf ( const wchar_t * in )
2006-10-18 07:11:29 +10:00
{
iconv_t cd = ( iconv_t ) - 1 ;
int i , j ;
char * char_in = ( char * ) in ;
char * out ;
char * from_name [ ] =
{
" wchar_t " , " WCHAR_T " , " wchar " , " WCHAR " , 0
}
;
char * to_name [ ] =
{
" utf-8 " , " UTF-8 " , " utf8 " , " UTF8 " , 0
}
;
size_t in_len = wcslen ( in ) ;
size_t out_len = sizeof ( char ) * ( ( MAX_UTF8_BYTES * in_len ) + 1 ) ;
size_t nconv ;
char * nout ;
out = malloc ( out_len ) ;
nout = ( char * ) out ;
in_len * = sizeof ( wchar_t ) ;
if ( ! out )
return 0 ;
for ( i = 0 ; to_name [ i ] ; i + + )
{
for ( j = 0 ; from_name [ j ] ; j + + )
{
cd = iconv_open ( to_name [ i ] , from_name [ j ] ) ;
if ( cd ! = ( iconv_t ) - 1 )
{
goto start_conversion ;
}
}
}
start_conversion :
if ( cd = = ( iconv_t ) - 1 )
{
/* Something went wrong. */
debug ( 0 , L " Could not perform utf-8 conversion " ) ;
if ( errno ! = EINVAL )
wperror ( L " iconv_open " ) ;
/* Terminate the output string. */
free ( out ) ;
return 0 ;
}
nconv = iconv ( cd , & char_in , & in_len , & nout , & out_len ) ;
if ( nconv = = ( size_t ) - 1 )
{
debug ( 0 , L " %d %d " , in_len , out_len ) ;
debug ( 0 , L " Error while converting from to string " ) ;
return 0 ;
}
* nout = ' \0 ' ;
if ( iconv_close ( cd ) ! = 0 )
wperror ( L " iconv_close " ) ;
return out ;
}
2005-09-21 09:42:00 +10:00
void env_universal_common_init ( void ( * cb ) ( int type , const wchar_t * key , const wchar_t * val ) )
2005-09-20 23:26:39 +10:00
{
callback = cb ;
hash_init ( & env_universal_var , & hash_wcs_func , & hash_wcs_cmp ) ;
}
2005-10-25 01:26:25 +10:00
/**
Free both key and data
*/
2006-06-13 07:47:42 +10:00
static void erase ( void * key ,
void * data )
2005-09-20 23:26:39 +10:00
{
free ( ( void * ) key ) ;
free ( ( void * ) data ) ;
}
void env_universal_common_destroy ( )
{
hash_foreach ( & env_universal_var , & erase ) ;
hash_destroy ( & env_universal_var ) ;
}
2006-10-07 04:45:39 +10:00
static int read_byte ( connection_t * src )
{
if ( src - > buffer_consumed > = src - > buffer_used )
{
int res ;
res = read ( src - > fd , src - > buffer , ENV_UNIVERSAL_BUFFER_SIZE ) ;
2006-10-11 08:21:13 +10:00
// debug(4, L"Read chunk '%.*s'", res, src->buffer );
2006-10-07 04:45:39 +10:00
if ( res < 0 )
{
if ( errno = = EAGAIN | |
errno = = EINTR )
{
return ENV_UNIVERSAL_AGAIN ;
}
return ENV_UNIVERSAL_ERROR ;
}
if ( res = = 0 )
{
return ENV_UNIVERSAL_EOF ;
}
src - > buffer_consumed = 0 ;
src - > buffer_used = res ;
}
return src - > buffer [ src - > buffer_consumed + + ] ;
}
2005-09-20 23:26:39 +10:00
void read_message ( connection_t * src )
{
while ( 1 )
{
2006-10-07 04:45:39 +10:00
int ib = read_byte ( src ) ;
char b ;
switch ( ib )
2005-09-20 23:26:39 +10:00
{
2006-10-07 04:45:39 +10:00
case ENV_UNIVERSAL_AGAIN :
{
return ;
}
case ENV_UNIVERSAL_ERROR :
2005-09-20 23:26:39 +10:00
{
debug ( 2 , L " Read error on fd %d, set killme flag " , src - > fd ) ;
2006-10-23 02:03:29 +10:00
if ( debug_level > 2 )
wperror ( L " read " ) ;
2005-09-20 23:26:39 +10:00
src - > killme = 1 ;
2006-10-07 04:45:39 +10:00
return ;
2005-09-20 23:26:39 +10:00
}
2006-10-07 04:45:39 +10:00
case ENV_UNIVERSAL_EOF :
2005-09-20 23:26:39 +10:00
{
2006-10-07 04:45:39 +10:00
src - > killme = 1 ;
debug ( 3 , L " Fd %d has reached eof, set killme flag " , src - > fd ) ;
if ( src - > input . used > 0 )
{
2006-10-18 07:11:29 +10:00
char c = 0 ;
b_append ( & src - > input , & c , 1 ) ;
2006-10-07 04:45:39 +10:00
debug ( 1 ,
2006-10-18 07:11:29 +10:00
L " Universal variable connection closed while reading command. Partial command recieved: '%s' " ,
2006-10-07 04:45:39 +10:00
( wchar_t * ) src - > input . buff ) ;
}
return ;
2005-09-20 23:26:39 +10:00
}
}
2006-10-07 04:45:39 +10:00
b = ( char ) ib ;
2006-10-18 07:11:29 +10:00
if ( b = = ' \n ' )
2005-09-20 23:26:39 +10:00
{
2006-10-18 07:11:29 +10:00
wchar_t * msg ;
b = 0 ;
b_append ( & src - > input , & b , 1 ) ;
msg = utf2wcs ( src - > input . buff ) ;
/*
Before calling parse_message , we must empty reset
everything , since the callback function could
potentially call read_message .
*/
src - > input . used = 0 ;
if ( msg )
2005-09-20 23:26:39 +10:00
{
2005-10-12 05:23:43 +10:00
parse_message ( msg , src ) ;
2005-09-20 23:26:39 +10:00
}
else
{
2006-10-18 07:11:29 +10:00
debug ( 0 , _ ( L " Could not convert message '%s' to wide character string " ) , src - > input . buff ) ;
2005-09-20 23:26:39 +10:00
}
2006-10-18 07:11:29 +10:00
free ( msg ) ;
}
else
{
b_append ( & src - > input , & b , 1 ) ;
2005-09-20 23:26:39 +10:00
}
}
}
2005-10-25 01:26:25 +10:00
/**
Remove variable with specified name
*/
2005-09-20 23:26:39 +10:00
static void remove_entry ( wchar_t * name )
{
void * k , * v ;
hash_remove ( & env_universal_var ,
name ,
2006-06-13 07:47:42 +10:00
& k ,
& v ) ;
2005-09-20 23:26:39 +10:00
free ( k ) ;
free ( v ) ;
}
2005-10-25 01:26:25 +10:00
/**
Test if the message msg contains the command cmd
*/
2005-09-20 23:26:39 +10:00
static int match ( const wchar_t * msg , const wchar_t * cmd )
{
size_t len = wcslen ( cmd ) ;
if ( wcsncasecmp ( msg , cmd , len ) ! = 0 )
return 0 ;
2005-09-23 06:16:52 +10:00
2005-09-20 23:26:39 +10:00
if ( msg [ len ] & & msg [ len ] ! = L ' ' & & msg [ len ] ! = L ' \t ' )
return 0 ;
return 1 ;
}
2005-10-25 01:26:25 +10:00
/**
Parse message msg
*/
2005-09-21 09:42:00 +10:00
static void parse_message ( wchar_t * msg ,
connection_t * src )
2005-09-20 23:26:39 +10:00
{
2006-10-11 08:21:13 +10:00
// debug( 3, L"parse_message( %ls );", msg );
2005-10-12 05:23:43 +10:00
2005-09-20 23:26:39 +10:00
if ( msg [ 0 ] = = L ' # ' )
return ;
2005-09-23 06:16:52 +10:00
if ( match ( msg , SET_STR ) | | match ( msg , SET_EXPORT_STR ) )
2005-09-20 23:26:39 +10:00
{
wchar_t * name , * val , * tmp ;
2005-09-23 06:16:52 +10:00
int export = match ( msg , SET_EXPORT_STR ) ;
name = msg + ( export ? wcslen ( SET_EXPORT_STR ) : wcslen ( SET_STR ) ) ;
2005-09-20 23:26:39 +10:00
while ( wcschr ( L " \t " , * name ) )
name + + ;
tmp = wcschr ( name , L ' : ' ) ;
if ( tmp )
{
wchar_t * key = malloc ( sizeof ( wchar_t ) * ( tmp - name + 1 ) ) ;
memcpy ( key , name , sizeof ( wchar_t ) * ( tmp - name ) ) ;
key [ tmp - name ] = 0 ;
val = tmp + 1 ;
2005-10-07 20:36:51 +10:00
val = unescape ( val , 0 ) ;
2005-09-20 23:26:39 +10:00
2005-10-25 01:26:25 +10:00
var_uni_entry_t * entry =
malloc ( sizeof ( var_uni_entry_t ) + sizeof ( wchar_t ) * ( wcslen ( val ) + 1 ) ) ;
2005-09-23 06:16:52 +10:00
if ( ! entry )
2006-07-03 20:39:57 +10:00
DIE_MEM ( ) ;
2005-09-23 06:16:52 +10:00
entry - > export = export ;
wcscpy ( entry - > val , val ) ;
2005-09-20 23:26:39 +10:00
remove_entry ( key ) ;
2005-09-23 06:16:52 +10:00
hash_put ( & env_universal_var , key , entry ) ;
2005-09-20 23:26:39 +10:00
if ( callback )
{
2005-09-23 06:16:52 +10:00
callback ( export ? SET_EXPORT : SET , key , val ) ;
2005-09-20 23:26:39 +10:00
}
2005-09-23 06:16:52 +10:00
free ( val ) ;
2005-09-20 23:26:39 +10:00
}
else
{
debug ( 1 , PARSE_ERR , msg ) ;
}
}
else if ( match ( msg , ERASE_STR ) )
{
2005-09-23 06:16:52 +10:00
wchar_t * name , * tmp ;
2005-09-20 23:26:39 +10:00
name = msg + wcslen ( ERASE_STR ) ;
while ( wcschr ( L " \t " , * name ) )
name + + ;
tmp = name ;
while ( iswalnum ( * tmp ) | | * tmp = = L ' _ ' )
tmp + + ;
* tmp = 0 ;
if ( ! wcslen ( name ) )
{
debug ( 1 , PARSE_ERR , msg ) ;
}
remove_entry ( name ) ;
if ( callback )
{
callback ( ERASE , name , 0 ) ;
}
}
else if ( match ( msg , BARRIER_STR ) )
{
message_t * msg = create_message ( BARRIER_REPLY , 0 , 0 ) ;
msg - > count = 1 ;
q_put ( & src - > unsent , msg ) ;
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-10-25 01:26:25 +10: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
*/
static int try_send ( message_t * msg ,
int fd )
2005-09-20 23:26:39 +10:00
{
2005-09-23 06:16:52 +10:00
debug ( 3 ,
L " before write of %d chars to fd %d " , strlen ( msg - > body ) , fd ) ;
2005-09-20 23:26:39 +10:00
int res = write ( fd , msg - > body , strlen ( msg - > body ) ) ;
2006-10-11 08:21:13 +10:00
if ( res ! = - 1 )
{
debug ( 4 , L " Wrote message '%s' " , msg - > body ) ;
}
else
{
debug ( 4 , L " Failed to write message '%s' " , msg - > body ) ;
}
2005-09-20 23:26:39 +10:00
if ( res = = - 1 )
{
switch ( errno )
{
case EAGAIN :
return 0 ;
default :
2006-10-23 02:03:29 +10:00
debug ( 2 ,
2005-09-23 23:10:31 +10:00
L " Error while sending universal variable message to fd %d. Closing connection " ,
2005-09-20 23:26:39 +10:00
fd ) ;
2006-10-23 02:03:29 +10:00
if ( debug_level > 2 )
wperror ( L " write " ) ;
2005-09-20 23:26:39 +10:00
return - 1 ;
}
}
msg - > count - - ;
if ( ! msg - > count )
{
free ( msg ) ;
}
return 1 ;
}
void try_send_all ( connection_t * c )
{
2006-10-11 08:21:13 +10:00
/* debug( 3,
2005-09-20 23:26:39 +10:00
L " Send all updates to connection on fd %d " ,
2006-10-11 08:21:13 +10:00
c - > fd ) ; */
2005-09-20 23:26:39 +10:00
while ( ! q_empty ( & c - > unsent ) )
{
switch ( try_send ( ( message_t * ) q_peek ( & c - > unsent ) , c - > fd ) )
{
case 1 :
q_get ( & c - > unsent ) ;
break ;
case 0 :
2006-10-11 08:21:13 +10:00
debug ( 4 ,
2005-09-23 06:16:52 +10:00
L " Socket full, send rest later " ) ;
2005-09-20 23:26:39 +10:00
return ;
case - 1 :
c - > killme = 1 ;
return ;
}
}
}
2006-10-18 07:11:29 +10:00
static wchar_t * full_escape ( const wchar_t * in )
{
string_buffer_t out ;
sb_init ( & out ) ;
for ( ; * in ; in + + )
{
if ( * in < 32 )
{
sb_printf ( & out , L " \\ x%.2x " , * in ) ;
}
else if ( * in < 128 )
{
sb_append_char ( & out , * in ) ;
}
else if ( * in < 65536 )
{
sb_printf ( & out , L " \\ u%.4x " , * in ) ;
}
else
{
sb_printf ( & out , L " \\ U%.8x " , * in ) ;
}
}
return ( wchar_t * ) out . buff ;
}
2005-09-20 23:26:39 +10:00
message_t * create_message ( int type ,
const wchar_t * key_in ,
const wchar_t * val_in )
{
message_t * msg = 0 ;
char * key = 0 ;
size_t sz ;
2006-10-11 08:21:13 +10:00
// debug( 4, L"Crete message of type %d", type );
2005-09-20 23:26:39 +10:00
if ( key_in )
{
2006-10-18 07:11:29 +10:00
if ( wcsvarname ( key_in ) )
{
debug ( 0 , L " Illegal variable name: '%ls' " , key_in ) ;
return 0 ;
}
key = wcs2utf ( key_in ) ;
2005-09-20 23:26:39 +10:00
if ( ! key )
{
debug ( 0 ,
L " Could not convert %ls to narrow character string " ,
key_in ) ;
return 0 ;
}
}
switch ( type )
{
case SET :
2005-09-23 06:16:52 +10:00
case SET_EXPORT :
2005-09-20 23:26:39 +10:00
{
if ( ! val_in )
{
val_in = L " " ;
}
2006-10-18 07:11:29 +10:00
wchar_t * esc = full_escape ( val_in ) ;
2005-09-20 23:26:39 +10:00
if ( ! esc )
break ;
2006-10-18 07:11:29 +10:00
char * val = wcs2utf ( esc ) ;
2005-09-20 23:26:39 +10:00
free ( esc ) ;
2005-09-23 06:16:52 +10:00
sz = strlen ( type = = SET ? SET_MBS : SET_EXPORT_MBS ) + strlen ( key ) + strlen ( val ) + 4 ;
2005-09-20 23:26:39 +10:00
msg = malloc ( sizeof ( message_t ) + sz ) ;
2005-09-23 06:16:52 +10:00
2005-09-20 23:26:39 +10:00
if ( ! msg )
2006-07-03 20:39:57 +10:00
DIE_MEM ( ) ;
2005-09-23 06:16:52 +10:00
strcpy ( msg - > body , ( type = = SET ? SET_MBS : SET_EXPORT_MBS ) ) ;
strcat ( msg - > body , " " ) ;
2005-09-20 23:26:39 +10:00
strcat ( msg - > body , key ) ;
strcat ( msg - > body , " : " ) ;
strcat ( msg - > body , val ) ;
strcat ( msg - > body , " \n " ) ;
2005-09-23 06:16:52 +10:00
2005-09-20 23:26:39 +10:00
free ( val ) ;
break ;
}
case ERASE :
{
sz = strlen ( ERASE_MBS ) + strlen ( key ) + 3 ;
msg = malloc ( sizeof ( message_t ) + sz ) ;
if ( ! msg )
2006-07-03 20:39:57 +10:00
DIE_MEM ( ) ;
2005-09-20 23:26:39 +10:00
strcpy ( msg - > body , ERASE_MBS " " ) ;
strcat ( msg - > body , key ) ;
strcat ( msg - > body , " \n " ) ;
break ;
}
case BARRIER :
{
msg = malloc ( sizeof ( message_t ) +
strlen ( BARRIER_MBS ) + 2 ) ;
if ( ! msg )
2006-07-03 20:39:57 +10:00
DIE_MEM ( ) ;
2005-09-20 23:26:39 +10:00
strcpy ( msg - > body , BARRIER_MBS " \n " ) ;
break ;
}
case BARRIER_REPLY :
{
msg = malloc ( sizeof ( message_t ) +
strlen ( BARRIER_REPLY_MBS ) + 2 ) ;
if ( ! msg )
2006-07-03 20:39:57 +10:00
DIE_MEM ( ) ;
2005-09-20 23:26:39 +10:00
strcpy ( msg - > body , BARRIER_REPLY_MBS " \n " ) ;
break ;
}
default :
{
debug ( 0 , L " create_message: Unknown message type " ) ;
}
}
free ( key ) ;
if ( msg )
msg - > count = 0 ;
2006-10-11 08:21:13 +10:00
// debug( 4, L"Message body is '%s'", msg->body );
2005-09-20 23:26:39 +10:00
return msg ;
}
2005-09-23 06:16:52 +10:00
/**
Function used with hash_foreach to insert keys of one table into
another
*/
2006-06-13 07:47:42 +10:00
static void add_key_to_hash ( void * key ,
void * data ,
2005-09-23 06:16:52 +10:00
void * aux )
{
2005-10-25 01:26:25 +10:00
var_uni_entry_t * e = ( var_uni_entry_t * ) data ;
2005-09-23 06:16:52 +10:00
if ( ( e - > export & & get_names_show_exported ) | |
( ! e - > export & & get_names_show_unexported ) )
al_push ( ( array_list_t * ) aux , key ) ;
}
void env_universal_common_get_names ( array_list_t * l ,
int show_exported ,
int show_unexported )
{
get_names_show_exported = show_exported ;
get_names_show_unexported = show_unexported ;
hash_foreach2 ( & env_universal_var ,
add_key_to_hash ,
l ) ;
}
wchar_t * env_universal_common_get ( const wchar_t * name )
{
2005-10-25 01:26:25 +10:00
var_uni_entry_t * e = ( var_uni_entry_t * ) hash_get ( & env_universal_var , name ) ;
2005-09-23 06:16:52 +10:00
if ( e )
return e - > val ;
return 0 ;
}
int env_universal_common_get_export ( const wchar_t * name )
{
2005-10-25 01:26:25 +10:00
var_uni_entry_t * e = ( var_uni_entry_t * ) hash_get ( & env_universal_var , name ) ;
2005-09-23 06:16:52 +10:00
if ( e )
return e - > export ;
return 0 ;
}
2005-10-25 01:26:25 +10:00
/**
Adds a variable creation message about the specified variable to
the specified queue . The function signature is non - obvious since
this function is used together with hash_foreach2 , which requires
the specified function signature .
\ param k the variable name
\ param v the variable value
\ param q the queue to add the message to
*/
2006-06-13 07:47:42 +10:00
static void enqueue ( void * k ,
void * v ,
2005-09-23 06:16:52 +10:00
void * q )
{
const wchar_t * key = ( const wchar_t * ) k ;
2005-10-25 01:26:25 +10:00
const var_uni_entry_t * val = ( const var_uni_entry_t * ) v ;
2005-10-11 02:12:55 +10:00
dyn_queue_t * queue = ( dyn_queue_t * ) q ;
2005-09-23 06:16:52 +10:00
message_t * msg = create_message ( val - > export ? SET_EXPORT : SET , key , val - > val ) ;
msg - > count = 1 ;
q_put ( queue , msg ) ;
}
void enqueue_all ( connection_t * c )
{
hash_foreach2 ( & env_universal_var ,
& enqueue ,
( void * ) & c - > unsent ) ;
try_send_all ( c ) ;
}
2006-10-19 02:44:38 +10:00
void connection_init ( connection_t * c , int fd )
{
memset ( c , 0 , sizeof ( connection_t ) ) ;
c - > fd = fd ;
b_init ( & c - > input ) ;
q_init ( & c - > unsent ) ;
c - > buffer_consumed = c - > buffer_used = 0 ;
}
void connection_destroy ( connection_t * c )
{
q_destroy ( & c - > unsent ) ;
b_destroy ( & c - > input ) ;
if ( close ( c - > fd ) )
{
wperror ( L " close " ) ;
}
}