aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar liljencrantz <liljencrantz@gmail.com>2007-10-27 04:42:32 +1000
committerGravatar liljencrantz <liljencrantz@gmail.com>2007-10-27 04:42:32 +1000
commit2160777d2f26a7e00c3dc003bf52bf9d40d885c7 (patch)
tree635d559912cba3dec7f00dd7e0e364e54300df79
parenta97faaf664264a356e592118ec99cc26ce4c0e47 (diff)
Implement non-clobbering file io. Use the >? operator for this for now.
darcs-hash:20071026184232-75c98-11edcbc7548c8ad3a2d4b648cb7ae18067569f02.gz
-rw-r--r--exec.c34
-rw-r--r--highlight.c12
-rw-r--r--parser.c9
-rw-r--r--tokenizer.c6
-rw-r--r--tokenizer.h1
5 files changed, 53 insertions, 9 deletions
diff --git a/exec.c b/exec.c
index 660d5dab..dbda6cbb 100644
--- a/exec.c
+++ b/exec.c
@@ -52,10 +52,17 @@
file descriptor redirection error message
*/
#define FD_ERROR _( L"An error occurred while redirecting file descriptor %d" )
+
/**
file redirection error message
*/
#define FILE_ERROR _( L"An error occurred while redirecting file '%ls'" )
+
+/**
+ file redirection clobbering error message
+*/
+#define NOCLOB_ERROR _( L"The file '%ls' already exists" )
+
/**
fork error message
*/
@@ -113,10 +120,10 @@ void exec_close( int fd )
if( n == fd )
{
al_set_long( open_fds,
- i,
- al_get_long( open_fds, al_get_count( open_fds ) -1 ) );
+ i,
+ al_get_long( open_fds, al_get_count( open_fds ) -1 ) );
al_truncate( open_fds,
- al_get_count( open_fds ) -1 );
+ al_get_count( open_fds ) -1 );
break;
}
}
@@ -288,13 +295,24 @@ static int handle_child_io( io_data_t *io )
case IO_FILE:
{
if( (tmp=wopen( io->param1.filename,
- io->param2.flags, OPEN_MASK ) )==-1 )
+ io->param2.flags, OPEN_MASK ) )==-1 )
{
- debug( 1,
- FILE_ERROR,
- io->param1.filename );
+ if( ( io->param2.flags & O_EXCL ) &&
+ ( errno ==EEXIST ) )
+ {
+ debug( 1,
+ NOCLOB_ERROR,
+ io->param1.filename );
+ }
+ else
+ {
+ debug( 1,
+ FILE_ERROR,
+ io->param1.filename );
+
+ wperror( L"open" );
+ }
- wperror( L"open" );
return -1;
}
else if( tmp != io->fd)
diff --git a/highlight.c b/highlight.c
index 603d75b9..8a5f7512 100644
--- a/highlight.c
+++ b/highlight.c
@@ -757,6 +757,7 @@ void highlight_shell( wchar_t * buff,
break;
}
+ case TOK_REDIRECT_NOCLOB:
case TOK_REDIRECT_OUT:
case TOK_REDIRECT_IN:
case TOK_REDIRECT_APPEND:
@@ -825,7 +826,7 @@ void highlight_shell( wchar_t * buff,
if it exists.
*/
if( last_type == TOK_REDIRECT_IN ||
- last_type == TOK_REDIRECT_APPEND )
+ last_type == TOK_REDIRECT_APPEND )
{
if( wstat( target, &buff ) == -1 )
{
@@ -834,6 +835,15 @@ void highlight_shell( wchar_t * buff,
al_push( error, wcsdupcat( L"File \'", target, L"\' does not exist" ) );
}
}
+ if( last_type == TOK_REDIRECT_NOCLOB )
+ {
+ if( wstat( target, &buff ) != -1 )
+ {
+ color[ tok_get_pos( &tok ) ] = HIGHLIGHT_ERROR;
+ if( error )
+ al_push( error, wcsdupcat( L"File \'", target, L"\' exists" ) );
+ }
+ }
}
break;
}
diff --git a/parser.c b/parser.c
index a699219e..916dd79b 100644
--- a/parser.c
+++ b/parser.c
@@ -1462,6 +1462,7 @@ static void parse_job_argument_list( process_t *p,
case TOK_REDIRECT_IN:
case TOK_REDIRECT_APPEND:
case TOK_REDIRECT_FD:
+ case TOK_REDIRECT_NOCLOB:
{
int type = tok_last_type( tok );
io_data_t *new_io;
@@ -1557,6 +1558,12 @@ static void parse_job_argument_list( process_t *p,
new_io->param1.filename = target;
break;
+ case TOK_REDIRECT_NOCLOB:
+ new_io->io_mode = IO_FILE;
+ new_io->param2.flags = O_CREAT | O_EXCL | O_WRONLY;
+ new_io->param1.filename = target;
+ break;
+
case TOK_REDIRECT_IN:
new_io->io_mode = IO_FILE;
new_io->param2.flags = O_RDONLY;
@@ -2121,6 +2128,7 @@ static int parse_job( process_t *p,
break;
case TOK_REDIRECT_OUT:
+ case TOK_REDIRECT_NOCLOB:
case TOK_REDIRECT_APPEND:
case TOK_REDIRECT_IN:
case TOK_REDIRECT_FD:
@@ -3324,6 +3332,7 @@ int parser_test( const wchar_t * buff,
case TOK_REDIRECT_IN:
case TOK_REDIRECT_APPEND:
case TOK_REDIRECT_FD:
+ case TOK_REDIRECT_NOCLOB:
{
if( !had_cmd )
{
diff --git a/tokenizer.c b/tokenizer.c
index 0551bb17..edefc070 100644
--- a/tokenizer.c
+++ b/tokenizer.c
@@ -69,6 +69,7 @@ static const wchar_t *tok_desc[] =
N_( L"Append output to file" ),
N_( L"Redirect input to file" ),
N_( L"Redirect to file descriptor" ),
+ N_( L"Redirect output to file if file does not exist" ),
N_( L"Run job in background" ),
N_( L"Comment" )
}
@@ -473,6 +474,11 @@ static void read_redirect( tokenizer *tok, int fd )
tok->buff++;
tok->last_type = TOK_REDIRECT_FD;
}
+ else if( *tok->buff == L'?' )
+ {
+ tok->buff++;
+ tok->last_type = TOK_REDIRECT_NOCLOB;
+ }
else
{
tok->last_type = TOK_REDIRECT_OUT + mode;
diff --git a/tokenizer.h b/tokenizer.h
index bced30e5..3954cc48 100644
--- a/tokenizer.h
+++ b/tokenizer.h
@@ -26,6 +26,7 @@ enum token_type
TOK_REDIRECT_APPEND,/**< redirection append token */
TOK_REDIRECT_IN,/**< input redirection token */
TOK_REDIRECT_FD,/**< redirection to new fd token */
+ TOK_REDIRECT_NOCLOB, /**<? redirection token */
TOK_BACKGROUND,/**< send job to bg token */
TOK_COMMENT/**< comment token */
}