Em um ambiente vazio, como os executáveis são encontrados?

7

Para fins de experimentação, criei um binário que imprime o $PATH e chama which da seguinte forma:

#include <stdlib.h>
#include <stdio.h>

int main() {
    char *path = getenv("PATH");

    if (path)
        printf("got a path: %s\n", path);
    else
        printf("got no path\n");

    system("which which");
    return 0;
}

quando eu o executo em um ambiente vazio via

env -i ./printpath

Recebo a seguinte impressão:

got no path
/usr/bin/which

Minha pergunta é: por que o binário which correto é chamado, mesmo se não houver $PATH ?

    
por keppla 19.04.2014 / 21:11

2 respostas

11

Você usou a função system , por isso usará outro shell para executar o comando which which . De man system :

DESCRIPTION
       system()  executes a command specified in command by calling /bin/sh -c
       command, and returns after the command has been completed.  During exe‐
       cution  of the command, SIGCHLD will be blocked, and SIGINT and SIGQUIT
       will be ignored.

Se você alterar o comando which which para echo $PATH :

$ env -i ./a.out 
got no path
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

Se você alterar seu código para usar execve em vez de system , obterá a saída esperada:

#include <stdlib.h>                                                             
#include <stdio.h>  

int main() {                                                                    
    char *path = getenv("PATH");                                                

    if (path)                                                                   
        printf("got a path: %s\n", path);                                       
    else                                                                        
        printf("got no path\n");                                                

    execve("echo $PATH");                                                       
    return 0;                                                                   
} 

Compile e execute:

$ gcc test.c && env -i ./a.out 
got no path
    
por 19.04.2014 / 21:24
2

Em um ambiente vazio, os executáveis não são encontrados, a menos que você especifique o caminho completo. Experimente com execvp .

A função system invoca um shell no Linux com o Glibc, invoca /bin/sh (portanto, não é necessário PATH ). Os shells definem algumas variáveis próprias além das que vêm do ambiente. Você pode ver o que definem executando env -i /path/to/shell -c set e quais exportam executando env -i /path/to/shell -c export . Em particular, tanto dash quanto bash - os dois shells que você provavelmente encontrará como /bin/sh no Linux - definem (mas não exportam) PATH para um padrão "sã" se não houver nenhum no ambiente . Conchas diferentes definem valores diferentes ou nenhum.

$ env -i bash -c 'echo $PATH'
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
$ env -i dash -c 'echo $PATH'
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
$ env -i mksh -c 'echo $PATH'
/usr/bin:/bin
$ env -i ksh93 -c 'echo $PATH'

$ env -i zsh -c 'echo $PATH' 
/bin:/usr/bin:/usr/ucb:/usr/local/bin
$ env -i csh -c 'echo $PATH' 
PATH: Undefined variable.
$ env -i tcsh -c 'echo $PATH'
PATH: Undefined variable.

Na minha máquina (e aparentemente na sua), which é em si um script /bin/sh . O shell chamado por system usa sua própria variável de caminho para localizar o programa which , mas não o exporta. O shell que executa o script which também define a variável PATH para seu uso interno.

    
por 21.04.2014 / 00:41

Tags