exécuter un script php à partir du programme C et stocker les résultats dans une variable

StackOverflow https://stackoverflow.com/questions/1047385

  •  20-08-2019
  •  | 
  •  

Question

Je voudrais exécuter un script PHP à partir d'un programme C et stocker le contenu renvoyé dans une variable C.

J'ai essayé de suivre, mais cela ne fonctionne pas:

C:

printf("calling php function\n");
execl("/usr/bin/php -q", "/var/www/html/phpinfo.php", NULL);
printf("End php function\n");

PHP:

<?php
echo "hello";
?>

Environnement:

  • PHP 5.2.6
  • Apache 2.0
  • Fedora Core 10

Suggérez également toute autre méthode plus efficace.

Était-ce utile?

La solution

La réponse courte ici est d’utiliser system() ou popen() plutôt que execl(). Étant donné que Jason a déjà publié une bonne réponse à propos de l’utilisation de argv[0], je vais sauter cela et expliquer comment utiliser main() au cas où cela vous intéresserait. Très probablement, il s’agit là d’un charabia technique inutile - mais bon sang, j’avais déjà presque tout cela tapé comme prélude avant de discuter (char *) et je ne le jette pas maintenant!

Tout d'abord ...

Lors de l'appel NULL, tous les arguments de ligne de commande doivent être passés séparément. En outre, le premier argument doit être répété car 0 dans n'importe quel programme (void *) 0 correspond généralement au nom du programme. Ainsi, l'appel fixe devrait ressembler à:

execl("/usr/bin/php", "/usr/bin/php", "-q",
    "/var/www/html/phpinfo.php", (char *) NULL);

(J'ai ajouté le transtypage à exec pour assurer qu'un pointeur nul soit passé comme argument final plutôt que comme l'entier 0, si fork() se trouve défini comme pipe() et non /usr/bin/php, ce qui légal.)

Cependant ...

L’appel fork est correct, mais le problème est plus grave. La famille de fonctions stderr est presque toujours utilisée en combinaison avec stdin et certaines jonglerie stdout compliquée. En effet, les fonctions <=> n'exécutent pas le programme dans un processus séparé. ils remplacent réellement le processus actuel! Donc, une fois que vous appelez <=>, votre code est terminé. Fini. <=> ne revient jamais. Si vous l'appelez simplement comme vous l'avez fait, vous ne verrez jamais ce qui se passe car votre programme se transformera comme par magie en un <=> processus.

OK, qu’en est-il <=> et <=>? À un niveau élevé, vous devez diviser votre processus en deux processus. Le processus parent continuera à être & Quot; votre & Quot; processus, alors que le processus enfant appelle immédiatement <=> et se transforme en <=>. Ensuite, si vous avez correctement connecté les processus parent et enfant, ils pourront communiquer les uns avec les autres.

Pour résumer, si vous êtes toujours ici et n’avez pas eu peur de la tête, vous devriez consulter Google, le sage oracle, pour plus de détails sur tout cela. Il existe de nombreux sites Web donnant encore plus (!) De détails détaillés sur la manière de faire la danse <=> / <=>.

Je ne vous laisserai pas pendre cependant. Voici une fonction que j'utilise pour mes propres programmes et qui fait exactement ce que j'ai décrit. Cela ressemble beaucoup à <=> en fait, la seule différence étant que l'appelant peut accéder au flux <=> de l'enfant en plus de <=> et de <=>.

Code ...

#include <errno.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

pid_t execute(const char *command, FILE **in, FILE **out, FILE **err)
{
    pid_t pid;
    int   fd[6];

    pipe(&fd[0]);
    pipe(&fd[2]);
    pipe(&fd[4]);

    switch (pid = fork()) {
        case -1:
            perror("unable to fork()");
            exit(1);

        case 0:
            close(fd[1]);   // Close write end of stdin.
            close(fd[2]);   // Close read end of stdout.
            close(fd[4]);   // Close read end of stderr.

            dup2(fd[0], STDIN_FILENO);  // Have stdin read from the first pipe.
            dup2(fd[3], STDOUT_FILENO); // Have stdout write to the second pipe.
            dup2(fd[5], STDERR_FILENO); // Have stderr write to the third pipe.

            execlp("/bin/sh", "/bin/sh", "-c", command, (char *) NULL);

            perror("execlp() failed");
            _exit(1);

        default:
            close(fd[0]); // Close read end of stdin.
            close(fd[3]); // Close write end of stdout.
            close(fd[5]); // Close write end of stderr.

            if (in)  *in  = fdopen(fd[1], "wb"); else close(fd[1]);
            if (out) *out = fdopen(fd[2], "rb"); else close(fd[2]);
            if (err) *err = fdopen(fd[4], "rb"); else close(fd[4]);

            return pid;
    }
}

Autres conseils

La solution la plus simple serait probablement d’utiliser la fonction contextuelle : (extrait de la page liée):

  

L'exemple suivant montre l'utilisation de popen () et de pclose () pour exécuter la commande ls * afin d'obtenir une liste de fichiers dans le répertoire en cours:

#include <stdio.h>
...


FILE *fp;
int status;
char path[PATH_MAX];


fp = popen("ls *", "r");
if (fp == NULL)
    /* Handle error */;


while (fgets(path, PATH_MAX, fp) != NULL)
    printf("%s", path);


status = pclose(fp);
if (status == -1) {
    /* Error reported by pclose() */
    ...
} else {
    /* Use macros described under wait() to inspect `status' in order
       to determine success/failure of command executed by popen() */
    ...
}

Cependant, vouloir lire la sortie d'un script PHP à partir d'un programme C est un peu un drapeau rouge, et je suppose qu'il existe probablement une solution plus propre à cela, mais il est difficile d'en dire plus sans une description de niveau supérieur de ce que vous essayez de faire.

N'oubliez pas que lorsque vous utilisez execl(), il va & quitter; en cas de succès &> ;. Donc, vous ne verrez jamais & "Terminer la fonction php &"; car il n'arrivera jamais à cette ligne de code.

Pour résoudre ce problème, vous pouvez utiliser system ou utiliser fork() pour créer un processus enfant. Dans votre processus enfant, utilisez execl ou toute autre fonction de la famille exec.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top