2005-09-20 23:26:39 +10:00
/** \file env.c
Functions for setting and getting environment variables .
*/
2005-10-05 19:58:00 +10:00
# include "config.h"
2005-09-20 23:26:39 +10:00
# include <stdlib.h>
# include <wchar.h>
# include <string.h>
# include <stdio.h>
# include <locale.h>
# include <unistd.h>
# include <signal.h>
# include <sys/types.h>
# include <sys/stat.h>
2011-12-26 19:18:46 -08:00
# include <pthread.h>
2005-09-20 23:26:39 +10:00
# include <pwd.h>
2011-12-26 19:18:46 -08:00
# include <set>
# include <map>
2005-09-20 23:26:39 +10:00
# if HAVE_NCURSES_H
# include <ncurses.h>
# else
# include <curses.h>
# endif
# if HAVE_TERMIO_H
# include <termio.h>
# endif
2006-01-19 22:22:07 +10:00
# if HAVE_TERM_H
2005-09-20 23:26:39 +10:00
# include <term.h>
2006-01-19 22:22:07 +10:00
# elif HAVE_NCURSES_TERM_H
# include <ncurses/term.h>
# endif
2006-07-20 09:11:49 +10:00
# if HAVE_LIBINTL_H
# include <libintl.h>
# endif
2005-10-22 20:06:05 +10:00
# include <errno.h>
2005-09-20 23:26:39 +10:00
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 "wutil.h"
# include "proc.h"
# include "common.h"
# include "env.h"
# include "sanity.h"
# include "expand.h"
# include "history.h"
# include "reader.h"
# include "parser.h"
# include "env_universal.h"
2005-09-27 00:47:03 +10:00
# include "input_common.h"
2005-10-06 08:37:08 +10:00
# include "event.h"
2007-05-11 05:11:28 +10:00
# include "path.h"
# include "halloc.h"
# include "halloc_util.h"
2006-07-20 08:55:49 +10:00
2006-01-13 11:00:12 +10:00
# include "complete.h"
2005-09-20 23:26:39 +10:00
/**
Command used to start fishd
*/
2006-10-19 02:44:38 +10:00
# define FISHD_CMD L"fishd ^ / tmp / fishd.log.%s"
2005-09-20 23:26:39 +10:00
2005-10-25 01:26:25 +10:00
/**
Value denoting a null string
*/
2005-09-27 00:47:03 +10:00
# define ENV_NULL L"\x1d"
2005-09-20 23:26:39 +10:00
/**
2007-01-28 02:59:11 +10:00
At init , we read all the environment variables from this array .
2005-09-20 23:26:39 +10:00
*/
extern char * * environ ;
2007-01-28 02:59:11 +10:00
/**
This should be the same thing as \ c environ , but it is possible only one of the two work . . .
*/
extern char * * __environ ;
2005-09-20 23:26:39 +10:00
/**
Struct representing one level in the function variable stack
*/
typedef struct env_node
{
2011-12-26 19:18:46 -08:00
/**
Variable table
2005-09-20 23:26:39 +10:00
*/
hash_table_t env ;
2011-12-26 19:18:46 -08:00
/**
2005-09-20 23:26:39 +10:00
Does this node imply a new variable scope ? If yes , all
non - global variables below this one in the stack are
invisible . If new_scope is set for the global variable node ,
the universe will explode .
*/
int new_scope ;
/**
Does this node contain any variables which are exported to subshells
*/
2011-12-26 19:18:46 -08:00
int exportv ;
/**
2005-09-20 23:26:39 +10:00
Pointer to next level
*/
struct env_node * next ;
}
2005-10-06 08:37:08 +10:00
env_node_t ;
2005-09-20 23:26:39 +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 .
*/
typedef struct var_entry
{
2011-12-26 19:18:46 -08:00
int exportv ; /**< Whether the variable should be exported */
2007-01-19 02:29:22 +10:00
size_t size ; /**< The maximum length (excluding the NULL) that will fit into this var_entry_t */
2011-12-26 19:18:46 -08:00
2006-06-14 03:22:51 +10:00
# if __STDC_VERSION__ < 199901L
2006-04-11 02:01:09 +10:00
wchar_t val [ 1 ] ; /**< The value of the variable */
2006-06-14 03:22:51 +10:00
# else
wchar_t val [ ] ; /**< The value of the variable */
# endif
2005-09-20 23:26:39 +10:00
}
2005-10-06 08:37:08 +10:00
var_entry_t ;
2005-09-20 23:26:39 +10:00
2011-12-26 19:18:46 -08:00
class variable_entry_t {
bool exportv ; /**< Whether the variable should be exported */
wcstring value ; /**< Value of the variable */
} ;
static pthread_mutex_t env_lock = PTHREAD_MUTEX_INITIALIZER ;
2005-09-20 23:26:39 +10:00
/**
Top node on the function stack
*/
static env_node_t * top = 0 ;
/**
Bottom node on the function stack
*/
static env_node_t * global_env = 0 ;
/**
Table for global variables
*/
static hash_table_t * global ;
/**
Table of variables that may not be set using the set command .
*/
2011-12-26 19:18:46 -08:00
static std : : set < wcstring > env_read_only ;
static bool is_read_only ( const wcstring & key )
{
return env_read_only . find ( key ) ! = env_read_only . end ( ) ;
}
2005-09-20 23:26:39 +10:00
2005-10-23 22:14:29 +10:00
/**
Table of variables whose value is dynamically calculated , such as umask , status , etc
*/
2011-12-26 19:18:46 -08:00
static std : : set < wcstring > env_electric ;
static bool is_electric ( const wcstring & key )
{
return env_electric . find ( key ) ! = env_electric . end ( ) ;
}
2005-10-23 22:14:29 +10:00
2005-09-20 23:26:39 +10:00
/**
Exported variable array used by execv
*/
static char * * export_arr = 0 ;
2005-09-23 06:16:52 +10:00
/**
Buffer used for storing string contents for export_arr
*/
static buffer_t export_buffer ;
2005-09-20 23:26:39 +10:00
/**
Flag for checking if we need to regenerate the exported variable
array
*/
static int has_changed = 1 ;
/**
This stringbuffer is used to store the value of dynamically
generated variables , such as history .
*/
static string_buffer_t dyn_var ;
/**
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 ;
2006-01-22 06:42:17 +10:00
/**
List of all locale variable names
*/
static const wchar_t * locale_variable [ ] =
{
L " LANG " ,
L " LC_ALL " ,
L " LC_COLLATE " ,
L " LC_CTYPE " ,
L " LC_MESSAGES " ,
L " LC_MONETARY " ,
L " LC_NUMERIC " ,
L " LC_TIME " ,
2011-12-26 19:18:46 -08:00
NULL
2006-01-22 06:42:17 +10:00
}
;
/**
Free hash key and hash value
*/
2006-06-13 07:47:42 +10:00
static void clear_hash_entry ( void * key , void * data )
2006-01-22 06:42:17 +10:00
{
2011-12-26 19:18:46 -08:00
var_entry_t * entry = ( var_entry_t * ) data ;
if ( entry - > exportv )
2007-01-22 01:01:14 +10:00
{
2006-01-22 06:42:17 +10:00
has_changed = 1 ;
2007-01-22 01:01:14 +10:00
}
2011-12-26 19:18:46 -08:00
2006-01-22 06:42:17 +10:00
free ( ( void * ) key ) ;
free ( ( void * ) data ) ;
}
2005-09-20 23:26:39 +10:00
/**
When fishd isn ' t started , this function is provided to
2005-10-03 23:09:37 +10:00
env_universal as a callback , it tries to start up fishd . It ' s
implementation is a bit of a hack , since it evaluates a bit of
shellscript , and it might be used at times when that might not be
the best idea .
2005-09-20 23:26:39 +10:00
*/
static void start_fishd ( )
{
string_buffer_t cmd ;
struct passwd * pw ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
sb_init ( & cmd ) ;
pw = getpwuid ( getuid ( ) ) ;
2011-12-26 19:18:46 -08:00
2005-11-29 20:13:03 +10:00
debug ( 3 , L " Spawning new copy of fishd " ) ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
if ( ! pw )
{
2006-01-04 22:51:02 +10:00
debug ( 0 , _ ( L " Could not get user information " ) ) ;
2005-09-20 23:26:39 +10:00
return ;
}
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
sb_printf ( & cmd , FISHD_CMD , pw - > pw_name ) ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
eval ( ( wchar_t * ) cmd . buff ,
0 ,
TOP ) ;
sb_destroy ( & cmd ) ;
}
2005-10-23 22:14:29 +10:00
/**
Return the current umask value .
*/
static mode_t get_umask ( )
{
mode_t res ;
res = umask ( 0 ) ;
umask ( res ) ;
return res ;
}
2006-01-09 09:00:49 +10:00
/**
Checks if the specified variable is a locale variable
*/
static int is_locale ( const wchar_t * key )
{
2006-01-13 11:00:12 +10:00
int i ;
for ( i = 0 ; locale_variable [ i ] ; i + + )
2007-01-22 01:01:14 +10:00
{
2006-01-13 11:00:12 +10:00
if ( wcscmp ( locale_variable [ i ] , key ) = = 0 )
2007-01-22 01:01:14 +10:00
{
2006-01-13 11:00:12 +10:00
return 1 ;
2007-01-22 01:01:14 +10:00
}
}
2006-01-13 11:00:12 +10:00
return 0 ;
2006-01-09 09:00:49 +10:00
}
/**
Properly sets all locale information
*/
static void handle_locale ( )
{
2012-01-12 03:57:38 +05:30
const wcstring lc_all = env_get_string ( L " LC_ALL " ) ;
wcstring lang ;
2006-01-09 09:00:49 +10:00
int i ;
2011-12-26 19:18:46 -08:00
wchar_t * old = wcsdup ( wsetlocale ( LC_MESSAGES , NULL ) ) ;
2006-01-13 11:00:12 +10:00
/*
Array of locale constants corresponding to the local variable names defined in locale_variable
*/
2011-12-26 19:18:46 -08:00
static const int cat [ ] =
2006-01-09 09:00:49 +10:00
{
2011-12-26 19:18:46 -08:00
0 ,
LC_ALL ,
2006-01-22 06:42:17 +10:00
LC_COLLATE ,
LC_CTYPE ,
LC_MESSAGES ,
LC_MONETARY ,
LC_NUMERIC ,
LC_TIME
2006-01-09 09:00:49 +10:00
}
;
2011-12-26 19:18:46 -08:00
2012-01-12 03:57:38 +05:30
if ( ! lc_all . empty ( ) )
2006-01-09 09:00:49 +10:00
{
2012-01-12 03:57:38 +05:30
wsetlocale ( LC_ALL , lc_all . c_str ( ) ) ;
2006-01-09 09:00:49 +10:00
}
else
{
2012-01-12 03:57:38 +05:30
lang = env_get_string ( L " LANG " ) ;
if ( ! lang . empty ( ) )
2006-01-09 09:00:49 +10:00
{
2012-01-12 03:57:38 +05:30
wsetlocale ( LC_ALL , lang . c_str ( ) ) ;
2006-01-09 09:00:49 +10:00
}
2011-12-26 19:18:46 -08:00
2006-01-13 11:00:12 +10:00
for ( i = 2 ; locale_variable [ i ] ; i + + )
2006-01-09 09:00:49 +10:00
{
2012-01-12 03:57:38 +05:30
const wcstring val = env_get_string ( locale_variable [ i ] ) ;
2007-01-22 01:01:14 +10:00
2012-01-12 03:57:38 +05:30
if ( ! val . empty ( ) )
2007-01-22 01:01:14 +10:00
{
2012-01-12 03:57:38 +05:30
wsetlocale ( cat [ i ] , val . c_str ( ) ) ;
2007-01-22 01:01:14 +10:00
}
2006-01-09 09:00:49 +10:00
}
}
2011-12-26 19:18:46 -08:00
if ( wcscmp ( wsetlocale ( LC_MESSAGES , NULL ) , old ) ! = 0 )
2006-01-09 09:00:49 +10:00
{
2006-01-22 02:02:34 +10:00
2011-12-26 19:18:46 -08:00
/*
2006-07-20 09:11:49 +10:00
Try to make change known to gettext . Both changing
_nl_msg_cat_cntr and calling dcgettext might potentially
tell some gettext implementation that the translation
strings should be reloaded . We do both and hope for the
best .
*/
2007-01-22 01:01:14 +10:00
2006-07-20 09:11:49 +10:00
extern int _nl_msg_cat_cntr ;
2007-01-22 01:01:14 +10:00
_nl_msg_cat_cntr + + ;
2006-07-20 09:11:49 +10:00
dcgettext ( " fish " , " Changing language to English " , LC_MESSAGES ) ;
2011-12-26 19:18:46 -08:00
2006-01-09 09:00:49 +10:00
if ( is_interactive )
{
2006-01-21 12:53:07 +10:00
debug ( 0 , _ ( L " Changing language to English " ) ) ;
2006-01-09 09:00:49 +10:00
}
}
free ( old ) ;
2011-12-26 19:18:46 -08:00
2006-01-09 09:00:49 +10:00
}
2005-10-23 22:14:29 +10:00
/**
Universal variable callback function . This function makes sure the
proper events are triggered when an event occurs .
*/
2005-10-12 05:23:43 +10:00
static void universal_callback ( int type ,
2011-12-26 19:18:46 -08:00
const wchar_t * name ,
2005-10-12 05:23:43 +10:00
const wchar_t * val )
{
2011-12-26 19:18:46 -08:00
const wchar_t * str = 0 ;
2006-01-09 09:00:49 +10:00
if ( is_locale ( name ) )
2007-01-22 01:01:14 +10:00
{
2006-01-09 09:00:49 +10:00
handle_locale ( ) ;
2007-01-22 01:01:14 +10:00
}
2011-12-26 19:18:46 -08:00
2005-10-12 05:23:43 +10:00
switch ( type )
{
case SET :
case SET_EXPORT :
2007-01-22 01:01:14 +10:00
{
2005-10-12 05:23:43 +10:00
str = L " SET " ;
break ;
2007-01-22 01:01:14 +10:00
}
2011-12-26 19:18:46 -08:00
2005-10-12 05:23:43 +10:00
case ERASE :
2007-01-22 01:01:14 +10:00
{
2005-10-12 05:23:43 +10:00
str = L " ERASE " ;
break ;
2007-01-22 01:01:14 +10:00
}
2005-10-12 05:23:43 +10:00
}
2011-12-26 19:18:46 -08:00
2005-10-12 05:23:43 +10:00
if ( str )
{
event_t ev ;
2011-12-26 19:18:46 -08:00
2005-10-12 05:23:43 +10:00
has_changed = 1 ;
2011-12-26 19:18:46 -08:00
2005-10-12 05:23:43 +10:00
ev . type = EVENT_VARIABLE ;
2005-10-12 05:31:16 +10:00
ev . param1 . variable = name ;
2005-10-12 05:23:43 +10:00
ev . function_name = 0 ;
2011-12-26 19:18:46 -08:00
2011-12-27 00:06:07 -08:00
ev . arguments = new wcstring_list_t ( ) ;
ev . arguments - > push_back ( L " VARIABLE " ) ;
ev . arguments - > push_back ( str ) ;
ev . arguments - > push_back ( name ) ;
event_fire ( & ev ) ;
delete ev . arguments ;
ev . arguments = NULL ;
2005-10-12 05:23:43 +10:00
}
}
2006-01-22 06:42:17 +10:00
/**
Make sure the PATH variable contains the essaential directories
*/
static void setup_path ( )
{
2012-01-12 03:57:38 +05:30
wcstring path ;
2011-12-26 19:18:46 -08:00
2011-12-27 18:41:38 -08:00
size_t i ;
int j ;
wcstring_list_t lst ;
2006-01-22 06:42:17 +10:00
2011-12-26 19:18:46 -08:00
const wchar_t * path_el [ ] =
2006-01-22 06:42:17 +10:00
{
L " /bin " ,
L " /usr/bin " ,
PREFIX L " /bin " ,
0
}
;
2012-01-12 03:57:38 +05:30
path = env_get_string ( L " PATH " ) ;
2011-12-26 19:18:46 -08:00
2012-01-12 03:57:38 +05:30
if ( ! path . empty ( ) )
2007-01-22 01:01:14 +10:00
{
2011-12-27 18:41:38 -08:00
tokenize_variable_array2 ( path , lst ) ;
2007-01-22 01:01:14 +10:00
}
2011-12-26 19:18:46 -08:00
2006-01-22 06:42:17 +10:00
for ( j = 0 ; path_el [ j ] ; j + + )
{
2007-01-22 01:01:14 +10:00
2006-01-22 06:42:17 +10:00
int has_el = 0 ;
2011-12-26 19:18:46 -08:00
2011-12-27 18:41:38 -08:00
for ( i = 0 ; i < lst . size ( ) ; i + + )
2006-01-22 06:42:17 +10:00
{
2011-12-27 18:41:38 -08:00
wcstring el = lst . at ( i ) ;
size_t len = el . size ( ) ;
2007-01-22 01:01:14 +10:00
2006-01-22 06:42:17 +10:00
while ( ( len > 0 ) & & ( el [ len - 1 ] = = L ' / ' ) )
2007-01-22 01:01:14 +10:00
{
2006-01-22 06:42:17 +10:00
len - - ;
2007-01-22 01:01:14 +10:00
}
2011-12-26 19:18:46 -08:00
if ( ( wcslen ( path_el [ j ] ) = = len ) & &
2011-12-27 18:41:38 -08:00
( wcsncmp ( el . c_str ( ) , path_el [ j ] , len ) = = 0 ) )
2006-01-22 06:42:17 +10:00
{
has_el = 1 ;
}
}
2011-12-26 19:18:46 -08:00
2006-01-22 06:42:17 +10:00
if ( ! has_el )
{
2011-12-27 18:41:38 -08:00
wcstring buffer ;
2006-01-22 06:42:17 +10:00
debug ( 3 , L " directory %ls was missing " , path_el [ j ] ) ;
2012-01-12 03:57:38 +05:30
if ( ! path . empty ( ) )
2006-01-22 06:42:17 +10:00
{
2012-01-12 03:57:38 +05:30
buffer + = path ;
2006-01-22 06:42:17 +10:00
}
2011-12-26 19:18:46 -08:00
2012-01-12 03:57:38 +05:30
buffer + = ARRAY_SEP_STR ;
buffer + = path_el [ j ] ;
2011-12-26 19:18:46 -08:00
2012-01-12 03:57:38 +05:30
env_set ( L " PATH " , buffer . empty ( ) ? NULL : buffer . c_str ( ) , ENV_GLOBAL | ENV_EXPORT ) ;
2011-12-27 18:41:38 -08:00
2012-01-12 03:57:38 +05:30
path = env_get_string ( L " PATH " ) ;
lst . resize ( 0 ) ;
2011-12-27 18:41:38 -08:00
tokenize_variable_array2 ( path , lst ) ;
2006-01-22 06:42:17 +10:00
}
}
}
2008-01-17 08:07:38 +10:00
int env_set_pwd ( )
{
wchar_t dir_path [ 4096 ] ;
wchar_t * res = wgetcwd ( dir_path , 4096 ) ;
if ( ! res )
{
return 0 ;
}
env_set ( L " PWD " , dir_path , ENV_EXPORT | ENV_GLOBAL ) ;
return 1 ;
}
2008-01-14 02:47:47 +10:00
/**
Set up default values for various variables if not defined .
*/
2006-10-19 21:38:44 +10:00
static void env_set_defaults ( )
{
2007-01-22 01:01:14 +10:00
2012-01-12 03:57:38 +05:30
if ( env_get_string ( L " USER " ) . empty ( ) )
2006-10-19 21:38:44 +10:00
{
struct passwd * pw = getpwuid ( getuid ( ) ) ;
wchar_t * unam = str2wcs ( pw - > pw_name ) ;
env_set ( L " USER " , unam , ENV_GLOBAL ) ;
free ( unam ) ;
}
2007-01-22 01:01:14 +10:00
2012-01-12 03:57:38 +05:30
if ( env_get_string ( L " HOME " ) . empty ( ) )
2006-10-19 21:38:44 +10:00
{
2012-01-12 03:57:38 +05:30
const wcstring unam = env_get_string ( L " USER " ) ;
char * unam_narrow = wcs2str ( unam . c_str ( ) ) ;
2006-10-19 21:38:44 +10:00
struct passwd * pw = getpwnam ( unam_narrow ) ;
wchar_t * dir = str2wcs ( pw - > pw_dir ) ;
env_set ( L " HOME " , dir , ENV_GLOBAL ) ;
2011-12-26 19:18:46 -08:00
free ( dir ) ;
2006-10-19 21:38:44 +10:00
free ( unam_narrow ) ;
2011-12-26 19:18:46 -08:00
}
2007-01-22 01:01:14 +10:00
2008-01-17 08:07:38 +10:00
env_set_pwd ( ) ;
2011-12-26 19:18:46 -08:00
2006-10-19 21:38:44 +10:00
}
2005-09-20 23:26:39 +10:00
void env_init ( )
{
char * * p ;
2005-10-23 20:22:32 +10:00
struct passwd * pw ;
2006-01-22 06:42:17 +10:00
wchar_t * uname ;
2006-08-28 19:58:40 +10:00
wchar_t * version ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
sb_init ( & dyn_var ) ;
2005-09-23 06:16:52 +10:00
b_init ( & export_buffer ) ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
/*
2011-12-26 19:18:46 -08:00
env_read_only variables can not be altered directly by the user
2005-09-20 23:26:39 +10:00
*/
2011-12-26 19:18:46 -08:00
const wchar_t * const ro_keys [ ] = {
L " status " ,
L " history " ,
L " version " ,
L " _ " ,
L " LINES " ,
L " COLUMNS " ,
L " PWD " ,
L " SHLVL " ,
} ;
for ( size_t i = 0 ; i < sizeof ro_keys / sizeof * ro_keys ; i + + ) {
env_read_only . insert ( ro_keys [ i ] ) ;
}
2005-09-20 23:26:39 +10:00
/*
2005-10-23 20:22:32 +10:00
HOME and USER should be writeable by root , since this can be a
2005-09-20 23:26:39 +10:00
convenient way to install software .
*/
if ( getuid ( ) ! = 0 )
2005-10-23 20:22:32 +10:00
{
2011-12-26 19:18:46 -08:00
env_read_only . insert ( L " HOME " ) ;
env_read_only . insert ( L " USER " ) ;
2005-10-23 20:22:32 +10:00
}
2011-12-26 19:18:46 -08:00
/*
Names of all dynamically calculated variables
*/
env_electric . insert ( L " history " ) ;
env_electric . insert ( L " status " ) ;
env_electric . insert ( L " umask " ) ;
top = ( env_node_t * ) malloc ( sizeof ( env_node_t ) ) ;
2005-09-20 23:26:39 +10:00
top - > next = 0 ;
top - > new_scope = 0 ;
2011-12-26 19:18:46 -08:00
top - > exportv = 0 ;
2005-09-20 23:26:39 +10:00
hash_init ( & top - > env , & hash_wcs_func , & hash_wcs_cmp ) ;
global_env = top ;
2011-12-26 19:18:46 -08:00
global = & top - > env ;
2006-01-22 06:42:17 +10:00
/*
Now the environemnt variable handling is set up , the next step
is to insert valid data
*/
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
/*
Import environment variables
*/
2007-01-28 02:59:11 +10:00
for ( p = environ ? environ : __environ ; p & & * p ; p + + )
2005-09-20 23:26:39 +10:00
{
wchar_t * key , * val ;
wchar_t * pos ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
key = str2wcs ( * p ) ;
2005-10-25 19:39:45 +10:00
2005-09-20 23:26:39 +10:00
if ( ! key )
2007-01-22 01:01:14 +10:00
{
2005-09-20 23:26:39 +10:00
continue ;
2007-01-22 01:01:14 +10:00
}
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
val = wcschr ( key , L ' = ' ) ;
2005-10-25 19:39:45 +10:00
2005-09-20 23:26:39 +10:00
if ( val = = 0 )
2007-01-22 01:01:14 +10:00
{
2005-09-20 23:26:39 +10:00
env_set ( key , L " " , ENV_EXPORT ) ;
2007-01-22 01:01:14 +10:00
}
2005-09-20 23:26:39 +10:00
else
2011-12-26 19:18:46 -08:00
{
2005-09-20 23:26:39 +10:00
* val = L ' \0 ' ;
val + + ;
pos = val ;
2005-09-24 09:15:38 +10:00
//fwprintf( stderr, L"Set $%ls to %ls\n", key, val );
2005-09-20 23:26:39 +10:00
while ( * pos )
{
if ( * pos = = L ' : ' )
2007-01-22 01:01:14 +10:00
{
2005-09-20 23:26:39 +10:00
* pos = ARRAY_SEP ;
2007-01-22 01:01:14 +10:00
}
2005-09-20 23:26:39 +10:00
pos + + ;
}
2005-10-25 19:39:45 +10:00
2005-09-20 23:26:39 +10:00
env_set ( key , val , ENV_EXPORT | ENV_GLOBAL ) ;
2011-12-26 19:18:46 -08:00
}
2005-09-20 23:26:39 +10:00
free ( key ) ;
2005-10-23 20:22:32 +10:00
}
2011-12-26 19:18:46 -08:00
2006-01-22 06:42:17 +10:00
/*
Set up the PATH variable
*/
setup_path ( ) ;
2005-11-24 04:57:43 +10:00
2006-01-22 06:42:17 +10:00
/*
Set up the USER variable
*/
2005-10-23 20:22:32 +10:00
pw = getpwuid ( getuid ( ) ) ;
2005-10-25 21:03:52 +10:00
if ( pw )
{
uname = str2wcs ( pw - > pw_name ) ;
env_set ( L " USER " , uname , ENV_GLOBAL | ENV_EXPORT ) ;
free ( uname ) ;
}
2006-08-28 19:58:40 +10:00
/*
Set up the version variable
*/
version = str2wcs ( PACKAGE_VERSION ) ;
env_set ( L " version " , version , ENV_GLOBAL ) ;
free ( version ) ;
2012-01-12 03:57:38 +05:30
2012-01-12 21:58:42 +05:30
const wcstring fishd_dir_wstr = env_get_string ( L " FISHD_SOCKET_DIR " ) ;
const wcstring user_dir_wstr = env_get_string ( L " USER " ) ;
wchar_t * fishd_dir = fishd_dir_wstr . empty ( ) ? NULL : const_cast < wchar_t * > ( fishd_dir_wstr . c_str ( ) ) ;
wchar_t * user_dir = user_dir_wstr . empty ( ) ? NULL : const_cast < wchar_t * > ( user_dir_wstr . c_str ( ) ) ;
2012-01-12 03:57:38 +05:30
env_universal_init ( fishd_dir , user_dir ,
2005-10-12 05:23:43 +10:00
& start_fishd ,
& universal_callback ) ;
2006-10-19 21:38:44 +10:00
2010-10-08 08:35:22 +08:00
/*
Set up SHLVL variable
*/
2012-01-12 03:57:38 +05:30
const wchar_t * shlvl = env_get_string ( L " SHLVL " ) . empty ( ) ? NULL : env_get_string ( L " SHLVL " ) . c_str ( ) ;
2010-10-08 08:35:22 +08:00
if ( shlvl )
{
wchar_t * nshlvl , * * end_nshlvl ;
/* add an extra space for digit dump (9+1=10) */
2010-10-08 09:01:25 +08:00
size_t i = wcslen ( shlvl ) + 2 * sizeof ( wchar_t ) ;
2010-10-08 09:38:06 +08:00
2011-12-26 19:18:46 -08:00
nshlvl = ( wchar_t * ) malloc ( i ) ;
end_nshlvl = ( wchar_t * * ) calloc ( 1 , sizeof ( nshlvl ) ) ;
2010-10-08 09:38:06 +08:00
if ( ! nshlvl | | ! end_nshlvl )
DIE_MEM ( ) ;
2010-10-08 08:35:22 +08:00
if ( nshlvl & & swprintf ( nshlvl , i ,
L " %ld " , wcstoul ( shlvl , end_nshlvl , 10 ) + 1 ) ! = - 1 )
{
env_set ( L " SHLVL " ,
nshlvl ,
ENV_GLOBAL | ENV_EXPORT ) ;
}
free ( end_nshlvl ) ;
free ( nshlvl ) ;
}
else
{
env_set ( L " SHLVL " ,
L " 1 " ,
ENV_GLOBAL | ENV_EXPORT ) ;
}
2006-10-19 21:38:44 +10:00
/*
Set correct defaults for e . g . USER and HOME variables
*/
env_set_defaults ( ) ;
2005-09-20 23:26:39 +10:00
}
void env_destroy ( )
{
env_universal_destroy ( ) ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
sb_destroy ( & dyn_var ) ;
2005-09-23 06:16:52 +10:00
b_destroy ( & export_buffer ) ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
while ( & top - > env ! = global )
2007-01-22 01:01:14 +10:00
{
2005-09-20 23:26:39 +10:00
env_pop ( ) ;
2007-01-22 01:01:14 +10:00
}
2011-12-26 19:18:46 -08:00
env_read_only . clear ( ) ;
env_electric . clear ( ) ;
2010-09-18 09:51:16 +08:00
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
hash_foreach ( global , & clear_hash_entry ) ;
hash_destroy ( global ) ;
free ( top ) ;
2011-12-26 19:18:46 -08:00
2005-09-23 06:16:52 +10:00
free ( export_arr ) ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
}
/**
2007-01-22 01:01:14 +10:00
Search all visible scopes in order for the specified key . Return
the first scope in which it was found .
2005-09-20 23:26:39 +10:00
*/
static env_node_t * env_get_node ( const wchar_t * key )
{
var_entry_t * res ;
env_node_t * env = top ;
while ( env ! = 0 )
{
2011-12-26 19:18:46 -08:00
res = ( var_entry_t * ) hash_get ( & env - > env ,
2005-09-20 23:26:39 +10:00
key ) ;
if ( res ! = 0 )
{
return env ;
}
if ( env - > new_scope )
2007-01-22 01:01:14 +10:00
{
2005-09-20 23:26:39 +10:00
env = global_env ;
2007-01-22 01:01:14 +10:00
}
2011-12-26 19:18:46 -08:00
else
2007-01-22 01:01:14 +10:00
{
2005-09-20 23:26:39 +10:00
env = env - > next ;
2007-01-22 01:01:14 +10:00
}
2005-09-20 23:26:39 +10:00
}
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
return 0 ;
}
2006-01-09 09:00:49 +10:00
2011-12-26 19:18:46 -08:00
int env_set ( const wchar_t * key ,
const wchar_t * val ,
2006-04-19 22:43:15 +10:00
int var_mode )
2005-09-20 23:26:39 +10:00
{
int free_val = 0 ;
var_entry_t * entry ;
env_node_t * node ;
int has_changed_old = has_changed ;
int has_changed_new = 0 ;
2011-12-26 19:18:46 -08:00
var_entry_t * e = 0 ;
2005-10-06 08:37:08 +10:00
int done = 0 ;
event_t ev ;
2011-12-26 19:18:46 -08:00
int is_universal = 0 ;
2006-06-21 10:48:36 +10:00
CHECK ( key , ENV_INVALID ) ;
2011-12-26 19:18:46 -08:00
2007-09-29 07:32:27 +10:00
if ( val & & contains ( key , L " PWD " , L " HOME " ) )
2007-05-11 05:11:28 +10:00
{
void * context = halloc ( 0 , 0 ) ;
const wchar_t * val_canonical = path_make_canonical ( context , val ) ;
if ( wcscmp ( val_canonical , val ) )
{
int res = env_set ( key , val_canonical , var_mode ) ;
halloc_free ( context ) ;
return res ;
}
halloc_free ( context ) ;
}
2011-12-26 19:18:46 -08:00
if ( ( var_mode & ENV_USER ) & & is_read_only ( key ) )
2005-09-20 23:26:39 +10:00
{
2006-04-11 01:36:26 +10:00
return ENV_PERM ;
2005-09-20 23:26:39 +10:00
}
2011-12-26 19:18:46 -08:00
2005-10-22 20:06:05 +10:00
if ( wcscmp ( key , L " umask " ) = = 0 )
{
wchar_t * end ;
int mask ;
2005-10-23 22:14:29 +10:00
/*
Set the new umask
*/
2005-10-22 20:06:05 +10:00
if ( val & & wcslen ( val ) )
2011-12-26 19:18:46 -08:00
{
2005-10-22 20:06:05 +10:00
errno = 0 ;
mask = wcstol ( val , & end , 8 ) ;
2011-12-26 19:18:46 -08:00
2005-10-23 22:14:29 +10:00
if ( ! errno & & ( ! * end ) & & ( mask < = 0777 ) & & ( mask > = 0 ) )
2005-10-22 20:06:05 +10:00
{
umask ( mask ) ;
}
}
2005-10-23 22:14:29 +10:00
/*
2007-01-22 01:01:14 +10:00
Do not actually create a umask variable , on env_get , it will
be calculated dynamically
2005-10-23 22:14:29 +10:00
*/
2006-04-11 01:36:26 +10:00
return 0 ;
2005-10-22 20:06:05 +10:00
}
2005-09-27 00:47:03 +10:00
/*
2007-01-22 01:01:14 +10:00
Zero element arrays are internaly not coded as null but as this
placeholder string
2005-09-27 00:47:03 +10:00
*/
2006-01-27 01:48:23 +10:00
if ( ! val )
2005-09-27 00:47:03 +10:00
{
val = ENV_NULL ;
}
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
if ( var_mode & ENV_UNIVERSAL )
{
2011-12-26 19:18:46 -08:00
int exportv = 0 ;
2005-09-23 06:16:52 +10:00
if ( ! ( var_mode & ENV_EXPORT ) & &
! ( var_mode & ENV_UNEXPORT ) )
{
env_universal_get_export ( key ) ;
}
2011-12-26 19:18:46 -08:00
else
2007-01-22 01:01:14 +10:00
{
2011-12-26 19:18:46 -08:00
exportv = ( var_mode & ENV_EXPORT ) ;
2007-01-22 01:01:14 +10:00
}
2011-12-26 19:18:46 -08:00
env_universal_set ( key , val , exportv ) ;
2005-10-12 05:23:43 +10:00
is_universal = 1 ;
2006-10-02 01:59:18 +10:00
2005-09-20 23:26:39 +10:00
}
2005-10-06 08:37:08 +10:00
else
2005-09-20 23:26:39 +10:00
{
2011-12-26 19:18:46 -08:00
2005-10-06 08:37:08 +10:00
node = env_get_node ( key ) ;
if ( node & & & node - > env ! = 0 )
{
2011-12-26 19:18:46 -08:00
e = ( var_entry_t * ) hash_get ( & node - > env ,
2005-10-06 08:37:08 +10:00
key ) ;
2011-12-26 19:18:46 -08:00
if ( e - > exportv )
2007-01-22 01:01:14 +10:00
{
2005-10-06 08:37:08 +10:00
has_changed_new = 1 ;
2007-01-22 01:01:14 +10:00
}
2005-10-06 08:37:08 +10:00
}
2005-09-20 23:26:39 +10:00
2011-12-26 19:18:46 -08:00
if ( ( var_mode & ENV_LOCAL ) | |
2005-10-06 08:37:08 +10:00
( var_mode & ENV_GLOBAL ) )
2005-09-20 23:26:39 +10:00
{
2005-10-06 08:37:08 +10:00
node = ( var_mode & ENV_GLOBAL ) ? global_env : top ;
2005-09-20 23:26:39 +10:00
}
else
{
2005-10-06 08:37:08 +10:00
if ( node )
2005-09-20 23:26:39 +10:00
{
2005-09-23 06:16:52 +10:00
if ( ! ( var_mode & ENV_EXPORT ) & &
! ( var_mode & ENV_UNEXPORT ) )
2011-12-26 19:18:46 -08:00
{
var_mode = e - > exportv ? ENV_EXPORT : 0 ;
2005-09-23 06:16:52 +10:00
}
2005-09-20 23:26:39 +10:00
}
else
{
2005-10-06 08:37:08 +10:00
if ( ! proc_had_barrier )
2005-11-28 09:22:08 +10:00
{
proc_had_barrier = 1 ;
2005-10-06 08:37:08 +10:00
env_universal_barrier ( ) ;
2005-11-28 09:22:08 +10:00
}
2011-12-26 19:18:46 -08:00
2005-10-06 08:37:08 +10:00
if ( env_universal_get ( key ) )
{
2011-12-26 19:18:46 -08:00
int exportv = 0 ;
2005-10-06 08:37:08 +10:00
if ( ! ( var_mode & ENV_EXPORT ) & &
! ( var_mode & ENV_UNEXPORT ) )
{
env_universal_get_export ( key ) ;
}
2011-12-26 19:18:46 -08:00
else
2007-01-22 01:01:14 +10:00
{
2011-12-26 19:18:46 -08:00
exportv = ( var_mode & ENV_EXPORT ) ;
2007-01-22 01:01:14 +10:00
}
2011-12-26 19:18:46 -08:00
env_universal_set ( key , val , exportv ) ;
2005-10-12 05:23:43 +10:00
is_universal = 1 ;
2011-12-26 19:18:46 -08:00
2005-10-06 08:37:08 +10:00
done = 1 ;
2011-12-26 19:18:46 -08:00
2005-10-06 08:37:08 +10:00
}
else
{
/*
2006-01-23 07:07:56 +10:00
New variable with unspecified scope . The default
2007-01-19 02:29:22 +10:00
scope is the innermost scope that is shadowing ,
which will be either the current function or the
2011-12-26 19:18:46 -08:00
global scope .
2005-10-06 08:37:08 +10:00
*/
node = top ;
while ( node - > next & & ! node - > new_scope )
2007-01-22 01:01:14 +10:00
{
2005-10-06 08:37:08 +10:00
node = node - > next ;
2007-01-22 01:01:14 +10:00
}
2005-10-06 08:37:08 +10:00
}
2005-09-20 23:26:39 +10:00
}
}
2011-12-26 19:18:46 -08:00
2005-10-06 08:37:08 +10:00
if ( ! done )
{
void * k , * v ;
2007-01-19 02:29:22 +10:00
var_entry_t * old_entry ;
size_t val_len = wcslen ( val ) ;
2006-06-13 07:47:42 +10:00
hash_remove ( & node - > env , key , & k , & v ) ;
2005-10-06 08:37:08 +10:00
2007-01-19 02:29:22 +10:00
/*
Try to reuse previous key string
*/
if ( ! k )
2007-01-22 01:01:14 +10:00
{
2007-01-19 02:29:22 +10:00
k = wcsdup ( key ) ;
2007-01-22 01:01:14 +10:00
}
2011-12-26 19:18:46 -08:00
2007-01-19 02:29:22 +10:00
old_entry = ( var_entry_t * ) v ;
if ( old_entry & & old_entry - > size > = val_len )
2005-10-06 08:37:08 +10:00
{
2007-01-19 02:29:22 +10:00
entry = old_entry ;
2011-12-26 19:18:46 -08:00
if ( ! ! ( var_mode & ENV_EXPORT ) | | entry - > exportv )
2007-01-19 02:29:22 +10:00
{
2011-12-26 19:18:46 -08:00
entry - > exportv = ! ! ( var_mode & ENV_EXPORT ) ;
has_changed_new = 1 ;
2007-01-19 02:29:22 +10:00
}
2005-10-06 08:37:08 +10:00
}
else
2007-01-19 02:29:22 +10:00
{
free ( v ) ;
2005-09-20 23:26:39 +10:00
2011-12-26 19:18:46 -08:00
entry = ( var_entry_t * ) malloc ( sizeof ( var_entry_t ) +
2007-01-19 02:29:22 +10:00
sizeof ( wchar_t ) * ( val_len + 1 ) ) ;
2011-12-26 19:18:46 -08:00
2007-01-19 02:29:22 +10:00
if ( ! entry )
2007-01-22 01:01:14 +10:00
{
2007-01-19 02:29:22 +10:00
DIE_MEM ( ) ;
2007-01-22 01:01:14 +10:00
}
2011-12-26 19:18:46 -08:00
2007-01-19 02:29:22 +10:00
entry - > size = val_len ;
2011-12-26 19:18:46 -08:00
2007-01-19 02:29:22 +10:00
if ( var_mode & ENV_EXPORT )
{
2011-12-26 19:18:46 -08:00
entry - > exportv = 1 ;
has_changed_new = 1 ;
2007-01-19 02:29:22 +10:00
}
2007-01-22 11:28:15 +10:00
else
{
2011-12-26 19:18:46 -08:00
entry - > exportv = 0 ;
2007-01-22 11:28:15 +10:00
}
2011-12-26 19:18:46 -08:00
2007-01-19 02:29:22 +10:00
}
2005-09-20 23:26:39 +10:00
2007-01-19 02:29:22 +10:00
wcscpy ( entry - > val , val ) ;
2011-12-26 19:18:46 -08:00
2007-01-19 02:29:22 +10:00
hash_put ( & node - > env , k , entry ) ;
2005-09-20 23:26:39 +10:00
2011-12-26 19:18:46 -08:00
if ( entry - > exportv )
2005-10-06 08:37:08 +10:00
{
2011-12-26 19:18:46 -08:00
node - > exportv = 1 ;
2005-10-06 08:37:08 +10:00
}
2005-09-20 23:26:39 +10:00
2005-10-06 08:37:08 +10:00
if ( free_val )
2007-01-22 01:01:14 +10:00
{
2005-10-06 08:37:08 +10:00
free ( ( void * ) val ) ;
2007-01-22 01:01:14 +10:00
}
2011-12-26 19:18:46 -08:00
2005-10-06 08:37:08 +10:00
has_changed = has_changed_old | | has_changed_new ;
}
2011-12-26 19:18:46 -08:00
2005-10-06 08:37:08 +10:00
}
2005-09-24 09:15:38 +10:00
2005-10-12 05:23:43 +10:00
if ( ! is_universal )
{
ev . type = EVENT_VARIABLE ;
2005-10-12 05:31:16 +10:00
ev . param1 . variable = key ;
2005-10-12 05:23:43 +10:00
ev . function_name = 0 ;
2011-12-26 19:18:46 -08:00
2011-12-27 00:06:07 -08:00
ev . arguments = new wcstring_list_t ;
ev . arguments - > push_back ( L " VARIABLE " ) ;
ev . arguments - > push_back ( L " SET " ) ;
ev . arguments - > push_back ( key ) ;
2011-12-26 19:18:46 -08:00
// debug( 1, L"env_set: fire events on variable %ls", key );
2005-12-12 08:21:01 +10:00
event_fire ( & ev ) ;
2011-12-26 19:18:46 -08:00
// debug( 1, L"env_set: return from event firing" );
2011-12-27 00:06:07 -08:00
delete ev . arguments ;
ev . arguments = NULL ;
2005-10-12 05:23:43 +10:00
}
2006-01-09 09:00:49 +10:00
if ( is_locale ( key ) )
{
handle_locale ( ) ;
}
2006-04-11 01:36:26 +10:00
return 0 ;
2005-09-20 23:26:39 +10:00
}
2006-01-09 09:00:49 +10:00
2005-09-20 23:26:39 +10:00
/**
Attempt to remove / free the specified key / value pair from the
specified hash table .
2006-05-29 23:12:17 +10:00
\ return zero if the variable was not found , non - zero otherwise
2005-09-20 23:26:39 +10:00
*/
static int try_remove ( env_node_t * n ,
2006-06-05 06:14:51 +10:00
const wchar_t * key ,
int var_mode )
2005-09-20 23:26:39 +10:00
{
2006-06-13 07:47:42 +10:00
void * old_key_void , * old_val_void ;
2005-09-20 23:26:39 +10:00
wchar_t * old_key , * old_val ;
2006-06-05 06:14:51 +10:00
2005-09-20 23:26:39 +10:00
if ( n = = 0 )
2007-01-22 01:01:14 +10:00
{
2005-09-20 23:26:39 +10:00
return 0 ;
2007-01-22 01:01:14 +10:00
}
2011-12-26 19:18:46 -08:00
hash_remove ( & n - > env ,
2005-09-20 23:26:39 +10:00
key ,
2011-12-26 19:18:46 -08:00
& old_key_void ,
2006-03-26 21:23:39 +10:00
& old_val_void ) ;
old_key = ( wchar_t * ) old_key_void ;
old_val = ( wchar_t * ) old_val_void ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
if ( old_key ! = 0 )
{
var_entry_t * v = ( var_entry_t * ) old_val ;
2011-12-26 19:18:46 -08:00
if ( v - > exportv )
2005-09-20 23:26:39 +10:00
{
has_changed = 1 ;
}
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
free ( old_key ) ;
free ( old_val ) ;
return 1 ;
}
2006-06-05 06:14:51 +10:00
if ( var_mode & ENV_LOCAL )
2007-01-22 01:01:14 +10:00
{
2006-06-05 06:14:51 +10:00
return 0 ;
2007-01-22 01:01:14 +10:00
}
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
if ( n - > new_scope )
2007-01-22 01:01:14 +10:00
{
2006-06-05 06:14:51 +10:00
return try_remove ( global_env , key , var_mode ) ;
2007-01-22 01:01:14 +10:00
}
2005-09-20 23:26:39 +10:00
else
2007-01-22 01:01:14 +10:00
{
2006-06-05 06:14:51 +10:00
return try_remove ( n - > next , key , var_mode ) ;
2007-01-22 01:01:14 +10:00
}
2005-09-20 23:26:39 +10:00
}
2006-06-05 06:14:51 +10:00
int env_remove ( const wchar_t * key , int var_mode )
2005-09-20 23:26:39 +10:00
{
2006-06-05 06:14:51 +10:00
env_node_t * first_node ;
int erased = 0 ;
2011-12-26 19:18:46 -08:00
2006-06-21 10:48:36 +10:00
CHECK ( key , 1 ) ;
2011-12-26 19:18:46 -08:00
if ( ( var_mode & ENV_USER ) & & is_read_only ( key ) )
2005-09-20 23:26:39 +10:00
{
2006-06-05 06:14:51 +10:00
return 2 ;
2005-09-20 23:26:39 +10:00
}
2011-12-26 19:18:46 -08:00
2006-06-05 06:14:51 +10:00
first_node = top ;
2011-12-26 19:18:46 -08:00
2006-06-05 06:14:51 +10:00
if ( ! ( var_mode & ENV_UNIVERSAL ) )
{
2011-12-26 19:18:46 -08:00
2006-06-05 06:14:51 +10:00
if ( var_mode & ENV_GLOBAL )
{
first_node = global_env ;
}
2011-12-26 19:18:46 -08:00
2006-06-05 06:14:51 +10:00
if ( try_remove ( first_node , key , var_mode ) )
2011-12-26 19:18:46 -08:00
{
2006-06-05 06:14:51 +10:00
event_t ev ;
2011-12-26 19:18:46 -08:00
2006-06-05 06:14:51 +10:00
ev . type = EVENT_VARIABLE ;
ev . param1 . variable = key ;
ev . function_name = 0 ;
2011-12-26 19:18:46 -08:00
2011-12-27 00:06:07 -08:00
ev . arguments = new wcstring_list_t ;
ev . arguments - > push_back ( L " VARIABLE " ) ;
ev . arguments - > push_back ( L " ERASE " ) ;
ev . arguments - > push_back ( key ) ;
2011-12-26 19:18:46 -08:00
event_fire ( & ev ) ;
2011-12-27 00:06:07 -08:00
delete ev . arguments ;
ev . arguments = NULL ;
2006-06-05 06:14:51 +10:00
erased = 1 ;
}
2006-05-29 23:12:17 +10:00
}
2011-12-26 19:18:46 -08:00
if ( ! erased & &
2006-06-05 06:14:51 +10:00
! ( var_mode & ENV_GLOBAL ) & &
2011-12-26 19:18:46 -08:00
! ( var_mode & ENV_LOCAL ) )
2005-09-20 23:26:39 +10:00
{
2006-06-05 06:14:51 +10:00
erased = ! env_universal_remove ( key ) ;
2005-09-20 23:26:39 +10:00
}
2006-01-09 09:00:49 +10:00
if ( is_locale ( key ) )
2006-06-05 06:14:51 +10:00
{
2006-01-09 09:00:49 +10:00
handle_locale ( ) ;
2006-06-05 06:14:51 +10:00
}
2011-12-26 19:18:46 -08:00
return ! erased ;
2005-09-20 23:26:39 +10:00
}
2011-12-26 19:18:46 -08:00
wcstring env_get_string ( const wchar_t * key )
{
scoped_lock lock ( env_lock ) ;
CHECK ( key , 0 ) ;
if ( wcscmp ( key , L " history " ) = = 0 )
{
wcstring result ;
wchar_t * current ;
int i ;
int add_current = 0 ;
current = reader_get_buffer ( ) ;
if ( current & & wcslen ( current ) )
{
add_current = 1 ;
result + = current ;
}
for ( i = add_current ; ; i + + )
{
// PCA This looks bad!
wchar_t * next = history_get ( i - add_current ) ;
if ( ! next )
{
break ;
}
if ( i ! = 0 )
{
result + = ARRAY_SEP_STR ;
}
result + = next ;
}
return result ;
}
else if ( wcscmp ( key , L " COLUMNS " ) = = 0 )
{
return format_val ( ( long ) common_get_width ( ) ) ;
}
else if ( wcscmp ( key , L " LINES " ) = = 0 )
{
return format_val ( ( long ) common_get_width ( ) ) ;
}
else if ( wcscmp ( key , L " status " ) = = 0 )
{
return format_val ( ( long ) proc_get_last_status ( ) ) ;
}
else if ( wcscmp ( key , L " umask " ) = = 0 )
{
return format_string ( L " 0%0.3o " , get_umask ( ) ) ;
}
else {
var_entry_t * res ;
env_node_t * env = top ;
wchar_t * item ;
wcstring result ;
while ( env ! = 0 )
{
res = ( var_entry_t * ) hash_get ( & env - > env ,
key ) ;
if ( res ! = 0 )
{
if ( wcscmp ( res - > val , ENV_NULL ) = = 0 )
{
2012-01-10 01:40:03 +05:30
return wcstring ( L " " ) ;
2011-12-26 19:18:46 -08:00
}
else
{
return res - > val ;
}
}
if ( env - > new_scope )
{
env = global_env ;
}
else
{
env = env - > next ;
}
}
if ( ! proc_had_barrier )
{
proc_had_barrier = 1 ;
env_universal_barrier ( ) ;
}
item = env_universal_get ( key ) ;
if ( ! item | | ( wcscmp ( item , ENV_NULL ) = = 0 ) )
{
2012-01-10 01:40:03 +05:30
return wcstring ( L " " ) ;
2011-12-26 19:18:46 -08:00
}
else
{
return item ;
}
}
}
2005-09-20 23:26:39 +10:00
wchar_t * env_get ( const wchar_t * key )
{
2011-12-26 19:18:46 -08:00
ASSERT_IS_MAIN_THREAD ( ) ;
2012-01-05 13:58:48 -08:00
2005-09-20 23:26:39 +10:00
var_entry_t * res ;
env_node_t * env = top ;
2005-09-27 00:47:03 +10:00
wchar_t * item ;
2011-12-26 19:18:46 -08:00
2006-06-21 10:48:36 +10:00
CHECK ( key , 0 ) ;
2006-10-02 01:59:18 +10:00
2005-09-20 23:26:39 +10:00
if ( wcscmp ( key , L " history " ) = = 0 )
{
wchar_t * current ;
2011-12-26 19:18:46 -08:00
int i ;
2005-09-20 23:26:39 +10:00
int add_current = 0 ;
2011-12-26 19:18:46 -08:00
sb_clear ( & dyn_var ) ;
2005-09-20 23:26:39 +10:00
current = reader_get_buffer ( ) ;
if ( current & & wcslen ( current ) )
{
add_current = 1 ;
sb_append ( & dyn_var , current ) ;
}
2011-12-26 19:18:46 -08:00
2006-10-19 21:39:16 +10:00
for ( i = add_current ; ; i + + )
2005-09-20 23:26:39 +10:00
{
wchar_t * next = history_get ( i - add_current ) ;
if ( ! next )
{
break ;
}
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
if ( i ! = 0 )
2007-01-22 01:01:14 +10:00
{
2005-09-20 23:26:39 +10:00
sb_append ( & dyn_var , ARRAY_SEP_STR ) ;
2007-01-22 01:01:14 +10:00
}
2005-09-20 23:26:39 +10:00
sb_append ( & dyn_var , next ) ;
}
2006-10-02 01:59:18 +10:00
2005-09-20 23:26:39 +10:00
return ( wchar_t * ) dyn_var . buff ;
}
2005-10-14 21:40:33 +10:00
else if ( wcscmp ( key , L " COLUMNS " ) = = 0 )
{
2011-12-26 19:18:46 -08:00
sb_clear ( & dyn_var ) ;
sb_printf ( & dyn_var , L " %d " , common_get_width ( ) ) ;
return ( wchar_t * ) dyn_var . buff ;
}
2005-10-14 21:40:33 +10:00
else if ( wcscmp ( key , L " LINES " ) = = 0 )
{
2011-12-26 19:18:46 -08:00
sb_clear ( & dyn_var ) ;
sb_printf ( & dyn_var , L " %d " , common_get_height ( ) ) ;
2005-10-14 21:40:33 +10:00
return ( wchar_t * ) dyn_var . buff ;
}
else if ( wcscmp ( key , L " status " ) = = 0 )
{
2011-12-26 19:18:46 -08:00
sb_clear ( & dyn_var ) ;
sb_printf ( & dyn_var , L " %d " , proc_get_last_status ( ) ) ;
return ( wchar_t * ) dyn_var . buff ;
2005-10-14 21:40:33 +10:00
}
2005-10-23 22:14:29 +10:00
else if ( wcscmp ( key , L " umask " ) = = 0 )
{
2011-12-26 19:18:46 -08:00
sb_clear ( & dyn_var ) ;
sb_printf ( & dyn_var , L " 0%0.3o " , get_umask ( ) ) ;
return ( wchar_t * ) dyn_var . buff ;
2005-10-23 22:14:29 +10:00
}
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
while ( env ! = 0 )
{
2011-12-26 19:18:46 -08:00
res = ( var_entry_t * ) hash_get ( & env - > env ,
2005-10-06 08:37:08 +10:00
key ) ;
2005-09-20 23:26:39 +10:00
if ( res ! = 0 )
{
2011-12-26 19:18:46 -08:00
if ( wcscmp ( res - > val , ENV_NULL ) = = 0 )
2005-09-27 00:47:03 +10:00
{
return 0 ;
}
else
2007-01-22 01:01:14 +10:00
{
2011-12-26 19:18:46 -08:00
return res - > val ;
2007-01-22 01:01:14 +10:00
}
2005-09-20 23:26:39 +10:00
}
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
if ( env - > new_scope )
2007-01-22 01:01:14 +10:00
{
2005-09-20 23:26:39 +10:00
env = global_env ;
2007-01-22 01:01:14 +10:00
}
2005-09-20 23:26:39 +10:00
else
2007-01-22 01:01:14 +10:00
{
2005-09-20 23:26:39 +10:00
env = env - > next ;
2007-01-22 01:01:14 +10:00
}
2011-12-26 19:18:46 -08:00
}
2005-09-24 09:15:38 +10:00
if ( ! proc_had_barrier )
2005-11-28 09:22:08 +10:00
{
proc_had_barrier = 1 ;
2005-09-24 09:15:38 +10:00
env_universal_barrier ( ) ;
2005-11-28 09:22:08 +10:00
}
2011-12-26 19:18:46 -08:00
2005-09-27 00:47:03 +10:00
item = env_universal_get ( key ) ;
2011-12-26 19:18:46 -08:00
2005-09-27 00:47:03 +10:00
if ( ! item | | ( wcscmp ( item , ENV_NULL ) = = 0 ) )
{
return 0 ;
}
else
2007-01-22 01:01:14 +10:00
{
2005-09-27 00:47:03 +10:00
return item ;
2007-01-22 01:01:14 +10:00
}
2005-09-27 00:47:03 +10:00
}
2006-06-05 06:14:51 +10:00
int env_exist ( const wchar_t * key , int mode )
2005-09-27 00:47:03 +10:00
{
var_entry_t * res ;
2006-06-05 06:14:51 +10:00
env_node_t * env ;
wchar_t * item = 0 ;
2006-06-21 10:48:36 +10:00
CHECK ( key , 0 ) ;
2011-12-26 19:18:46 -08:00
2006-06-05 06:14:51 +10:00
/*
Read only variables all exist , and they are all global . A local
2006-06-09 09:52:12 +10:00
version can not exist .
2006-06-05 06:14:51 +10:00
*/
if ( ! ( mode & ENV_LOCAL ) & & ! ( mode & ENV_UNIVERSAL ) )
2005-09-27 00:47:03 +10:00
{
2011-12-26 19:18:46 -08:00
if ( is_read_only ( key ) | | is_electric ( key ) )
2005-09-27 00:47:03 +10:00
{
return 1 ;
}
2006-06-05 06:14:51 +10:00
}
if ( ! ( mode & ENV_UNIVERSAL ) )
2005-11-28 09:22:08 +10:00
{
2006-06-05 06:14:51 +10:00
env = ( mode & ENV_GLOBAL ) ? global_env : top ;
2011-12-26 19:18:46 -08:00
2006-06-05 06:14:51 +10:00
while ( env ! = 0 )
{
2011-12-26 19:18:46 -08:00
res = ( var_entry_t * ) hash_get ( & env - > env ,
2006-06-05 06:14:51 +10:00
key ) ;
if ( res ! = 0 )
{
return 1 ;
}
2011-12-26 19:18:46 -08:00
2006-06-05 06:14:51 +10:00
if ( mode & ENV_LOCAL )
2007-01-22 01:01:14 +10:00
{
2006-06-05 06:14:51 +10:00
break ;
2007-01-22 01:01:14 +10:00
}
2011-12-26 19:18:46 -08:00
2006-06-05 06:14:51 +10:00
if ( env - > new_scope )
2007-01-22 01:01:14 +10:00
{
2006-06-05 06:14:51 +10:00
env = global_env ;
2007-01-22 01:01:14 +10:00
}
2006-06-05 06:14:51 +10:00
else
2007-01-22 01:01:14 +10:00
{
2006-06-05 06:14:51 +10:00
env = env - > next ;
2007-01-22 01:01:14 +10:00
}
2011-12-26 19:18:46 -08:00
}
2005-11-28 09:22:08 +10:00
}
2011-12-26 19:18:46 -08:00
2006-06-05 06:14:51 +10:00
if ( ! ( mode & ENV_LOCAL ) & & ! ( mode & ENV_GLOBAL ) )
{
if ( ! proc_had_barrier )
{
proc_had_barrier = 1 ;
env_universal_barrier ( ) ;
}
2011-12-26 19:18:46 -08:00
2006-06-05 06:14:51 +10:00
item = env_universal_get ( key ) ;
2011-12-26 19:18:46 -08:00
2006-06-05 06:14:51 +10:00
}
2005-09-27 00:47:03 +10:00
return item ! = 0 ;
2006-06-05 06:14:51 +10:00
2005-09-20 23:26:39 +10:00
}
2005-10-25 01:26:25 +10:00
/**
Returns true if the specified scope or any non - shadowed non - global subscopes contain an exported variable .
*/
2005-09-20 23:26:39 +10:00
static int local_scope_exports ( env_node_t * n )
{
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
if ( n = = global_env )
return 0 ;
2011-12-26 19:18:46 -08:00
if ( n - > exportv )
2005-09-20 23:26:39 +10:00
return 1 ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
if ( n - > new_scope )
return 0 ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
return local_scope_exports ( n - > next ) ;
}
void env_push ( int new_scope )
{
2011-12-26 19:18:46 -08:00
env_node_t * node = ( env_node_t * ) malloc ( sizeof ( env_node_t ) ) ;
2005-09-20 23:26:39 +10:00
node - > next = top ;
2011-12-26 19:18:46 -08:00
node - > exportv = 0 ;
2005-09-20 23:26:39 +10:00
hash_init ( & node - > env , & hash_wcs_func , & hash_wcs_cmp ) ;
node - > new_scope = new_scope ;
if ( new_scope )
{
2005-09-24 09:15:38 +10:00
has_changed | = local_scope_exports ( top ) ;
2005-09-20 23:26:39 +10:00
}
2011-12-26 19:18:46 -08:00
top = node ;
2005-09-20 23:26:39 +10:00
}
void env_pop ( )
{
if ( & top - > env ! = global )
{
2006-01-13 11:00:12 +10:00
int i ;
int locale_changed = 0 ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
env_node_t * killme = top ;
2006-01-13 11:00:12 +10:00
for ( i = 0 ; locale_variable [ i ] ; i + + )
{
if ( hash_get ( & killme - > env , locale_variable [ i ] ) )
{
locale_changed = 1 ;
break ;
}
}
2005-09-20 23:26:39 +10:00
if ( killme - > new_scope )
{
2011-12-26 19:18:46 -08:00
has_changed | = killme - > exportv | | local_scope_exports ( killme - > next ) ;
2005-09-20 23:26:39 +10:00
}
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
top = top - > next ;
hash_foreach ( & killme - > env , & clear_hash_entry ) ;
hash_destroy ( & killme - > env ) ;
free ( killme ) ;
2006-01-13 11:00:12 +10:00
if ( locale_changed )
handle_locale ( ) ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
}
else
{
debug ( 0 ,
2006-01-04 22:51:02 +10:00
_ ( L " Tried to pop empty environment stack. " ) ) ;
2005-09-20 23:26:39 +10:00
sanity_lose ( ) ;
2011-12-26 19:18:46 -08:00
}
2005-09-20 23:26:39 +10:00
}
/**
Function used with hash_foreach to insert keys of one table into
another
*/
2011-12-26 19:18:46 -08:00
static void add_key_to_hash ( void * key ,
2006-06-13 07:47:42 +10:00
void * data ,
2005-09-20 23:26:39 +10:00
void * aux )
{
var_entry_t * e = ( var_entry_t * ) data ;
2011-12-26 19:18:46 -08:00
if ( ( e - > exportv & & get_names_show_exported ) | |
( ! e - > exportv & & get_names_show_unexported ) )
2006-01-22 06:42:17 +10:00
{
2005-09-20 23:26:39 +10:00
hash_put ( ( hash_table_t * ) aux , key , 0 ) ;
2006-01-22 06:42:17 +10:00
}
2005-09-20 23:26:39 +10:00
}
2005-09-23 06:16:52 +10:00
2005-10-25 01:26:25 +10:00
/**
Add key to hashtable
*/
2006-06-13 07:47:42 +10:00
static void add_to_hash ( void * k , void * aux )
2005-09-20 23:26:39 +10:00
{
2005-09-23 06:16:52 +10:00
hash_put ( ( hash_table_t * ) aux ,
k ,
0 ) ;
2005-09-20 23:26:39 +10:00
}
void env_get_names ( array_list_t * l , int flags )
{
int show_local = flags & ENV_LOCAL ;
int show_global = flags & ENV_GLOBAL ;
int show_universal = flags & ENV_UNIVERSAL ;
hash_table_t names ;
env_node_t * n = top ;
2006-06-21 20:07:46 +10:00
CHECK ( l , ) ;
2011-12-26 19:18:46 -08:00
get_names_show_exported =
2005-09-20 23:26:39 +10:00
flags & ENV_EXPORT | | ( ! ( flags & ENV_UNEXPORT ) ) ;
2011-12-26 19:18:46 -08:00
get_names_show_unexported =
2005-09-20 23:26:39 +10:00
flags & ENV_UNEXPORT | | ( ! ( flags & ENV_EXPORT ) ) ;
if ( ! show_local & & ! show_global & & ! show_universal )
{
show_local = show_universal = show_global = 1 ;
}
hash_init ( & names , & hash_wcs_func , & hash_wcs_cmp ) ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
if ( show_local )
{
while ( n )
{
if ( n = = global_env )
break ;
2011-12-26 19:18:46 -08:00
hash_foreach2 ( & n - > env ,
2005-09-20 23:26:39 +10:00
add_key_to_hash ,
& names ) ;
if ( n - > new_scope )
2011-12-26 19:18:46 -08:00
break ;
2005-09-20 23:26:39 +10:00
else
n = n - > next ;
}
}
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
if ( show_global )
{
2011-12-26 19:18:46 -08:00
hash_foreach2 ( & global_env - > env ,
2005-09-20 23:26:39 +10:00
add_key_to_hash ,
& names ) ;
2005-10-23 22:14:29 +10:00
2011-12-26 19:18:46 -08:00
if ( get_names_show_unexported ) {
for ( std : : set < wcstring > : : iterator iter = env_electric . begin ( ) ; iter ! = env_electric . end ( ) ; iter + + ) {
al_push ( l , iter - > c_str ( ) ) ;
}
}
2005-10-14 21:40:33 +10:00
if ( get_names_show_exported )
{
al_push ( l , L " COLUMNS " ) ;
al_push ( l , L " LINES " ) ;
}
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
}
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
if ( show_universal )
{
2005-09-23 06:16:52 +10:00
array_list_t uni_list ;
al_init ( & uni_list ) ;
2011-12-26 19:18:46 -08:00
env_universal_get_names ( & uni_list ,
2005-09-23 06:16:52 +10:00
get_names_show_exported ,
get_names_show_unexported ) ;
al_foreach2 ( & uni_list , & add_to_hash , & names ) ;
al_destroy ( & uni_list ) ;
2005-09-20 23:26:39 +10:00
}
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
hash_get_keys ( & names , l ) ;
2011-12-26 19:18:46 -08:00
hash_destroy ( & names ) ;
2005-09-20 23:26:39 +10:00
}
2005-10-03 23:24:46 +10:00
/**
Function used by env_export_arr to iterate over hashtable of variables
*/
2006-06-13 07:47:42 +10:00
static void export_func1 ( void * k , void * v , void * aux )
2005-09-20 23:26:39 +10:00
{
2005-09-23 06:16:52 +10:00
var_entry_t * val_entry = ( var_entry_t * ) v ;
2006-11-26 23:09:43 +10:00
hash_table_t * h = ( hash_table_t * ) aux ;
hash_remove ( h , k , 0 , 0 ) ;
2011-12-26 19:18:46 -08:00
if ( val_entry - > exportv & & wcscmp ( val_entry - > val , ENV_NULL ) )
{
2006-11-26 23:09:43 +10:00
hash_put ( h , k , val_entry - > val ) ;
2005-09-23 06:16:52 +10:00
}
2011-12-26 19:18:46 -08:00
2005-09-23 06:16:52 +10:00
}
2005-09-20 23:26:39 +10:00
2008-01-14 02:47:47 +10:00
/**
Get list of all exported variables
*/
2006-11-26 23:09:43 +10:00
static void get_exported ( env_node_t * n , hash_table_t * h )
{
if ( ! n )
return ;
2011-12-26 19:18:46 -08:00
2006-11-26 23:09:43 +10:00
if ( n - > new_scope )
get_exported ( global_env , h ) ;
else
get_exported ( n - > next , h ) ;
2011-12-26 19:18:46 -08:00
hash_foreach2 ( & n - > env , & export_func1 , h ) ;
}
2006-11-26 23:09:43 +10:00
2005-10-03 23:24:46 +10:00
/**
Function used by env_export_arr to iterate over hashtable of variables
*/
2006-06-13 07:47:42 +10:00
static void export_func2 ( void * k , void * v , void * aux )
2005-09-23 06:16:52 +10:00
{
wchar_t * key = ( wchar_t * ) k ;
wchar_t * val = ( wchar_t * ) v ;
2011-12-26 19:18:46 -08:00
2005-09-23 06:16:52 +10:00
char * ks = wcs2str ( key ) ;
char * vs = wcs2str ( val ) ;
2011-12-26 19:18:46 -08:00
2005-09-23 06:16:52 +10:00
char * pos = vs ;
buffer_t * out = ( buffer_t * ) aux ;
if ( ! ks | | ! vs )
{
2006-07-03 20:39:57 +10:00
DIE_MEM ( ) ;
2005-09-23 06:16:52 +10:00
}
2011-12-26 19:18:46 -08:00
2005-09-23 06:16:52 +10:00
/*
Make arrays into colon - separated lists
*/
while ( * pos )
{
if ( * pos = = ARRAY_SEP )
2011-12-26 19:18:46 -08:00
* pos = ' : ' ;
2005-09-23 06:16:52 +10:00
pos + + ;
}
int nil = 0 ;
2011-12-26 19:18:46 -08:00
2005-09-23 06:16:52 +10:00
b_append ( out , ks , strlen ( ks ) ) ;
b_append ( out , " = " , 1 ) ;
b_append ( out , vs , strlen ( vs ) ) ;
b_append ( out , & nil , 1 ) ;
free ( ks ) ;
free ( vs ) ;
}
2006-06-21 20:07:46 +10:00
char * * env_export_arr ( int recalc )
2005-09-23 06:16:52 +10:00
{
2005-09-24 09:15:38 +10:00
if ( recalc & & ! proc_had_barrier )
2005-11-28 09:22:08 +10:00
{
proc_had_barrier = 1 ;
2005-09-23 06:16:52 +10:00
env_universal_barrier ( ) ;
2005-11-28 09:22:08 +10:00
}
2011-12-26 19:18:46 -08:00
2005-10-12 05:23:43 +10:00
if ( has_changed )
2005-09-23 06:16:52 +10:00
{
hash_table_t vals ;
int prev_was_null = 1 ;
2011-12-26 19:18:46 -08:00
int pos = 0 ;
2005-09-23 06:16:52 +10:00
int i ;
2005-09-27 00:47:03 +10:00
debug ( 4 , L " env_export_arr() recalc " ) ;
2011-12-26 19:18:46 -08:00
2005-09-23 06:16:52 +10:00
hash_init ( & vals , & hash_wcs_func , & hash_wcs_cmp ) ;
2011-12-26 19:18:46 -08:00
2006-11-26 23:09:43 +10:00
get_exported ( top , & vals ) ;
2011-12-26 19:18:46 -08:00
2011-12-28 12:36:47 -08:00
wcstring_list_t uni ;
env_universal_get_names2 ( uni , 1 , 0 ) ;
for ( i = 0 ; i < uni . size ( ) ; i + + )
2005-09-23 06:16:52 +10:00
{
2011-12-28 12:36:47 -08:00
const wchar_t * key = uni . at ( i ) . c_str ( ) ;
const wchar_t * val = env_universal_get ( key ) ;
2007-01-19 02:29:22 +10:00
if ( wcscmp ( val , ENV_NULL ) & & ! hash_get ( & vals , key ) )
2005-09-23 06:16:52 +10:00
hash_put ( & vals , key , val ) ;
}
export_buffer . used = 0 ;
2011-12-26 19:18:46 -08:00
2005-09-23 06:16:52 +10:00
hash_foreach2 ( & vals , & export_func2 , & export_buffer ) ;
hash_destroy ( & vals ) ;
2011-12-26 19:18:46 -08:00
export_arr = ( char * * ) realloc ( export_arr ,
2005-09-23 06:16:52 +10:00
sizeof ( char * ) * ( hash_get_count ( & vals ) + 1 ) ) ;
2011-12-26 19:18:46 -08:00
2005-09-23 06:16:52 +10:00
for ( i = 0 ; i < export_buffer . used ; i + + )
{
if ( prev_was_null )
{
export_arr [ pos + + ] = & export_buffer . buff [ i ] ;
debug ( 3 , L " %s " , & export_buffer . buff [ i ] ) ;
}
prev_was_null = ( export_buffer . buff [ i ] = = 0 ) ;
}
2005-09-20 23:26:39 +10:00
export_arr [ pos ] = 0 ;
has_changed = 0 ;
2005-09-23 06:16:52 +10:00
2005-09-20 23:26:39 +10:00
}
2011-12-26 19:18:46 -08:00
return export_arr ;
2005-09-20 23:26:39 +10:00
}
2011-12-26 19:18:46 -08:00
env_vars : : env_vars ( const wchar_t * const * keys )
{
ASSERT_IS_MAIN_THREAD ( ) ;
for ( size_t i = 0 ; keys [ i ] ; i + + ) {
2012-01-12 03:57:38 +05:30
const wcstring val = env_get_string ( keys [ i ] ) ;
if ( ! val . empty ( ) ) {
vars [ keys [ i ] ] = wcsdup ( val . c_str ( ) ) ;
2011-12-26 19:18:46 -08:00
}
}
}
env_vars : : env_vars ( ) { }
const wchar_t * env_vars : : get ( const wchar_t * key ) const
{
std : : map < wcstring , wcstring > : : const_iterator iter = vars . find ( key ) ;
return ( iter = = vars . end ( ) ? NULL : iter - > second . c_str ( ) ) ;
}
const wchar_t * const env_vars : : highlighting_keys [ ] = { L " PATH " , L " CDPATH " , L " HIGHLIGHT_DELAY " , NULL } ;