aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--env.c2
-rw-r--r--env_universal.c5
-rw-r--r--env_universal_common.c4
-rw-r--r--exec.c137
-rw-r--r--fishd.c137
-rw-r--r--parser.c2
-rw-r--r--proc.c147
-rw-r--r--reader.c7
9 files changed, 224 insertions, 222 deletions
diff --git a/ChangeLog b/ChangeLog
index 73010c95..3f55d4f0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2005-09-22 Axel Liljencrantz <axel@liljencrantz.se>
+
+ * env_universal.c, env_universal_common.c, env.c, fishd.c, builtin_set.c, exec.c, init/fish_interactive.fish: Exportable universal variables
+
+
2005-09-20 Axel Liljencrantz <axel@liljencrantz.se>
* exec.c, reader.c (exec_read_io_buffer, run_pager): Don't leak file descriptors when showing completion pager
diff --git a/env.c b/env.c
index ea146196..cf96515e 100644
--- a/env.c
+++ b/env.c
@@ -42,7 +42,7 @@
/**
Command used to start fishd
*/
-#define FISHD_CMD L"if which fishd >/dev/null ^/dev/null; fishd ^/tmp/fish.%s.log; end"
+#define FISHD_CMD L"fishd ^/tmp/fish.%s.log"
/**
At init, we read all the environment variables from this array
diff --git a/env_universal.c b/env_universal.c
index 3f73d7b4..e9b4b492 100644
--- a/env_universal.c
+++ b/env_universal.c
@@ -228,13 +228,15 @@ int env_universal_read_all()
return 0;
debug( 2, L"Get new fishd connection" );
-
+
init = 0;
env_universal_server.fd = get_socket(1);
init = 1;
if( env_universal_server.fd >= 0 )
+ {
env_universal_barrier();
+ }
}
if( env_universal_server.fd != -1 )
@@ -252,7 +254,6 @@ 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;
diff --git a/env_universal_common.c b/env_universal_common.c
index 6aa42810..175fb28e 100644
--- a/env_universal_common.c
+++ b/env_universal_common.c
@@ -313,7 +313,7 @@ int try_send( message_t *msg,
default:
debug( 1,
- L"Error while sending message to fd %d. Closing connection",
+ L"Error while sending universal variable message to fd %d. Closing connection",
fd );
wperror( L"write" );
@@ -348,8 +348,6 @@ void try_send_all( connection_t *c )
return;
case -1:
- debug( 1,
- L"Socket dead!!!" );
c->killme = 1;
return;
}
diff --git a/exec.c b/exec.c
index c280aba0..953afd87 100644
--- a/exec.c
+++ b/exec.c
@@ -61,6 +61,20 @@ pid_t getpgid( pid_t pid );
*/
#define FORK_ERROR L"Could not create child process - exiting"
+
+static void close_loop( int fd )
+{
+ while( close(fd) == -1 )
+ {
+ if( errno != EINTR )
+ {
+ debug( 1, FD_ERROR, fd );
+ wperror( L"close" );
+ }
+ }
+}
+
+
/**
Make sure the fd used by this redirection is not used by i.e. a pipe.
*/
@@ -102,7 +116,7 @@ static void handle_child_io( io_data_t *io )
{
if( env_universal_server.fd >= 0 )
- close( env_universal_server.fd );
+ close_loop( env_universal_server.fd );
for( ; io; io=io->next )
{
@@ -122,8 +136,11 @@ static void handle_child_io( io_data_t *io )
}
- if( close(io->fd) == -1 )
+ while( close(io->fd) == -1 )
{
+ if( errno != EINTR )
+ break;
+
/* debug( 1,
FD_ERROR,
io->fd );
@@ -155,14 +172,7 @@ static void handle_child_io( io_data_t *io )
wperror( L"dup2" );
exit(1);
}
- if( close( tmp ) == -1 )
- {
- debug( 1,
- FD_ERROR,
- io->fd );
- wperror( L"close" );
- exit(1);
- }
+ close_loop( tmp );
}
break;
case IO_FD:
@@ -203,11 +213,11 @@ static void handle_child_io( io_data_t *io )
if( fd_to_dup )
{
- close( io->pipe_fd[0]);
- close( io->pipe_fd[1]);
+ close_loop( io->pipe_fd[0]);
+ close_loop( io->pipe_fd[1]);
}
else
- close( io->pipe_fd[fd_to_dup] );
+ close_loop( io->pipe_fd[fd_to_dup] );
/*
if( close( io[i].pipe_fd[ io->fd ] ) == -1 )
@@ -314,37 +324,44 @@ static int has_fd( io_data_t *d, int fd )
void exec_read_io_buffer( io_data_t *d )
{
- if( close( d->pipe_fd[1] ) == -1 )
- {
- debug( 1, PIPE_ERROR );
- wperror( L"close" );
- }
+ close_loop(d->pipe_fd[1] );
if( d->io_mode == IO_BUFFER )
- {
-
- if( fcntl( d->pipe_fd[0], F_SETFL, 0 ) )
+ {
+/* if( fcntl( d->pipe_fd[0], F_SETFL, 0 ) )
{
wperror( L"fcntl" );
return;
}
-
+*/
debug( 3, L"exec_read_io_buffer: blocking read on fd %d", d->pipe_fd[0] );
while(1)
{
char b[4096];
int l;
- l=read_blocked( d->pipe_fd[0], b, 4096 );
+ l=read_blocked( d->pipe_fd[0], b, 4096 );
if( l==0 )
{
break;
}
else if( l<0 )
{
- debug( 1,
- L"An error occured while reading output from code block on fd %d", d->pipe_fd[0] );
- wperror( L"exec_read_io_buffer" );
+ /*
+ exec_read_io_buffer is only called on jobs that have
+ exited, and will therefore never block. But a broken
+ pipe seems to cause some flags to reset, causing the
+ EOF flag to not be set. Therefore, EAGAIN is ignored
+ and we exit anyway.
+ */
+ if( errno != EAGAIN )
+ {
+ debug( 1,
+ L"An error occured while reading output from code block on fd %d",
+ d->pipe_fd[0] );
+ wperror( L"exec_read_io_buffer" );
+ }
+
break;
}
else
@@ -375,7 +392,9 @@ io_data_t *exec_make_io_buffer()
free( buffer_redirect );
return 0;
}
- else if( fcntl( buffer_redirect->pipe_fd[0], F_SETFL, O_NONBLOCK ) )
+ else if( fcntl( buffer_redirect->pipe_fd[0],
+ F_SETFL,
+ O_NONBLOCK ) )
{
debug( 1, PIPE_ERROR );
wperror( L"fcntl" );
@@ -388,12 +407,8 @@ io_data_t *exec_make_io_buffer()
void exec_free_io_buffer( io_data_t *io_buffer )
{
- if( close( io_buffer->pipe_fd[0] ) == -1)
- {
- debug( 1, PIPE_ERROR );
- wperror( L"close" );
-
- }
+
+ close_loop( io_buffer->pipe_fd[0] );
/*
Dont free fd for writing. This should already be free'd before calling exec_read_io_buffer on the buffer
@@ -457,13 +472,6 @@ static io_data_t *io_transmogrify( io_data_t * in )
}
out->old_fd = fd;
-/*
- fwprintf( stderr,
- L"Replacing call to redirect %d to file '%ls' with call to redirect to fd %d\n",
- in->fd,
- in->filename,
- fd );
-*/
break;
}
}
@@ -484,13 +492,7 @@ static void io_untransmogrify( io_data_t * in, io_data_t *out )
switch( in->io_mode )
{
case IO_FILE:
- if( close( out->old_fd ) == -1 )
- {
- debug( 1,
- FILE_ERROR,
- in->filename );
- wperror( L"close" );
- }
+ close_loop( out->old_fd );
break;
}
free(out);
@@ -567,11 +569,6 @@ static void io_print( io_data_t *io )
static int handle_new_child( job_t *j, process_t *p )
{
- /*
- If we do not output to stdout, builtin IO will not appear.
- I have no idea why...
- */
- //fwprintf( stdout, L"" );
if(is_interactive && !is_subshell && !is_block)
{
@@ -664,10 +661,8 @@ void exec( job_t *j )
io_data_t *tmp;
io_data_t *io_buffer =0;
-
-// if( j->job_id > 3 )
-
- debug( 2, L"Exec job %ls with id %d", j->command, j->job_id );
+
+ debug( 3, L"Exec job %ls with id %d", j->command, j->job_id );
if( j->first_process->type==INTERNAL_EXEC )
{
@@ -694,25 +689,12 @@ void exec( job_t *j )
if( block_io )
{
-// fwprintf( stderr, L"Before\n" );
-// io_print( j->io );
-
if( j->io )
j->io = io_add( io_duplicate(block_io), j->io );
else
j->io=io_duplicate(block_io);
-
-// fwprintf( stderr, L"After\n" );
-// io_print( j->io );
-
}
-/*
- if true;
- read foo; read bar; read baz;
- end <foo.txt
-*/
-
j->io = io_add( j->io, &pipe_write );
for (p = j->first_process; p; p = p->next)
@@ -722,12 +704,10 @@ void exec( job_t *j )
if( p->type == EXTERNAL )
env_export_arr( 1 );
-
/*
Set up fd:s that will be used in the pipe
*/
-// fwprintf( stderr, L"Create process %ls\n", p->actual_cmd );
if( p == j->first_process->next )
{
@@ -924,7 +904,7 @@ void exec( job_t *j )
if( close_stdin )
{
// fwprintf( stderr, L"Close builtin_stdin\n" );
- close( builtin_stdin );
+ close_loop( builtin_stdin );
}
break;
}
@@ -1146,7 +1126,7 @@ void exec( job_t *j )
Close the pipe the current process uses to read from the previous process_t
*/
if( pipe_read.pipe_fd[0] >= 0 )
- close( pipe_read.pipe_fd[0] );
+ close_loop( pipe_read.pipe_fd[0] );
/*
Set up the pipe the next process uses to read from the current process_t
*/
@@ -1159,15 +1139,11 @@ void exec( job_t *j )
*/
if( p->next )
{
- if( close(mypipe[1]) != 0 )
- {
- debug( 1, PIPE_ERROR );
- wperror( L"close" );
- }
+ close_loop(mypipe[1]);
}
}
-// fwprintf( stderr, L"Job is constructedk\n" );
+ debug( 3, L"Job is constructed" );
j->io = io_remove( j->io, &pipe_read );
j->io = io_remove( j->io, &pipe_write );
@@ -1175,10 +1151,7 @@ void exec( job_t *j )
for( tmp = block_io; tmp; tmp=tmp->next )
j->io = io_remove( j->io, tmp );
-
-// assert( !job_is_stopped(j));
j->constructed = 1;
-// ggg( j->command, j->io );
if( !j->fg )
{
diff --git a/fishd.c b/fishd.c
index 2cf4e599..bd18b6d0 100644
--- a/fishd.c
+++ b/fishd.c
@@ -28,20 +28,42 @@ down and save.
#include "wutil.h"
#include "env_universal_common.h"
-
+/**
+ Maximum length of socket filename
+*/
#ifndef UNIX_PATH_MAX
#define UNIX_PATH_MAX 100
#endif
-#define GREETING "#Fish universal variable daemon\n#Lines beginning with '#' are ignored\n#Syntax:\n#SET VARNAME:VALUE\n#or\n#ERASE VARNAME\n#Where VALUE is the escaped value of the variable\n#Backslash escapes and \\xxx hexadecimal style escapes are supported\n"
-#define FILE ".fishd"
+/**
+ Small greeting to show that fishd is running
+*/
+#define GREETING "#Fish universal variable daemon\n"
+/**
+ The name of the save file. The hostname is appended to this.
+*/
+#define FILE ".fishd."
+/**
+ Maximum length of hostname. Longer hostnames are truncated
+*/
+#define HOSTNAME_LEN 32
+
+/**
+ The list of connections to clients
+*/
static connection_t *conn;
-static int sock;
+/**
+ The socket to accept new clients on
+*/
+static int sock;
-int get_socket()
+/**
+ Connects to the fish socket
+*/
+static int get_socket()
{
int s, len;
struct sockaddr_un local;
@@ -107,7 +129,10 @@ int get_socket()
return s;
}
-void broadcast( int type, const wchar_t *key, const wchar_t *val )
+/**
+ Event handler. Broadcasts updates to all clients.
+*/
+static void broadcast( int type, const wchar_t *key, const wchar_t *val )
{
connection_t *c;
message_t *msg;
@@ -136,7 +161,10 @@ void broadcast( int type, const wchar_t *key, const wchar_t *val )
}
}
-void daemonize()
+/**
+ Make program into a creature of the night.
+*/
+static void daemonize()
{
/*
Fork, and let parent exit
@@ -178,77 +206,75 @@ void daemonize()
}
-
-void load()
+/**
+ Load or save all variables
+*/
+void load_or_save( int save)
{
struct passwd *pw;
char *name;
char *dir = getenv( "HOME" );
+ char hostname[HOSTNAME_LEN];
+ connection_t c;
+
if( !dir )
{
pw = getpwuid( getuid() );
dir = pw->pw_dir;
}
-
- name = malloc( strlen(dir)+ strlen(FILE)+ 2 );
+
+ gethostname( hostname, HOSTNAME_LEN );
+
+ name = malloc( strlen(dir)+ strlen(FILE)+ strlen(hostname) + 2 );
strcpy( name, dir );
strcat( name, "/" );
strcat( name, FILE );
+ strcat( name, hostname );
- debug( 1, L"Open file for loading: '%s'", name );
-
- connection_t load;
- load.fd = open( name, O_RDONLY);
+ debug( 1, L"Open file for %s: '%s'",
+ save?"saving":"loading",
+ name );
+ c.fd = open( name, save?(O_CREAT | O_TRUNC | O_WRONLY):O_RDONLY, 0600);
free( name );
- if( load.fd == -1 )
+ if( c.fd == -1 )
{
- debug( 0, L"Could not open save file. No previous saves?" );
+ debug( 1, L"Could not open load/save file. No previous saves?" );
+ wperror( L"open" );
+
}
- debug( 1, L"Load input file on fd %d", load.fd );
- sb_init( &load.input );
- memset (&load.wstate, '\0', sizeof (mbstate_t));
- read_message( &load );
- sb_destroy( &load.input );
- close( load.fd );
+ debug( 1, L"File open on fd %d", c.fd );
+
+ sb_init( &c.input );
+ memset (&c.wstate, '\0', sizeof (mbstate_t));
+ q_init( &c.unsent );
+
+ if( save )
+ enqueue_all( &c );
+ else
+ read_message( &c );
+
+ q_destroy( &c.unsent );
+ sb_destroy( &c.input );
+ close( c.fd );
+
}
-void save()
+static void load()
{
- struct passwd *pw;
- char *name;
- char *dir = getenv( "HOME" );
- if( !dir )
- {
- pw = getpwuid( getuid() );
- dir = pw->pw_dir;
- }
-
- name = malloc( strlen(dir)+ strlen(FILE)+ 2 );
- strcpy( name, dir );
- strcat( name, "/" );
- strcat( name, FILE );
-
- debug( 1, L"Open file for saving: '%s'", name );
-
- connection_t save;
- save.fd = open( name, O_CREAT | O_TRUNC | O_WRONLY);
- free( name );
+ load_or_save(0);
+}
- if( save.fd == -1 )
- {
- debug( 0, L"Could not open save file" );
- wperror( L"open" );
- exit(1);
- }
- debug( 1, L"File open on fd %d'", save.fd );
- q_init( &save.unsent );
- enqueue_all( &save );
- close( save.fd );
- q_destroy( &save.unsent );
+
+static void save()
+{
+ load_or_save(1);
}
+/**
+ Do all sorts of boring initialization.
+*/
static void init()
{
program_name=L"fishd";
@@ -268,6 +294,7 @@ static void init()
load();
}
+
int main( int argc, char ** argv )
{
int child_socket, t;
@@ -362,7 +389,7 @@ int main( int argc, char ** argv )
won't lose everything on a system crash
*/
update_count++;
- if( update_count >= 8 )
+ if( update_count >= 64 )
{
save();
update_count = 0;
diff --git a/parser.c b/parser.c
index 6a8fa932..7aa04787 100644
--- a/parser.c
+++ b/parser.c
@@ -1762,7 +1762,7 @@ static void eval_job( tokenizer *tok )
}
}
- if( is_subshell )
+ if( is_subshell || is_block )
job_do_notification();
// debug( 2, L"end eval_job()\n" );
}
diff --git a/proc.c b/proc.c
index 86b23a0b..911edae3 100644
--- a/proc.c
+++ b/proc.c
@@ -606,12 +606,12 @@ static void handle_child_status( pid_t pid, int status )
{
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 ));
+ 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 )
{
@@ -946,12 +946,12 @@ static void read_try( job_t *j )
if( buff )
{
- // fwprintf( stderr, L"proc::read_try('%ls')\n", j->command );
+ debug( 3, L"proc::read_try('%ls')\n", j->command );
while(1)
{
char b[BUFFER_SIZE];
int l;
- //fwprintf( stderr, L"read...\n");
+
l=read_blocked( buff->pipe_fd[0], b, BUFFER_SIZE );
if( l==0 )
{
@@ -964,8 +964,7 @@ static void read_try( job_t *j )
debug( 1,
L"An error occured while reading output from code block" );
wperror( L"read_try" );
- }
-
+ }
break;
}
else
@@ -987,7 +986,6 @@ void job_continue (job_t *j, int cont)
first_job = j;
j->notified = 0;
-// if( is_interactive )
debug( 3,
L"Continue on job %d (%ls), %ls, %ls",
j->job_id,
@@ -1023,7 +1021,6 @@ void job_continue (job_t *j, int cont)
if( cont )
{
-// fwprintf( stderr, L"tcsetattr\n" );
while( 1 )
{
if( tcsetattr (0, TCSADRAIN, &j->tmodes))
@@ -1045,82 +1042,78 @@ void job_continue (job_t *j, int cont)
}
}
}
- }
- /*
- Send the job a continue signal, if necessary.
- */
- if( cont )
- {
- process_t *p;
- for( p=j->first_process; p; p=p->next )
- p->stopped=0;
- for( p=j->first_process; p; p=p->next )
- {
- if (kill ( p->pid, SIGCONT) < 0)
- {
- wperror (L"kill (SIGCONT)");
- return;
- }
- }
- }
-
- if( j->fg )
- {
- int quit = 0;
-
/*
- Wait for job to report. Looks a bit ugly because it has to
- handle the possibility that a signal is dispatched while
- running job_is_stopped().
- */
- /*
- fwprintf( stderr, L"Wait for %ls (%d)\n", j->command, j->pgid );
+ Send the job a continue signal, if necessary.
*/
- while( !quit )
+ if( cont )
{
- do
+ process_t *p;
+ for( p=j->first_process; p; p=p->next )
+ p->stopped=0;
+ for( p=j->first_process; p; p=p->next )
{
- got_signal = 0;
- quit = job_is_stopped( j ) || job_last_is_completed( j );
+ if (kill ( p->pid, SIGCONT) < 0)
+ {
+ wperror (L"kill (SIGCONT)");
+ return;
+ }
}
- while( got_signal && !quit );
- if( !quit )
+ }
+
+ if( j->fg )
+ {
+ int quit = 0;
+
+ /*
+ Wait for job to report. Looks a bit ugly because it has to
+ handle the possibility that a signal is dispatched while
+ running job_is_stopped().
+ */
+ while( !quit )
{
-
- debug( 3, L"select_try()" );
- switch( select_try(j) )
+ do
+ {
+ got_signal = 0;
+ quit = job_is_stopped( j ) || job_last_is_completed( j );
+ }
+ while( got_signal && !quit );
+ if( !quit )
{
- case 1:
- {
- debug( 3, L"1" );
- read_try( j );
- break;
- }
- case -1:
+ debug( 3, L"select_try()" );
+ switch( select_try(j) )
{
- /*
- If there is no funky IO magic, we can use
- waitpid instead of handling child deaths
- through signals. This gives a rather large
- speed boost (A factor 3 startup time
- improvement on my 300 MHz machine) on
- short-lived jobs.
- */
- debug( 3, L"-1" );
- int status;
- pid_t pid = waitpid(-1, &status, WUNTRACED );
- if( pid > 0 )
- handle_child_status( pid, status );
- break;
- }
+ case 1:
+ {
+ read_try( j );
+ break;
+ }
+
+ case -1:
+ {
+ /*
+ If there is no funky IO magic, we can use
+ waitpid instead of handling child deaths
+ through signals. This gives a rather large
+ speed boost (A factor 3 startup time
+ improvement on my 300 MHz machine) on
+ short-lived jobs.
+ */
+ int status;
+ pid_t pid = waitpid(-1, &status, WUNTRACED );
+ if( pid > 0 )
+ handle_child_status( pid, status );
+ break;
+ }
- }
- }
+ }
+ }
+ }
}
+
}
-
+
if( j->fg )
{
@@ -1141,8 +1134,7 @@ void job_continue (job_t *j, int cont)
debug( 3, L"Set status of %ls to %d", j->command, WEXITSTATUS(p->status) );
proc_set_last_status( j->negate?(WEXITSTATUS(p->status)?0:1):WEXITSTATUS(p->status) );
}
- }
-
+ }
}
/*
Put the shell back in the foreground.
@@ -1202,7 +1194,6 @@ void job_continue (job_t *j, int cont)
}
}
}
-// fwprintf( stderr, L"Job_continue end\n" );
}
void proc_sanity_check()
diff --git a/reader.c b/reader.c
index 7a853cf8..ac547c76 100644
--- a/reader.c
+++ b/reader.c
@@ -1483,6 +1483,13 @@ static void set_signal_handlers()
sigaction( SIGTTOU, &act, 0);
sigaction( SIGCHLD, &act, 0);
+ /*
+ Ignore sigpipe, it is generated if fishd dies, but we can
+ recover.
+ */
+ act.sa_handler=SIG_IGN;
+ sigaction( SIGPIPE, &act, 0);
+
if( is_interactive )
{