Se eu fosse adivinhar, seu sh
favorece a simplicidade ou o desempenho em relação à facilidade de uso. O erro "permissão negada" é fornecido por perror(3)
, uma função padrão para imprimir uma mensagem de erro. Por exemplo:
$ cat foo.c
#include <stdio.h>
#include <unistd.h>
int main()
{
char* const args[] = { "/usr", NULL };
if (execv(args[0], args))
perror(args[0]);
return 0;
}
$ gcc -o foo foo.c
$ ./foo
/usr: Permission denied
bash
provavelmente faz uma verificação para ver se o caminho é um diretório. Isso, claro, será um pouco mais lento e um código um pouco mais longo.
bash
, zsh
, etc. têm mais de um motivo para fazer a verificação - eles permitem que você "execute" um caminho para um diretório para cd
:
$ shopt -s autocd
$ cd /
$ pwd
/
$ /usr/share
cd /usr/share
$ pwd
/usr/share
No caso de dash
( /bin/sh
do Debian aponta para /bin/dash
), esse é o caso. O código que executa o comando está em shellexec()
:
if (strchr(argv[0], '/') != NULL) {
tryexec(argv[0], argv, envp);
e = errno;
} else {
// snip
exerror(EXEXIT, "%s: %s", argv[0], errmsg(e, E_EXEC));
Essa função chama errms()
:
const char *
errmsg(int e, int action)
{
if (e != ENOENT && e != ENOTDIR)
return strerror(e);
if (action & E_OPEN)
return "No such file";
else if (action & E_CREAT)
return "Directory nonexistent";
else
return "not found";
}
strerror(3)
é outra função padrão, como perror
. strerror
retorna a mensagem de erro, perror
imprime diretamente.