Nous avons beaucoup de difficulté à interpréter notre professeur. Nous avons demandé des éclaircissements et nous avons reçu ce qui suit.
Pour execve, envoyez-lui un environnement que vous avez configuré avec vos variables exportées et créez une commande intégrée pour créer un sous-shell de/bin/bash. Ainsi, vous pourrez voir vos variables exportées à l'aide de env.
(Il parle de créer notre propre environnement vars ici.)
Ceci est lié au post suivant sur Stack Overflow par moi (lire cet autre post vous aidera à comprendre ce que j'essaie de faire):
en utilisant un nouveau chemin avec execve pour exécuter la commande ls
Nous sommes juste très confus à ce sujet. Une fois de plus, je vais expliquer ce que nous essayons de faire maintenant. De la même manière que votre shell Linux, nous devons écrire notre propre programme qui peut définir des variables d’environnement telles que PATH et USER, ainsi que tout autre vars que l’utilisateur souhaite définir.
Voici un exemple de ce que vous appelleriez (dans votre programme à l’invite):
mysetenv dog spike
ce qui créerait une variable d'environnement ressemblant à "chien = pointe"
Plus important encore, nous devons pouvoir définir notre propre variable PATH et l'envoyer à une commande exec
. C'est la partie déroutante parce que, sur la base de toutes nos questions, nous ne comprenons pas ce que nous sommes censés faire.
C'est en fait très simple. Vous savez déjà que vos arguments sont une liste de char *
, terminée par un pointeur NULL. De même, l'environnement est simplement une liste de char *
, terminée par un pointeur NULL. Classiquement, les valeurs de la liste prennent la forme VARNAME=var-value
, bien que vous puissiez passer d’autres formats si vous le souhaitez.
Alors, pour prendre un cas simple:
#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;
}
Dans cet exemple, le programme exécutera /bin/sh
avec les arguments -c
et env
, ce qui signifie que le shell exécutera le programme env
trouvé sur son PATH actuel. L'environnement ici est défini pour contenir 5 valeurs au format orthodoxe. Si vous remplacez env
par date
(ou env; date
), vous verrez l'effet du paramètre TZ, par exemple. Lorsque je lance cela sur ma machine MacOS X, la sortie est:
USER=beelzebub
PATH=/bin:/usr/bin
PWD=/Users/jleffler/tmp/soq
TZ=UTC0
SHLVL=1
HOME=/
LOGNAME=tarzan
_=/usr/bin/env
Le shell a ajouté les variables d’environnement SHLVL
, _
et PWD
à celles que j’ai définies explicitement dans l’appel execve()
.
Vous pouvez également effectuer des opérations plus sophistiquées, telles que la copie de certaines autres variables d’environnement à partir de votre environnement véritable, où elles ne sont pas en conflit avec celles que vous souhaitez définir explicitement. Vous pouvez également jouer à des jeux comme avoir deux valeurs pour une seule variable dans l'environnement - laquelle prend effet? Et vous pouvez jouer à des jeux avec des noms de variable contenant des espaces (le shell n’aime pas tant que ça), ou des entrées qui ne correspondent pas du tout à la notation 'varname = value' (pas de signe égal).
Je suis un peu en retard pour la fête ici, mais si vous voulez conserver les anciennes variables d'environnement et créer les vôtres, utilisez setenv
, puis passez environ
à execve()
.
setenv("dog", "spike", 1);
extern char** environ;
execve(argv[0], argv, environ);
environ
est une variable déclarée dans unistd.h
et assure le suivi des variables d'environnement pendant ce processus en cours d'exécution.
setenv()
et putenv()
modifient environ
. Ainsi, lorsque vous le passez sur execve()
, les variables d'environnement seront comme vous le souhaitiez.
Le code de Jonathan Leffler fonctionne très bien, sauf si vous souhaitez modifier la variable PWD
(répertoire de travail).
Ce que j'ai fait, afin de changer le répertoire de travail, a été de mettre un chdir(..)
avant un execve(..)
et d'appeler:
chdir("/foo/bar");
execve(argv[0], &argv[0], envp);