Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

System et Exec

4 réponses
Avatar
Stéphane Müller
Bonjour,

J'ai le script perl essai.pl suivant:

print "++ system ++\n";
system @ARGV;
print "++ exec ++\n";
exec @ARGV;

J'ai le fichier arg.bat suivant:

@echo off
echo 1: %1
echo 2: %2
echo 3: %3

Le résultat de la commande:

C:\Tmp>perl essai.pl arg.bat -p"Mon repertoire" -d

est le suivant:

++ system ++
1: "-pMon repertoire"
2: -d
3:
++ exec ++
C:\Tmp>1: -pMon
2: repertoire
3: -d

Pourquoi les arguments sont-ils correctement interprétés par la
commande system alors que ce n'est pas le cas par exec ?

Merci de votre aide.
Stéphane

4 réponses

Avatar
Paul Gaborit
À (at) Tue, 5 Jun 2007 17:37:21 +0200,
"Stéphane Müller" écrivait (wrote):
J'ai le script perl essai.pl suivant:

print "++ system ++n";
system @ARGV;
print "++ exec ++n";
exec @ARGV;

J'ai le fichier arg.bat suivant:

@echo off
echo 1: %1
echo 2: %2
echo 3: %3

Le résultat de la commande:

C:Tmp>perl essai.pl arg.bat -p"Mon repertoire" -d

est le suivant:

++ system ++
1: "-pMon repertoire"
2: -d
3:
++ exec ++
C:Tmp>1: -pMon
2: repertoire
3: -d

Pourquoi les arguments sont-ils correctement interprétés par la
commande system alors que ce n'est pas le cas par exec ?


Ça ne devrait pas être le cas... En tous cas, sur Unix, tout se passe
comme prévu (arg.bat ne reeçoit que deux arguments à chaque fois).

C'est certainement un effet de bord de la manière dont 'exec' est
simulé par Perl sur Windows.

--
Paul Gaborit - <http://perso.enstimac.fr/~gaborit/>
Perl en français - <http://perl.enstimac.fr/>

Avatar
jl_morel
Dans l'article <f43vv4$1ri$,
a dit...

[couic]


Pourquoi les arguments sont-ils correctement interprétés par la
commande system alors que ce n'est pas le cas par exec ?



Comme Paul Gaborit l'a deviné, il s'agit d'un problème dû à l'émulation de
exec sous Windows. Les guillemets sont retirés par cmd.exe.

Pour créer un process avec CreateProcess, Perl a besoin d'une ligne de
commande complète (donc une chaîne et pas une liste). Il reconstitue cette
ligne de commande à partir de la liste d'arguments d'exec.

Voir la fonction create_command_line dans win32.c :
http://search.cpan.org/src/NWCLARK/perl-5.8.8/win32/win32.c

C'est cette fonction qui rajoute des guillemets en utilisant un algorithme
heuristique... qui n'est pas parfait (voir les commentaires dans le code).

Vous pouvez "protéger" vos guillemets :

F:tmp>perl essai.pl arg.bat -p"Mon repertoire" -d
++ system ++
1: -p"Mon repertoire"
2: -d
3:
++ exec ++

F:tmp>1: -p"Mon repertoire"
2: -d
3:


--
J-L.M.
http://www.bribes.org/perl

Avatar
Paul Gaborit
À (at) 06 Jun 2007 13:20:24 GMT,
(Jean-Louis MOREL) écrivait (wrote):
Comme Paul Gaborit l'a deviné, il s'agit d'un problème dû à l'émulation de
exec sous Windows. Les guillemets sont retirés par cmd.exe.

Pour créer un process avec CreateProcess, Perl a besoin d'une ligne de
commande complète (donc une chaîne et pas une liste). Il reconstitue cette
ligne de commande à partir de la liste d'arguments d'exec.

Voir la fonction create_command_line dans win32.c :
http://search.cpan.org/src/NWCLARK/perl-5.8.8/win32/win32.c

C'est cette fonction qui rajoute des guillemets en utilisant un algorithme
heuristique... qui n'est pas parfait (voir les commentaires dans le code).

Vous pouvez "protéger" vos guillemets :

F:tmp>perl essai.pl arg.bat -p"Mon repertoire" -d
++ system ++
1: -p"Mon repertoire"
2: -d
3:
++ exec ++

F:tmp>1: -p"Mon repertoire"
2: -d
3:


Ce qui m'étonne quand même un peu dans cette histoire, c'est que les
deux appels (system et exec) se comportent de manière
différentes... alors qu'ils devraient être quand même très similaires.

Pourquoi l'appel 'system' reconstitue-t-il correctement la ligne de
commande et pas 'exec' ?

--
Paul Gaborit - <http://perso.enstimac.fr/~gaborit/>
Perl en français - <http://perl.enstimac.fr/>

Avatar
Stéphane Müller
Finallement, j'ai modifié comme ci-dessous mon code pour faire
fonctionner correctement le exec:

$cmd = shift @ARGV;
while ( $arg = shift @ARGV ) { $cmd .= " "$arg"" }
exec $cmd;

Ce n'est pas génial mais ça a le mérite de fonctionner pour mon
cas.

En tout cas, merçi pour vos réponses.

Stéphane