mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-26 12:53:13 +00:00
Improve error messages on failed execve calls a bit more
darcs-hash:20080116010454-75c98-883050bf00f10bdb205724d7d273f10e6f0a1065.gz
This commit is contained in:
parent
f3b6b74568
commit
f974c7c416
1 changed files with 73 additions and 7 deletions
80
exec.c
80
exec.c
|
@ -442,7 +442,41 @@ static int setup_child_process( job_t *j, process_t *p )
|
||||||
return res;
|
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
|
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->argv = res;
|
||||||
p->actual_cmd = L"/bin/sh";
|
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),
|
execve ( wcs2str(p->actual_cmd),
|
||||||
res_real,
|
res_real,
|
||||||
|
@ -552,19 +586,19 @@ static void launch_process( process_t *p )
|
||||||
sb_format_size( &sz2, ARG_MAX );
|
sb_format_size( &sz2, ARG_MAX );
|
||||||
|
|
||||||
debug( 0,
|
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 *)sz1.buff,
|
||||||
(wchar_t *)sz2.buff);
|
(wchar_t *)sz2.buff);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
debug( 0,
|
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);
|
(wchar_t *)sz1.buff);
|
||||||
}
|
}
|
||||||
|
|
||||||
debug( 0,
|
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( &sz1 );
|
||||||
sb_destroy( &sz2 );
|
sb_destroy( &sz2 );
|
||||||
|
|
||||||
|
@ -573,10 +607,42 @@ static void launch_process( process_t *p )
|
||||||
break;
|
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:
|
default:
|
||||||
{
|
{
|
||||||
debug(0, L"The file '%ls' is marked as an executable but could not be run by the operating system.", p->actual_cmd);
|
wperror(L"exec");
|
||||||
exit(STATUS_EXEC_FAIL);
|
|
||||||
|
// 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue