Wie werden ausführbare Dateien in einer leeren Umgebung gefunden?

7

Zu Versuchszwecken habe ich eine Binärdatei erstellt, die das druckt $PATHund whichwie folgt aufruft :

#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;
}

wenn ich es in einer leeren Umgebung über laufen lasse

env -i ./printpath

Ich bekomme folgenden Ausdruck:

got no path
/usr/bin/which

Meine Frage ist: Warum wird die richtige whichBinärdatei aufgerufen, auch wenn es keine gibt $PATH?

keppla
quelle

Antworten:

11

Sie haben die systemFunktion verwendet, daher wird eine andere Shell zum Ausführen des Befehls verwendet which which. Von 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.

Wenn Sie den which whichBefehl ändern in echo $PATH:

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

Wenn Sie Ihren Code so ändern, dass er execveanstelle von verwendet wird system, erhalten Sie die erwartete Ausgabe:

#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;                                                                   
} 

Kompilieren und ausführen:

$ gcc test.c && env -i ./a.out 
got no path
cuonglm
quelle
Ich erwartete, dass die Subshell den leeren Pfad erben würde und hatte daher keine Konsequenz. Vielen Dank, dass Sie auf dieses Missverständnis hingewiesen haben!
Keppla
1
Der Sub - Shell hat den leeren Pfad erben. Als ein Merkmal von bash (und vermutlich auch anderen Shells) wird es, wenn es mit PATH unset gestartet wird, auf einen Standardwert gesetzt, wie wir im echo $PATHBeispiel sehen.
Nate Eldredge
3

In einer leeren Umgebung werden ausführbare Dateien nur gefunden, wenn Sie den vollständigen Pfad angeben. Probieren Sie es mit execvp.

Die systemFunktion ruft eine Shell auf - unter Linux mit Glibc ruft sie auf /bin/sh(also nicht PATHerforderlich). Shells definieren zusätzlich zu den aus der Umgebung stammenden Variablen einige eigene Variablen. Sie können sehen, was sie durch Ausführen definieren env -i /path/to/shell -c setund welche sie durch Ausführen exportieren env -i /path/to/shell -c export. Insbesondere setzen sowohl Dash als auch Bash - die beiden Shells, die Sie wahrscheinlich /bin/shunter Linux finden - PATHauf einen „vernünftigen“ Standardwert (aber nicht exportieren) , wenn es keinen in der Umgebung gibt. Unterschiedliche Schalen setzen unterschiedliche oder gar keine Werte.

$ 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.

Auf meinem Computer (und anscheinend auf Ihrem) whichbefindet sich selbst ein /bin/shSkript. Die von aufgerufene Shell systemverwendet eine eigene Pfadvariable, um das whichProgramm zu finden , exportiert es jedoch nicht. Die Shell, die das whichSkript selbst ausführt, definiert auch die PATHVariable für den internen Gebrauch.

Gilles 'SO - hör auf böse zu sein'
quelle