Verständnis der Anforderungen für execve und Einstellung von Umgebungsvariablen

Lesezeit: 4 Minuten

Benutzer-Avatar
James

Wir haben große Probleme, unseren Lehrer zu interpretieren. Wir baten um Klärung und bekamen folgendes von ihm zurück

  1. Senden Sie für execve eine Umgebung, die Sie mit Ihren exportierten Variablen eingerichtet haben, und erstellen Sie einen integrierten Befehl, um eine Subshell von /bin/bash zu erzeugen, damit Sie Ihre exportierten Variablen mit env sehen können.

    (Er spricht hier über das Erstellen unserer eigenen Umgebungsvariablen.)

  2. Ja erstellen Sie Ihre eigenen. Sie können beginnen, indem Sie environ kopieren, wenn Ihre Shell startet, und nur exportierte Variablen hinzufügen

Dies hängt mit dem folgenden Beitrag von mir zu Stack Overflow zusammen (das Lesen dieses anderen Beitrags hilft Ihnen zu verstehen, was ich versuche zu tun):

Verwenden eines neuen Pfads mit execve zum Ausführen des Befehls ls

Wir sind nur sehr verwirrt darüber. Ich werde noch einmal erklären, was wir jetzt versuchen zu tun. Ähnlich wie Ihre Linux-Shell dies tut, müssen wir unser eigenes Programm schreiben, das Umgebungsvariablen wie PATH und USER und alle anderen Variablen, die der Benutzer definieren möchte, setzen kann.

Ein Beispiel dafür, wie Sie dies aufrufen würden, wäre (in Ihrem Programm an der Eingabeaufforderung):

mysetenv dog spike

was eine Umgebungsvariable erstellen würde, die wie “dog=spike” aussieht

Noch wichtiger ist, dass wir in der Lage sein müssen, unsere eigene PATH-Variable festzulegen und an eine zu senden exec Befehl. Das ist der verwirrende Teil, weil wir aufgrund all unserer Fragen nicht verstehen, was wir tun sollen.

Es ist eigentlich ganz einfach. Sie wissen bereits, dass Ihre Argumente eine Liste von sind char *, abgeschlossen durch einen NULL-Zeiger. Ebenso ist die Umgebung einfach eine Liste von char *, abgeschlossen durch einen NULL-Zeiger. Herkömmlicherweise nehmen die Werte in der Liste die Form an VARNAME=var-valueSie können jedoch auch andere Formate übergeben, wenn Sie dies wünschen.

Also, um einen einfachen Fall zu nehmen:

#include <unistd.h>
#include <stdio.h>

int main(void)
{
    char *argv[] = { "/bin/sh", "-c", "env", 0 };
    char *envp[] =
    {
        "HOME=/",
        "PATH=/bin:/usr/bin",
        "TZ=UTC0",
        "USER=beelzebub",
        "LOGNAME=tarzan",
        0
    };
    execve(argv[0], &argv[0], envp);
    fprintf(stderr, "Oops!\n");
    return -1;
}

In diesem Beispiel wird das Programm ausgeführt /bin/sh mit Argumenten -c und envwas bedeutet, dass die Shell die env Programm auf seinem aktuellen PATH gefunden. Die Umgebung hier ist so eingestellt, dass sie 5 Werte im orthodoxen Format enthält. Wenn Sie sich ändern env zu date (oder env; date) sehen Sie beispielsweise die Wirkung der TZ-Einstellung. Wenn ich das auf meinem MacOS X-Rechner ausführe, lautet die Ausgabe:

USER=beelzebub
PATH=/bin:/usr/bin
PWD=/Users/jleffler/tmp/soq
TZ=UTC0
SHLVL=1
HOME=/
LOGNAME=tarzan
_=/usr/bin/env

Die Shell hat Umgebungsvariablen hinzugefügt SHLVL, _ und PWD zu denen, die ich explizit in der setze execve() Anruf.

Sie können auch ausgefallenere Dinge tun, z. B. einige der anderen Umgebungsvariablen aus Ihrer echten Umgebung kopieren, wo sie nicht mit denen in Konflikt stehen, die Sie explizit festlegen möchten. Sie können auch Spiele spielen, wie z. B. zwei Werte für eine einzelne Variable in der Umgebung zu haben – welcher wirkt sich aus? Und Sie können Spiele mit Variablennamen spielen, die Leerzeichen enthalten (die Shell mag das nicht so sehr) oder Einträge, die überhaupt nicht mit der ‘varname=value’-Notation übereinstimmen (kein Gleichheitszeichen).

  • Du hast mir wirklich alles klar gemacht. Ich habe schon alles abgegeben, aber danke! Ich verstehe es jetzt.

    – James

    8. Oktober 2011 um 17:37 Uhr

Benutzer-Avatar
fpf3

Ich bin hier etwas spät dran, aber wenn Sie die alten Umgebungsvariablen beibehalten und Ihre eigenen erstellen möchten, verwenden Sie setenvund dann passieren environ zu execve().

    setenv("dog", "spike", 1);
    extern char** environ;
    execve(argv[0], argv, environ);

environ ist eine in deklarierte Variable unistd.hund es verfolgt die Umgebungsvariablen während dieses laufenden Prozesses.

setenv() und putenv() ändern environalso wenn du es übergibst execve()sind die Umgebungsvariablen genau so, wie Sie es erwarten würden.

  • Könntest du nicht einfach anrufen execv(argv[0], argv); nach dem Erweitern der Umgebung mit setenv stattdessen?

    – Erich Kitzmüller

    15. Februar um 11:53 Uhr

  • @ErichKitzmueller Soweit ich weiß, wird die Umgebungsvariable selbst nicht über execve beibehalten, und wenn Sie execve aufrufen, ohne environ zu übergeben, werden standardmäßig die Umgebungsvariablen der Shell verwendet. Ich könnte mich aber irren. Ich schlage vor, Sie versuchen es.

    – fpf3

    15. Februar um 23:08 Uhr

  • Nach meinem Verständnis, wenn Sie anrufen execve, müssen Sie eine Umgebung bereitstellen (Linux erlaubt NULL, was dieselbe Bedeutung hat wie eine Liste mit einem einzelnen NULL-Zeiger; dies ist jedoch nicht portierbar). Aber anstatt anzurufen execvedu könntest anrufen execv (ohne das e) und das würde sich genauso gut übertragen lassen environeinschließlich der Änderungen, die Sie per Anruf vorgenommen haben setenv.

    – Erich Kitzmüller

    16. Februar um 13:05 Uhr


Benutzer-Avatar
qritter

Der Code von Jonathan Leffler funktioniert super, außer wenn man das ändern will PWD (Arbeitsverzeichnis) Variable.

Was ich getan habe, um das Arbeitsverzeichnis zu ändern, war, a chdir(..) Vor execve(..) und Ruf an:

chdir("/foo/bar"); 
execve(argv[0], &argv[0], envp);

1186840cookie-checkVerständnis der Anforderungen für execve und Einstellung von Umgebungsvariablen

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy