Exportable universal variables

darcs-hash:20050922201652-ac50b-f70e7607b4ace24da4020f2d432718dc335e5bdd.gz
This commit is contained in:
axel 2005-09-23 06:16:52 +10:00
parent fcdaed44d7
commit f971e02256
19 changed files with 539 additions and 203 deletions

View file

@ -328,6 +328,9 @@ tokenize: tokenize.o doc_src/tokenize.c
tokenizer_test: tokenizer.c tokenizer.h util.o wutil.o common.o
$(CC) ${CFLAGS} tokenizer.c util.o wutil.o common.o -D TOKENIZER_TEST $(LDFLAGS) -o $@
key_reader: key_reader.o input_common.o common.o env_universal.o env_universal_common.o util.o wutil.o
$(CC) key_reader.o input_common.o common.o env_universal.o env_universal_common.o util.o wutil.o $(LDFLAGS) -o $@
depend:
makedepend -fMakefile.in -Y *.c

View file

@ -234,7 +234,7 @@ static void print_variables(int include_values, int escape, int scope)
for( i = 0; i < al_get_count(&names); i++ )
{
wchar_t *key = al_get( &names, i );
wchar_t *key = (wchar_t *)al_get( &names, i );
/* Why does expand_escape free its argument ?! */
wchar_t *e_key = escape ? expand_escape(wcsdup(key), 1) : wcsdup(key);
sb_append(sb_out, e_key);
@ -283,13 +283,16 @@ int builtin_set( wchar_t **argv )
{
L"universal", no_argument, 0, 'U'
} ,
{
L"query", no_argument, 0, 'q'
} ,
{
0, 0, 0, 0
}
}
;
wchar_t short_options[] = L"xglenuU";
wchar_t short_options[] = L"xglenuUq";
int argc = builtin_count_args(argv);
@ -298,7 +301,7 @@ int builtin_set( wchar_t **argv )
*/
int local = 0, global = 0, export = 0;
int erase = 0, list = 0, unexport=0;
int universal = 0;
int universal = 0, query=0;
/*
@ -349,6 +352,9 @@ int builtin_set( wchar_t **argv )
case 'U':
universal = 1;
break;
case 'q':
query = 1;
break;
case '?':
return 1;
default:
@ -356,6 +362,20 @@ int builtin_set( wchar_t **argv )
}
}
if( query && (erase || list || global || local || universal || export || unexport ) )
{
sb_append2(sb_err,
argv[0],
BUILTIN_ERR_COMBO,
L"\n",
parser_current_line(),
L"\n",
0);
builtin_print_help( argv[0], sb_err );
return 1;
}
/* Check operation and modifiers sanity */
if( erase && list )
{
@ -394,6 +414,22 @@ int builtin_set( wchar_t **argv )
return 1;
}
if( query )
{
/*
Query mode. Return number of specified variables that do not exist.
*/
int i;
for( i=woptind; i<argc; i++ )
{
if( env_get( argv[i] )==0 )
retcode++;
}
return retcode;
}
/* Parse destination */
if( woptind < argc )
{

View file

@ -882,7 +882,8 @@ g++, javac, java, gcj, lpr, doxygen, whois, find)
version of a POSIX command
- Yanking weird characters from clipboard prints Unicode escapes
- Prefix string in completion display is sometimes incorrect
- Pressing escape when doing a token search breaks things
- Universal variables should be exportable
If you think you have found a bug not described here, please send a
report to <a href="mailto:axel@liljencrantz.se"> axel@liljencrantz.se

View file

@ -7,12 +7,13 @@ The <tt>set</tt> builtin causes fish to assign the variable <tt>VARIABLE_NAME</t
\subsection set-description Description
- <tt>-e</tt> or <tt>--erase</tt> causes the specified environment variables to be erased
- <tt>-U</tt> or <tt>--universal</tt> causes the specified environment variable to be made universal. If this option is supplied, the variable will be shared between all the current users fish instances on the current computer, and will be preserved across restarts of the shell.
- <tt>-g</tt> or <tt>--global</tt> causes the specified environment variable to be made global. If this option is not supplied, the specified variable will dissapear when the current block ends
- <tt>-l</tt> or <tt>--local</tt> forces the specified environment variable to be made local to the current block, even if the variable already exists and is non-local
- <tt>-n</tt> or <tt>--names</tt> List only the names of all defined variables
- <tt>-x</tt> or <tt>--export</tt> causes the specified environment variable to be exported to child processes
- <tt>-q</tt> or <tt>--query</tt> test if the specified variable names are defined. Does not output anything, but the builtins exit status is the number of variables specified that where not defined.
- <tt>-u</tt> or <tt>--unexport</tt> causes the specified environment not to be exported to child processes
- <tt>-U</tt> or <tt>--universal</tt> causes the specified environment variable to be made universal. If this option is supplied, the variable will be shared between all the current users fish instances on the current computer, and will be preserved across restarts of the shell.
- <tt>-x</tt> or <tt>--export</tt> causes the specified environment variable to be exported to child processes
If set is called with no arguments, the names and values of all
environment variables are printed.

226
env.c
View file

@ -38,8 +38,6 @@
#include "reader.h"
#include "parser.h"
#include "env_universal.h"
#include "env_universal.h"
/**
Command used to start fishd
@ -119,6 +117,12 @@ static hash_table_t env_read_only;
*/
static char **export_arr=0;
/**
Buffer used for storing string contents for export_arr
*/
static buffer_t export_buffer;
/**
Flag for checking if we need to regenerate the exported variable
array
@ -200,6 +204,9 @@ void env_init()
char **p;
sb_init( &dyn_var );
b_init( &export_buffer );
/*
These variables can not be altered directly by the user
@ -275,6 +282,8 @@ void env_destroy()
// fwprintf( stderr, L"Filled %d exported vars\n", c1 );
sb_destroy( &dyn_var );
b_destroy( &export_buffer );
while( &top->env != global )
env_pop();
@ -285,13 +294,8 @@ void env_destroy()
hash_destroy( global );
free( top );
if( export_arr != 0 )
{
for( ptr = export_arr; *ptr; ptr++ )
free( *ptr );
free( export_arr );
}
free( export_arr );
}
/**
@ -347,7 +351,18 @@ void env_set( const wchar_t *key,
if( var_mode & ENV_UNIVERSAL )
{
env_universal_set( key, val );
int export = 0;
if( !(var_mode & ENV_EXPORT ) &&
!(var_mode & ENV_UNEXPORT ) )
{
env_universal_get_export( key );
}
else
export = (var_mode & ENV_EXPORT );
env_universal_set( key, val, export );
return;
}
@ -389,7 +404,18 @@ void env_set( const wchar_t *key,
{
if( env_universal_get( key ) )
{
env_universal_set( key, val );
int export = 0;
if( !(var_mode & ENV_EXPORT ) &&
!(var_mode & ENV_UNEXPORT ) )
{
env_universal_get_export( key );
}
else
export = (var_mode & ENV_EXPORT );
env_universal_set( key, val, export );
return;
}
else
@ -602,50 +628,6 @@ void env_pop()
}
}
/**
Recreate the table of global variables used by execv
*/
static void fill_arr( const void *key, const void *val, void *aux )
{
var_entry_t *val_entry = (var_entry_t *)val;
if( val_entry->export )
{
c1++;
wchar_t *wcs_val = wcsdup( val_entry->val );
wchar_t *pos = wcs_val;
int *idx_ptr = (int *)aux;
char *key_str = wcs2str((wchar_t *)key);
char *val_str;
char *woot;
while( *pos )
{
if( *pos == ARRAY_SEP )
*pos = L':';
pos++;
}
val_str = wcs2str( wcs_val );
free( wcs_val );
woot = malloc( sizeof(char)*( strlen(key_str) +
strlen(val_str) + 2) );
strcpy( woot, key_str );
strcat( woot, "=" );
strcat( woot, val_str );
export_arr[*idx_ptr] = woot;
(*idx_ptr)++;
free( key_str );
free( val_str );
}
}
/**
Function used with hash_foreach to insert keys of one table into
@ -660,13 +642,15 @@ static void add_key_to_hash( const void *key,
( !e->export && get_names_show_unexported) )
hash_put( (hash_table_t *)aux, key, 0 );
}
static void add_universal_key_to_hash( const void *key,
const void *data,
void *aux )
static void add_to_hash( const void *k, void *aux )
{
hash_put( (hash_table_t *)aux, key, 0 );
hash_put( (hash_table_t *)aux,
k,
0 );
}
void env_get_names( array_list_t *l, int flags )
{
int show_local = flags & ENV_LOCAL;
@ -718,10 +702,15 @@ void env_get_names( array_list_t *l, int flags )
if( show_universal )
{
if( get_names_show_unexported )
hash_foreach2( &env_universal_var,
add_universal_key_to_hash,
&names );
array_list_t uni_list;
al_init( &uni_list );
env_universal_get_names( &uni_list,
get_names_show_exported,
get_names_show_unexported );
al_foreach2( &uni_list, &add_to_hash, &names );
al_destroy( &uni_list );
}
hash_get_keys( &names, l );
@ -729,35 +718,116 @@ void env_get_names( array_list_t *l, int flags )
}
char **env_export_arr()
static void export_func1( const void *k, const void *v, void *aux )
{
if( has_changed )
var_entry_t *val_entry = (var_entry_t *)v;
if( val_entry->export )
{
int pos=0;
char **ptr;
env_node_t *n=top;
hash_table_t *h = (hash_table_t *)aux;
if( export_arr != 0 )
{
for( ptr = export_arr; *ptr; ptr++ )
free( *ptr );
}
if( !hash_get( h, k ) )
hash_put( h, k, val_entry->val );
}
}
export_arr = realloc( export_arr,
sizeof(char *)*(export_count + 1) );
static void export_func2( const void *k, const void *v, void *aux )
{
wchar_t *key = (wchar_t *)k;
wchar_t *val = (wchar_t *)v;
char *ks = wcs2str( key );
char *vs = wcs2str( val );
char *pos = vs;
buffer_t *out = (buffer_t *)aux;
if( !ks || !vs )
{
die_mem();
}
/*
Make arrays into colon-separated lists
*/
while( *pos )
{
if( *pos == ARRAY_SEP )
*pos = ':';
pos++;
}
int nil = 0;
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 );
}
char **env_export_arr( int recalc)
{
if( recalc )
env_universal_barrier();
if( has_changed || env_universal_update )
{
array_list_t uni;
hash_table_t vals;
env_node_t *n=top;
int prev_was_null=1;
int pos=0;
int i;
debug( 3, L"env_export_arr()" );
hash_init( &vals, &hash_wcs_func, &hash_wcs_cmp );
while( n )
{
hash_foreach2( &n->env, &fill_arr, &pos );
hash_foreach2( &n->env, &export_func1, &vals );
if( n->new_scope )
n = global_env;
else
n = n->next;
n = n->next;
}
al_init( &uni );
env_universal_get_names( &uni, 1, 0 );
for( i=0; i<al_get_count( &uni ); i++ )
{
wchar_t *key = (wchar_t *)al_get( &uni, i );
wchar_t *val = env_universal_get( key );
if( !hash_get( &vals, key ) )
hash_put( &vals, key, val );
}
al_destroy( &uni );
export_buffer.used=0;
hash_foreach2( &vals, &export_func2, &export_buffer );
hash_destroy( &vals );
export_arr = realloc( export_arr,
sizeof(char *)*(hash_get_count( &vals) + 1) );
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);
}
export_arr[pos]=0;
has_changed=0;
env_universal_update=0;
}
return export_arr;
}

2
env.h
View file

@ -89,7 +89,7 @@ void env_pop();
/**
Returns an array containing all exported variables in a format suitable for execv.
*/
char **env_export_arr();
char **env_export_arr( int recalc );
/**
Insert all variable names into l. These are not copies of the strings and should not be freed after use.

View file

@ -41,9 +41,11 @@ wchar_t * path;
wchar_t *user;
void (*start_fishd)();
int env_universal_update=0;
static int barrier_reply = 0;
static void barrier();
void env_universal_barrier();
/**
@ -109,8 +111,12 @@ static int get_socket( int fork_ok )
if( fork_ok )
{
debug( 2, L"Could not connect to socket %d, starting fishd", s );
if( start_fishd )
{
start_fishd();
}
return get_socket( 0 );
}
@ -133,15 +139,35 @@ static int get_socket( int fork_ok )
static void callback( int type, const wchar_t *name, const wchar_t *val )
{
if( type == BARRIER_REPLY )
{
debug( 3, L"Got barrier reply" );
barrier_reply = 1;
}
else
{
env_universal_update=1;
}
}
static void check_connection()
{
if( !init )
return;
if( env_universal_server.killme )
{
debug( 3, L"Lost connection to universal variable server." );
close( env_universal_server.fd );
env_universal_server.fd = -1;
env_universal_server.killme=0;
sb_clear( &env_universal_server.input );
env_universal_read_all();
}
}
void env_universal_init( wchar_t * p, wchar_t *u, void (*sf)() )
{
@ -160,7 +186,7 @@ void env_universal_init( wchar_t * p, wchar_t *u, void (*sf)() )
init = 1;
if( env_universal_server.fd >= 0 )
{
barrier();
env_universal_barrier();
}
debug( 2, L"end env_universal_init()" );
}
@ -208,22 +234,13 @@ int env_universal_read_all()
init = 1;
if( env_universal_server.fd >= 0 )
barrier();
env_universal_barrier();
}
if( env_universal_server.fd != -1 )
{
read_message( &env_universal_server );
if( env_universal_server.killme )
{
debug( 2, L"Lost connection to universal variable server." );
close( env_universal_server.fd );
env_universal_server.fd = -1;
env_universal_server.killme=0;
sb_clear( &env_universal_server.input );
env_universal_read_all();
}
check_connection();
return 1;
}
else
@ -235,40 +252,59 @@ int env_universal_read_all()
wchar_t *env_universal_get( const wchar_t *name )
{
debug( 3, L"env_universal_get( %ls )", name );
if( !init)
return 0;
debug( 2, L"env_universal_get( %ls )", name );
barrier();
if( !name )
return 0;
return (wchar_t *)hash_get( &env_universal_var, name );
env_universal_barrier();
return env_universal_common_get( name );
}
static void barrier()
int env_universal_get_export( const wchar_t *name )
{
return env_universal_common_get_export( name );
}
void env_universal_barrier()
{
message_t *msg;
fd_set fds;
if( !init )
return;
barrier_reply = 0;
/*
Create barrier request
*/
msg= create_message( BARRIER, 0, 0);
msg->count=1;
q_put( &env_universal_server.unsent, msg );
/*
Wait until barrier request has been sent
*/
debug( 3, L"Create barrier" );
while( 1 )
{
try_send_all( &env_universal_server );
check_connection();
if( q_empty( &env_universal_server.unsent ) )
break;
FD_ZERO( &fds );
FD_SET( env_universal_server.fd, &fds );
select( env_universal_server.fd+1, 0, &fds, 0, 0 );
}
/*
Wait for barrier reply
*/
debug( 3, L"Sent barrier request" );
while( !barrier_reply )
{
@ -278,25 +314,31 @@ static void barrier()
env_universal_read_all();
}
debug( 3, L"End barrier" );
}
void env_universal_set( const wchar_t *name, const wchar_t *value )
void env_universal_set( const wchar_t *name, const wchar_t *value, int export )
{
message_t *msg;
if( !init )
return;
debug( 2, L"env_universal_set( %ls, %ls )", name, value );
debug( 3, L"env_universal_set( %ls, %ls )", name, value );
msg = create_message( export?SET_EXPORT:SET,
name,
value);
msg= create_message( SET, name, value);
if( !msg )
{
debug( 1, L"Could not create universal variable message" );
return;
}
msg->count=1;
q_put( &env_universal_server.unsent, msg );
barrier();
env_universal_barrier();
}
void env_universal_remove( const wchar_t *name )
@ -312,5 +354,14 @@ void env_universal_remove( const wchar_t *name )
msg= create_message( ERASE, name, 0);
msg->count=1;
q_put( &env_universal_server.unsent, msg );
barrier();
env_universal_barrier();
}
void env_universal_get_names( array_list_t *l,
int show_exported,
int show_unexported )
{
env_universal_common_get_names( l,
show_exported,
show_unexported );
}

View file

@ -12,6 +12,11 @@
*/
extern connection_t env_universal_server;
/**
Update flag. Set to 1 whenever an update has occured.
*/
extern int env_universal_update;
/**
Initialize the envuni library
*/
@ -25,10 +30,17 @@ void env_universal_destroy();
Get the value of a universal variable
*/
wchar_t *env_universal_get( const wchar_t *name );
/**
Get the export flag of the variable with the specified
name. Returns 0 if the variable doesn't exist.
*/
int env_universal_get_export( const wchar_t *name );
/**
Set the value of a universal variable
*/
void env_universal_set( const wchar_t *name, const wchar_t *val );
void env_universal_set( const wchar_t *name, const wchar_t *val, int export );
/**
Erase a universal variable
*/
@ -36,4 +48,10 @@ void env_universal_remove( const wchar_t *name );
int env_universal_read_all();
void env_universal_get_names( array_list_t *l,
int show_exported,
int show_unexported );
void env_universal_barrier();
#endif

View file

@ -35,12 +35,24 @@
*/
#define SET_MBS "SET"
/**
Non-wide version of the set_export command
*/
#define SET_EXPORT_MBS "SET_EXPORT"
/**
Non-wide version of the erase command
*/
#define ERASE_MBS "ERASE"
/**
Non-wide version of the barrier command
*/
#define BARRIER_MBS "BARRIER"
/**
Non-wide version of the barrier_reply command
*/
#define BARRIER_REPLY_MBS "BARRIER_REPLY"
/**
@ -48,6 +60,19 @@
*/
#define PARSE_ERR L"Unable to parse universal variable message: '%ls'"
/**
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
{
int export; /**< Whether the variable should be exported */
wchar_t val[0]; /**< The value of the variable */
}
var_entry_t;
static void parse_message( wchar_t *msg,
connection_t *src );
@ -61,6 +86,17 @@ void (*callback)( int type,
const wchar_t *val );
/**
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;
void env_universal_common_init( void (*cb)(int type, const wchar_t *key, const wchar_t *val ) )
{
@ -155,6 +191,7 @@ static int match( const wchar_t *msg, const wchar_t *cmd )
size_t len = wcslen( cmd );
if( wcsncasecmp( msg, cmd, len ) != 0 )
return 0;
if( msg[len] && msg[len]!= L' ' && msg[len] != L'\t' )
return 0;
@ -169,12 +206,13 @@ static void parse_message( wchar_t *msg,
if( msg[0] == L'#' )
return;
if( match( msg, SET_STR ) )
if( match( msg, SET_STR ) || match( msg, SET_EXPORT_STR ))
{
wchar_t *name, *val, *tmp;
name = msg+wcslen(SET_STR);
int export = match( msg, SET_EXPORT_STR );
name = msg+(export?wcslen(SET_EXPORT_STR):wcslen(SET_STR));
while( wcschr( L"\t ", *name ) )
name++;
@ -189,14 +227,22 @@ static void parse_message( wchar_t *msg,
val = unescape( wcsdup(val), 0 );
var_entry_t *entry =
malloc( sizeof(var_entry_t) + sizeof(wchar_t)*(wcslen(val)+1) );
if( !entry )
die_mem();
entry->export=export;
wcscpy( entry->val, val );
remove_entry( key );
hash_put( &env_universal_var, key, val );
hash_put( &env_universal_var, key, entry );
if( callback )
{
callback( SET, key, val );
callback( export?SET_EXPORT:SET, key, val );
}
free(val );
}
else
{
@ -205,7 +251,7 @@ static void parse_message( wchar_t *msg,
}
else if( match( msg, ERASE_STR ) )
{
wchar_t *name, *val, *tmp;
wchar_t *name, *tmp;
name = msg+wcslen(ERASE_STR);
while( wcschr( L"\t ", *name ) )
@ -253,8 +299,11 @@ int try_send( message_t *msg,
int fd )
{
debug( 3,
L"before write of %d chars to fd %d", strlen(msg->body), fd );
int res = write( fd, msg->body, strlen(msg->body) );
if( res == -1 )
{
switch( errno )
@ -282,12 +331,11 @@ int try_send( message_t *msg,
void try_send_all( connection_t *c )
{
debug( 2,
debug( 3,
L"Send all updates to connection on fd %d",
c->fd );
while( !q_empty( &c->unsent) )
{
switch( try_send( (message_t *)q_peek( &c->unsent), c->fd ) )
{
case 1:
@ -295,9 +343,13 @@ void try_send_all( connection_t *c )
break;
case 0:
debug( 1,
L"Socket full, send rest later" );
return;
case -1:
debug( 1,
L"Socket dead!!!" );
c->killme = 1;
return;
}
@ -329,6 +381,7 @@ message_t *create_message( int type,
switch( type )
{
case SET:
case SET_EXPORT:
{
if( !val_in )
{
@ -341,20 +394,20 @@ message_t *create_message( int type,
char *val = wcs2str(esc );
free(esc);
sz = strlen(SET_MBS) + strlen(key) + strlen(val) + 4;
sz = strlen(type==SET?SET_MBS:SET_EXPORT_MBS) + strlen(key) + strlen(val) + 4;
msg = malloc( sizeof( message_t ) + sz );
if( !msg )
die_mem();
strcpy( msg->body, SET_MBS " " );
strcpy( msg->body, (type==SET?SET_MBS:SET_EXPORT_MBS) );
strcat( msg->body, " " );
strcat( msg->body, key );
strcat( msg->body, ":" );
strcat( msg->body, val );
strcat( msg->body, "\n" );
free( val );
break;
@ -406,3 +459,68 @@ message_t *create_message( int type,
msg->count=0;
return msg;
}
/**
Function used with hash_foreach to insert keys of one table into
another
*/
static void add_key_to_hash( const void *key,
const void *data,
void *aux )
{
var_entry_t *e = (var_entry_t *)data;
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 )
{
var_entry_t *e = (var_entry_t *)hash_get( &env_universal_var, name );
if( e )
return e->val;
return 0;
}
int env_universal_common_get_export( const wchar_t *name )
{
var_entry_t *e = (var_entry_t *)hash_get( &env_universal_var, name );
if( e )
return e->export;
return 0;
}
static void enqueue( const void *k,
const void *v,
void *q)
{
const wchar_t *key = (const wchar_t *)k;
const var_entry_t *val = (const var_entry_t *)v;
queue_t *queue = (queue_t *)q;
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 );
}

View file

@ -7,12 +7,24 @@
*/
#define SET_STR L"SET"
/**
The set_export command
*/
#define SET_EXPORT_STR L"SET_EXPORT"
/**
The erase command
*/
#define ERASE_STR L"ERASE"
/**
The barrier command
*/
#define BARRIER_STR L"BARRIER"
/**
The barrier_reply command
*/
#define BARRIER_REPLY_STR L"BARRIER_REPLY"
@ -27,17 +39,13 @@
enum
{
SET,
SET_EXPORT,
ERASE,
BARRIER,
BARRIER_REPLY,
}
;
/**
The table of universal variables
*/
extern hash_table_t env_universal_var;
/**
This struct represents a connection between a universal variable server/client
*/
@ -107,4 +115,25 @@ void env_universal_common_init(void (*cb)(int type, const wchar_t *key, const wc
*/
void env_universal_common_destroy();
/**
Add all variable names to the specified list
*/
void env_universal_common_get_names( array_list_t *l,
int show_exported,
int show_unexported );
/**
Get the value of the variable with the specified name
*/
wchar_t *env_universal_common_get( const wchar_t *name );
/**
Get the export flag of the variable with the specified
name. Returns 0 if the variable doesn't exist.
*/
int env_universal_common_get_export( const wchar_t *name );
void enqueue_all( connection_t *c );
#endif

7
exec.c
View file

@ -289,7 +289,7 @@ static void launch_process( process_t *p )
/* Set the standard input/output channels of the new process. */
execve (wcs2str(p->actual_cmd), wcsv2strv( (const wchar_t **) p->argv), env_export_arr() );
execve (wcs2str(p->actual_cmd), wcsv2strv( (const wchar_t **) p->argv), env_export_arr( 0 ) );
debug( 0,
L"Failed to execute process %ls",
p->actual_cmd );
@ -659,7 +659,6 @@ void exec( job_t *j )
int skip_fork;
/* This call is used so the global environment variable array is regenerated, if needed, before the fork. That way, we avoid a lot of duplicate work where EVERY child would need to generate it */
env_export_arr();
io_data_t pipe_read, pipe_write;
io_data_t *tmp;
@ -720,6 +719,10 @@ void exec( job_t *j )
{
mypipe[1]=-1;
skip_fork=0;
if( p->type == EXTERNAL )
env_export_arr( 1 );
/*
Set up fd:s that will be used in the pipe

33
fishd.c
View file

@ -107,48 +107,29 @@ int get_socket()
return s;
}
void enqueue( const void *k,
const void *v,
void *q)
{
const wchar_t *key = (const wchar_t *)k;
const wchar_t *val = (const wchar_t *)v;
queue_t *queue = (queue_t *)q;
message_t *msg = create_message( SET, key, 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 );
}
void broadcast( int type, const wchar_t *key, const wchar_t *val )
{
connection_t *c;
message_t *msg;
debug( 1, L"Got message %d %ls %ls", type, key, val );
if( !conn )
return;
msg = create_message( type, key, val );
msg = create_message( type, key, val );
/*
Don't merge loops, or try_send_all can free the message prematurely
*/
for( c = conn; c; c=c->next )
{
msg->count++;
q_put( &c->unsent, msg );
}
for( c = conn; c; c=c->next )
{
try_send_all( c );

View file

@ -7,6 +7,7 @@ complete -c set -s u -l unexport -d "Do not export variable to subprocess"
complete -c set -s g -l global -d "Make variable scope global"
complete -c set -s l -l local -d "Make variable scope local"
complete -c set -s U -l universal -d "Make variable scope universal, i.e. shared between all fish terminals"
complete -c set -s q -l query -d "Test if variable is defined"
complete -c set -s h -l help -d "Display help and exit"
function __fish_set_is_first -d 'Test if no non-switch argument has been specified yet'

View file

@ -1,3 +1,6 @@
#
# Completions for the wget command
#
complete -c wget -s V -l version -d "Display version and exit"
complete -c wget -s h -l help -d "Display help and exit"
@ -20,11 +23,11 @@ complete -c wget -l no-clobber -d "Never overwrite files with same name"
complete -c wget -o nc -d "Never overwrite files with same name"
complete -c wget -s c -l continue -d "Continue getting a partially-downloaded file"
complete -c wget -l progress -d "Select progress meter type" -a "
dot\t'Print one dot for every kB of data, 50 dots per line'
dot:default\t'Print one dot for every kB of data, 50 dots per line'
dot:binary\t'Print one dot for every 8 kB of data, 48 dots per line'
dot:mega\t'Print one dot for every 64 kB of data, 48 dots per line'
bar\t'Print progress bar'
dot\t'Print one dot for every kB of data, 50 dots per line'
dot:default\t'Print one dot for every kB of data, 50 dots per line'
dot:binary\t'Print one dot for every 8 kB of data, 48 dots per line'
dot:mega\t'Print one dot for every 64 kB of data, 48 dots per line'
bar\t'Print progress bar'
"
complete -c wget -s N -l timestamping -d "Turn on time-stamping"
complete -c wget -s S -l server-response -d "Print the headers/responses sent by servers"
@ -41,8 +44,8 @@ complete -c wget -s Y -l proxy -d "Toggle proxy support" -xa "on off"
complete -c wget -s Q -l quota -d "Specify download quota for automatic retrievals" -x
complete -c wget -l dns-cache -d "Turn off caching of DNS lookups" -xa "off"
complete -c wget -l restrict-file-names -d "Change which characters found in remote URLs may show up in local file names" -a "
unix\t'Escape slash and non-printing characters'
windows\t'Escape most non-alphabetical characters'
unix\t'Escape slash and non-printing characters'
windows\t'Escape most non-alphabetical characters'
"
# HTTP options

View file

@ -1,3 +1,6 @@
#
# Completions for the yum command
#
#Load rpm completions, since that is where the package completion function is defined
complete -y rpm

View file

@ -53,12 +53,19 @@ end
# Set various color values
#
function set_default -d "Set a universal variable, unless it has already been set"
if not test $$argv[1]
function set_default -d "Set an universal variable, unless it has already been set"
if not set -q $argv[1]
set -U -- $argv
end
end
function set_exported_default -d "Set an exported universal variable, unless it has already been set"
if not set -q $argv[1]
set -Ux -- $argv
end
end
# Regular syntax highlighting colors
set_default fish_color_normal normal
set_default fish_color_command green
@ -83,21 +90,20 @@ set_default fish_pager_color_progress cyan
# Directory history colors
set_default fish_color_history_current cyan
functions -e set_default
#
# Setup the CDPATH variable
#
set -gx CDPATH . ~
set_exported_default CDPATH . ~
#
# Match colors for grep, if supported
#
if grep --color=auto --help 1>/dev/null 2>/dev/null
set -gx GREP_COLOR '97;45'
set -gx -- GREP_OPTIONS '--color=auto'
set_exported_default GREP_COLOR '97;45'
set_exported_default GREP_OPTIONS '--color=auto'
end
#
@ -105,6 +111,9 @@ end
#
if command ls --color=auto --help 1>/dev/null 2>/dev/null
set -gx LS_COLORS $LS_COLORS '*.jar=01;31' '*.doc=35' '*.pdf=35' '*.ps=35' '*.xls=35' '*.swf=35' '*~=37'
set_exported_default LS_COLORS $LS_COLORS '*.jar=01;31' '*.doc=35' '*.pdf=35' '*.ps=35' '*.xls=35' '*.swf=35' '*~=37'
end
functions -e set_default
functions -e set_exported_default

View file

@ -12,17 +12,7 @@
#include <unistd.h>
#include <termcap.h>
static int readch()
{
char arr[1];
if( read( 0, arr, 1 ) < 0 )
{
perror( "read" );
return readch();
}
else
return arr[0];
}
#include "input_common.h"
int writestr( char *str )
{
@ -66,6 +56,9 @@ int main( int argc, char **argv)
struct termios modes, /* so we can change the modes */
savemodes; /* so we can reset the modes when we're done */
input_common_init(0);
tcgetattr(0,&modes); /* get the current terminal modes */
savemodes = modes; /* save a copy so we can reset them */
@ -76,9 +69,9 @@ int main( int argc, char **argv)
tcsetattr(0,TCSANOW,&modes); /* set the new modes */
while(1)
{
if( (c=readch()) == EOF )
if( (c=input_common_readch(0)) == EOF )
break;
if((c > 31) && (c != 127) )
if( (c > 31) && (c != 127) )
sprintf( scratch, "dec: %d hex: %x char: %c\n", c, c, c );
else
sprintf( scratch, "dec: %d hex: %x\n", c, c );
@ -86,6 +79,8 @@ int main( int argc, char **argv)
}
/* reset the terminal to the saved mode */
tcsetattr(0,TCSANOW,&savemodes);
input_common_destroy();
}
return 0;

View file

@ -1605,10 +1605,7 @@ static void eval_job( tokenizer *tok )
long long t1=0, t2=0, t3=0;
profile_element_t *p=0;
int skip = 0;
if( !is_block && !is_subshell )
env_universal_read_all();
if( profile )
{
p=malloc( sizeof(profile_element_t));

31
proc.c
View file

@ -45,6 +45,7 @@ Some of the code in this file is based on code from the Glibc manual.
#include "reader.h"
#include "sanity.h"
#include "env.h"
#include "parser.h"
/**
Size of message buffer
@ -540,7 +541,7 @@ static void handle_child_status( pid_t pid, int status )
int found_proc = 0;
job_t *j;
process_t *p;
// char mess[MESS_SIZE];
char mess[MESS_SIZE];
found_proc = 0;
/*
snprintf( mess,
@ -587,13 +588,12 @@ static void handle_child_status( pid_t pid, int status )
}
if( !is_interactive )
if( WIFSIGNALED( status ) &&
( WTERMSIG(status)==SIGINT ||
WTERMSIG(status)==SIGQUIT ) )
{
if( WIFSIGNALED( status ) &&
( WTERMSIG(status)==SIGINT ||
WTERMSIG(status)==SIGQUIT ) )
{
if( !is_interactive_session )
{
struct sigaction act;
sigemptyset( & act.sa_mask );
act.sa_flags=0;
@ -602,6 +602,23 @@ static void handle_child_status( pid_t pid, int status )
sigaction( SIGQUIT, &act, 0 );
kill( getpid(), WTERMSIG(status) );
}
else
{
block_t *c = current_block;
snprintf( mess,
MESS_SIZE,
"Process %ls from job %ls exited through signal, breaking loops\n",
p->actual_cmd,
j->command );
write( 2, mess, strlen(mess ));
while( c )
{
c->skip=1;
c=c->outer;
}
}
}
if( !found_proc )