Beispiel #1
0
bool env_exist(const wchar_t *key, int mode)
{
    env_node_t *env;
    const wchar_t *item = NULL;

    CHECK(key, false);

    /*
      Read only variables all exist, and they are all global. A local
      version can not exist.
    */
    if (!(mode & ENV_LOCAL) && !(mode & ENV_UNIVERSAL))
    {
        if (is_read_only(key) || is_electric(key))
        {
            //Such variables are never exported
            if (mode & ENV_EXPORT)
            {
                return false;
            }
            else if (mode & ENV_UNEXPORT)
            {
                return true;
            }
            return true;
        }
    }

    if (!(mode & ENV_UNIVERSAL))
    {
        env = (mode & ENV_GLOBAL)?global_env:top;

        while (env != 0)
        {
            var_table_t::iterator result = env->env.find(key);

            if (result != env->env.end())
            {
                const var_entry_t &res = result->second;

                if (mode & ENV_EXPORT)
                {
                    return res.exportv;
                }
                else if (mode & ENV_UNEXPORT)
                {
                    return ! res.exportv;
                }

                return true;
            }

            if (mode & ENV_LOCAL)
                break;

            env = env->next_scope_to_search();
        }
    }

    if (!(mode & ENV_LOCAL) && !(mode & ENV_GLOBAL))
    {
        if (! get_proc_had_barrier())
        {
            set_proc_had_barrier(true);
            env_universal_barrier();
        }

        item = env_universal_get(key);

        if (item != NULL)
        {
            if (mode & ENV_EXPORT)
            {
                return env_universal_get_export(key) == 1;
            }
            else if (mode & ENV_UNEXPORT)
            {
                return env_universal_get_export(key) == 0;
            }

            return 1;
        }
    }

    return 0;
}
Beispiel #2
0
int env_set(const wcstring &key, const wchar_t *val, int var_mode)
{
    ASSERT_IS_MAIN_THREAD();
    bool has_changed_old = has_changed_exported;
    bool has_changed_new = false;
    int done=0;

    int is_universal = 0;

    if (val && contains(key, L"PWD", L"HOME"))
    {
        /* Canoncalize our path; if it changes, recurse and try again. */
        wcstring val_canonical = val;
        path_make_canonical(val_canonical);
        if (val != val_canonical)
        {
            return env_set(key, val_canonical.c_str(), var_mode);
        }
    }

    if ((var_mode & ENV_USER) && is_read_only(key))
    {
        return ENV_PERM;
    }

    if (key == L"umask")
    {
        wchar_t *end;

        /*
         Set the new umask
         */
        if (val && wcslen(val))
        {
            errno=0;
            long mask = wcstol(val, &end, 8);

            if (!errno && (!*end) && (mask <= 0777) && (mask >= 0))
            {
                umask(mask);
            }
        }
        /* Do not actually create a umask variable, on env_get, it will be calculated dynamically */
        return 0;
    }

    /*
     Zero element arrays are internaly not coded as null but as this
     placeholder string
     */
    if (!val)
    {
        val = ENV_NULL;
    }

    if (var_mode & ENV_UNIVERSAL)
    {
        bool exportv;
        if (var_mode & ENV_EXPORT)
        {
            // export
            exportv = true;
        }
        else if (var_mode & ENV_UNEXPORT)
        {
            // unexport
            exportv = false;
        }
        else
        {
            // not changing the export
            exportv = env_universal_get_export(key);
        }
        env_universal_set(key, val, exportv);
        is_universal = 1;

    }
    else
    {
        // Determine the node

        env_node_t *preexisting_node = env_get_node(key);
        bool preexisting_entry_exportv = false;
        if (preexisting_node != NULL)
        {
            var_table_t::const_iterator result = preexisting_node->env.find(key);
            assert(result != preexisting_node->env.end());
            const var_entry_t &entry = result->second;
            if (entry.exportv)
            {
                preexisting_entry_exportv = true;
                has_changed_new = true;
            }
        }

        env_node_t *node = NULL;
        if (var_mode & ENV_GLOBAL)
        {
            node = global_env;
        }
        else if (var_mode & ENV_LOCAL)
        {
            node = top;
        }
        else if (preexisting_node != NULL)
        {
            node = preexisting_node;

            if ((var_mode & (ENV_EXPORT | ENV_UNEXPORT)) == 0)
            {
                // use existing entry's exportv
                var_mode = preexisting_entry_exportv ? ENV_EXPORT : 0;
            }
        }
        else
        {
            if (! get_proc_had_barrier())
            {
                set_proc_had_barrier(true);
                env_universal_barrier();
            }

            if (env_universal_get(key))
            {
                bool exportv;
                if (var_mode & ENV_EXPORT)
                {
                    exportv = true;
                }
                else if (var_mode & ENV_UNEXPORT)
                {
                    exportv = false;
                }
                else
                {
                    exportv = env_universal_get_export(key);
                }

                env_universal_set(key, val, exportv);
                is_universal = 1;

                done = 1;

            }
            else
            {
                /*
                 New variable with unspecified scope. The default
                 scope is the innermost scope that is shadowing,
                 which will be either the current function or the
                 global scope.
                 */
                node = top;
                while (node->next && !node->new_scope)
                {
                    node = node->next;
                }
            }
        }

        if (!done)
        {
            // Set the entry in the node
            // Note that operator[] accesses the existing entry, or creates a new one
            var_entry_t &entry = node->env[key];
            if (entry.exportv)
            {
                // this variable already existed, and was exported
                has_changed_new = true;
            }
            entry.val = val;
            if (var_mode & ENV_EXPORT)
            {
                // the new variable is exported
                entry.exportv = true;
                node->exportv = true;
                has_changed_new = true;
            }
            else
            {
                entry.exportv = false;
            }

            if (has_changed_old || has_changed_new)
                mark_changed_exported();
        }

    }

    if (!is_universal)
    {
        event_t ev = event_t::variable_event(key);
        ev.arguments.reserve(3);
        ev.arguments.push_back(L"VARIABLE");
        ev.arguments.push_back(L"SET");
        ev.arguments.push_back(key);

        //  debug( 1, L"env_set: fire events on variable %ls", key );
        event_fire(&ev);
        //  debug( 1, L"env_set: return from event firing" );
    }

    react_to_variable_change(key);

    return 0;
}
Beispiel #3
0
int env_set(const wcstring &key, const wchar_t *val, int var_mode)
{
    ASSERT_IS_MAIN_THREAD();
	env_node_t *node = NULL;
	bool has_changed_old = has_changed_exported;
	bool has_changed_new = false;
	var_entry_t *e=0;	
	int done=0;
    
	int is_universal = 0;
    
	if( val && contains( key, L"PWD", L"HOME" ) )
	{
        /* Canoncalize our path; if it changes, recurse and try again. */
        wcstring val_canonical = val;
        path_make_canonical(val_canonical);
        if (val != val_canonical) {
            return env_set( key, val_canonical.c_str(), var_mode );
        }
	}
    
	if( (var_mode & ENV_USER ) && is_read_only(key) )
	{
		return ENV_PERM;
	}
	
	if (key == L"umask")
	{
		wchar_t *end;

		/*
         Set the new umask
         */
		if( val && wcslen(val) )
		{				
			errno=0;
			long mask = wcstol( val, &end, 8 );
            
			if( !errno && (!*end) && (mask <= 0777) && (mask >= 0) )
			{
				umask( mask );
			}
		}
		/*
         Do not actually create a umask variable, on env_get, it will
         be calculated dynamically
         */
		return 0;
	}
    
	/*
     Zero element arrays are internaly not coded as null but as this
     placeholder string
     */
	if( !val )
	{
		val = ENV_NULL;
	}
	
	if( var_mode & ENV_UNIVERSAL )
	{
		int exportv = 0;
        
		if( !(var_mode & ENV_EXPORT ) &&
           !(var_mode & ENV_UNEXPORT ) )
		{
			env_universal_get_export( key );
		}
		else 
		{
			exportv = (var_mode & ENV_EXPORT );
		}
		
		env_universal_set(key, val, exportv);
		is_universal = 1;
        
	}
	else
	{
		
		node = env_get_node( key );
		if( node )
		{
			var_table_t::iterator result = node->env.find(key);
            assert(result != node->env.end());
            e  = result->second;
                        
			if( e->exportv )
			{
				has_changed_new = true;
			}
		}
        
		if( (var_mode & ENV_LOCAL) || 
           (var_mode & ENV_GLOBAL) )
		{
			node = ( var_mode & ENV_GLOBAL )?global_env:top;
		}
		else
		{
			if( node )
			{
				if( !(var_mode & ENV_EXPORT ) &&
                   !(var_mode & ENV_UNEXPORT ) )
				{				
					var_mode = e->exportv?ENV_EXPORT:0;
				}
			}
			else
			{
				if( ! get_proc_had_barrier())
				{
					set_proc_had_barrier(true);
					env_universal_barrier();
				}
				
				if( env_universal_get( key ) )
				{
					int exportv = 0;
                    
					if( !(var_mode & ENV_EXPORT ) &&
                       !(var_mode & ENV_UNEXPORT ) )
					{
						env_universal_get_export( key );
					}
					else 
					{
						exportv = (var_mode & ENV_EXPORT );
					}
					
					env_universal_set(key, val, exportv);
					is_universal = 1;
					
					done = 1;
                    
				}
				else
				{
					/*
                     New variable with unspecified scope. The default
                     scope is the innermost scope that is shadowing,
                     which will be either the current function or the
                     global scope.				   
                     */
					node = top;
					while( node->next && !node->new_scope )
					{
						node = node->next;
					}
				}
			}
		}
        
		if( !done )
        {
		    var_entry_t *old_entry = NULL;
		    var_table_t::iterator result = node->env.find(key);
		    if ( result != node->env.end() )
		    {
				old_entry = result->second;
				node->env.erase(result);
		    }
            
			var_entry_t *entry = NULL;
			if( old_entry )
            {
			    entry = old_entry;
				
			    if( (var_mode & ENV_EXPORT) || entry->exportv )
                {
                    entry->exportv = !!(var_mode & ENV_EXPORT);
                    has_changed_new = true;		
                }
            }	
			else
            {
			    entry = new var_entry_t;
                
			    if( var_mode & ENV_EXPORT)
                {
                    entry->exportv = 1;
                    has_changed_new = true;		
                }
			    else
                {
                    entry->exportv = 0;
                }
				
            }
            
			entry->val = val;
			node->env[key] = entry;
            
			if( entry->exportv )
            {
			    node->exportv=1;
            }
            
            if (has_changed_old || has_changed_new)
                mark_changed_exported();
        }
        
    }
    
    if( !is_universal )
    {
        event_t ev = event_t::variable_event(key);		
        ev.arguments.reset(new wcstring_list_t);
        ev.arguments->push_back(L"VARIABLE");
        ev.arguments->push_back(L"SET");
        ev.arguments->push_back(key);
		
        //	debug( 1, L"env_set: fire events on variable %ls", key );	
        event_fire( &ev );
        //	debug( 1, L"env_set: return from event firing" );	
        ev.arguments.reset(NULL);
    }
    
    react_to_variable_change(key);
    
    return 0;
}