aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar liljencrantz <liljencrantz@gmail.com>2008-01-16 11:04:54 +1000
committerGravatar liljencrantz <liljencrantz@gmail.com>2008-01-16 11:04:54 +1000
commitf974c7c4163cc12c461c920905ade7b8e46d644d (patch)
treea4673b98a6290032b5f4ef5722952983940daf72
parentf3b6b7456826ae7f0ce1e0b10c378eac007ffef9 (diff)
Improve error messages on failed execve calls a bit more
darcs-hash:20080116010454-75c98-883050bf00f10bdb205724d7d273f10e6f0a1065.gz
-rw-r--r--exec.c80
1 files changed, 73 insertions, 7 deletions
diff --git a/exec.c b/exec.c
index 7c894805..dea56819 100644
--- a/exec.c
+++ b/exec.c
@@ -442,7 +442,41 @@ static int setup_child_process( job_t *j, process_t *p )
return res;
}
-
+
+/**
+ Returns the interpreter for the specified script. Returns 0 if file
+ is not a script with a shebang. This function leaks memory on every
+ call. Only use it in the execve error handler which calls exit
+ right afterwards, anyway.
+ */
+static wchar_t *get_interpreter( wchar_t *file )
+{
+ string_buffer_t sb;
+ FILE *fp = wfopen( file, "r" );
+ sb_init( &sb );
+ wchar_t *res = 0;
+ if( fp )
+ {
+ while( 1 )
+ {
+ wint_t ch = getwc( fp );
+ if( ch == WEOF )
+ break;
+ if( ch == L'\n' )
+ break;
+ sb_append_char( &sb, (wchar_t)ch );
+ }
+ }
+
+ res = (wchar_t *)sb.buff;
+
+ if( !wcsncmp( L"#! /", res, 4 ) )
+ return res+3;
+ if( !wcsncmp( L"#!/", res, 3 ) )
+ return res+2;
+ return 0;
+}
+
/**
This function is executed by the child process created by a call to
@@ -503,7 +537,7 @@ static void launch_process( process_t *p )
p->argv = res;
p->actual_cmd = L"/bin/sh";
- res_real = wcsv2strv( (const wchar_t **) res);
+ res_real = wcsv2strv( (const wchar_t **) res);
execve ( wcs2str(p->actual_cmd),
res_real,
@@ -552,19 +586,19 @@ static void launch_process( process_t *p )
sb_format_size( &sz2, ARG_MAX );
debug( 0,
- L"The total size of the argument and environment lists (%ls) exceeds the system limit of %ls.",
+ L"The total size of the argument and environment lists (%ls) exceeds the operating system limit of %ls.",
(wchar_t *)sz1.buff,
(wchar_t *)sz2.buff);
}
else
{
debug( 0,
- L"The total size of the argument and environment lists (%ls) exceeds the system limit.",
+ L"The total size of the argument and environment lists (%ls) exceeds the operating system limit.",
(wchar_t *)sz1.buff);
}
debug( 0,
- L"Please try running the command again with fewer arguments.");
+ L"Try running the command again with fewer arguments.");
sb_destroy( &sz1 );
sb_destroy( &sz2 );
@@ -573,10 +607,42 @@ static void launch_process( process_t *p )
break;
}
+ case ENOEXEC:
+ {
+ wperror(L"exec");
+
+ debug(0, L"The file '%ls' is marked as an executable but could not be run by the operating system.", p->actual_cmd);
+ exit(STATUS_EXEC_FAIL);
+ }
+
+ case ENOENT:
+ {
+ wchar_t *interpreter = get_interpreter( p->actual_cmd );
+
+ if( interpreter && waccess( interpreter, X_OK ) )
+ {
+ debug(0, L"The file '%ls' specified the interpreter '%ls', which is not an executable command.", p->actual_cmd, interpreter );
+ }
+ else
+ {
+ debug(0, L"The file '%ls' or a script or ELF interpreter does not exist, or a shared library needed for file or interpreter cannot be found.", p->actual_cmd);
+ }
+
+ exit(STATUS_EXEC_FAIL);
+ }
+
+ case ENOMEM:
+ {
+ debug(0, L"Out of memory");
+ exit(STATUS_EXEC_FAIL);
+ }
+
default:
{
- debug(0, L"The file '%ls' is marked as an executable but could not be run by the operating system.", p->actual_cmd);
- exit(STATUS_EXEC_FAIL);
+ wperror(L"exec");
+
+ // debug(0, L"The file '%ls' is marked as an executable but could not be run by the operating system.", p->actual_cmd);
+ exit(STATUS_EXEC_FAIL);
}
}