executar script php a partir do programa C e armazenar os resultados em uma variável

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

  •  20-08-2019
  •  | 
  •  

Pergunta

Gostaria de executar um script PHP a partir de um programa C e armazenar o conteúdo de voltar-se para uma variável C.

Eu tentei como seguir, mas ele não funciona:

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";
?>

Ambiente:

  • PHP 5.2.6
  • Apache 2.0
  • Fedora Core 10

Também sugerir alguma outra maneira melhor de fazer isso.

Foi útil?

Solução

A resposta curta aqui é usar system() ou popen() em vez de execl(). Vendo como Jason já postou uma boa resposta sobre o uso popen(), eu vou pular isso e explicar como usar execl() apenas no caso de você realmente se importa. Provavelmente, isso é tudo desnecessário patranhas técnico - mas droga, eu tinha a maior parte deste digitado já como um longo prelúdio antes de discutir popen() e não vou jogá-lo fora agora

Em primeiro lugar ...

Ao chamar execl() toda a linha de comando argumentos precisam ser passados ??separadamente. Além disso, o primeiro argumento deve ser repetido como argv[0] em main() qualquer programa é tradicionalmente o nome do programa. Assim, a chamada fixo deve ser parecido:

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

(I adicionou-se o fundido para (char *) para assegurar que um ponteiro nulo é transmitido como o argumento final, em vez do número inteiro 0, se NULL acontece para ser definido como 0 e não (void *) 0, que é legal.)

No entanto ...

Este recebe a chamada direita execl(), mas há um problema maior. A família exec de funções são quase sempre usados ??em combinação com fork() e alguns malabarismos pipe() complicado. Isso ocorre porque as funções exec não executar o programa em um processo separado; eles realmente substituir o atual processo! Então, quando você chamar execl(), seu código é feito. Acabado. execl() nunca retorna. Se você chamá-lo apenas como você fez você nunca vai conseguir ver o que acontece como seu programa irá magicamente transformar em um processo /usr/bin/php.

OK, então o que é isso de fork() e pipe()? Em um nível alto, o que você tem a fazer é dividir o seu processo em dois processos. O processo pai continuará a ser "seu" processo, enquanto o processo filho vai chamar imediatamente execl() e transformar-se em /usr/bin/php. Então, se você fio os processos pai e filho juntos corretamente eles serão capazes de se comunicar uns com os outros.

Para fazer uma longa história curta, se você ainda está aqui e não ter cochilado você deve consultar o oráculo sábio Google para maneira mais detalhes sobre tudo isso. Há uma abundância de sites lá fora, dando ainda mais (!) Em profundidade detalhes sobre como fazer a dança fork / exec.

Eu não vou deixá-lo pendurado no entanto. Aqui está um uso I função para os meus próprios programas que faz exatamente o que eu esbocei. É muito semelhante ao popen() na verdade, a única diferença é que o chamador pode acessar fluxo stderr da criança, além de stdin e stdout.

Código ...

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

Outras dicas

Provavelmente a maneira mais fácil seria usar o popen função : (trecho de página vinculada):

O exemplo a seguir demonstra o uso de popen () e pclose () para executar o comando ls * a fim de obter uma lista de arquivos no diretório atual:

#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() */
    ...
}

No entanto, querendo ler a saída de um script PHP de dentro de um programa C é uma espécie de bandeira vermelha, e eu suspeito que provavelmente há alguma solução global mais clara para isso, mas é difícil dizer mais sem uma descrição maior nível de o que você está tentando fazer.

Lembre-se de quando você usa execl() ele irá "saída em caso de sucesso". Então, você nunca vai ver "função php End" porque ele nunca vai chegar a essa linha de código.

Para superar esse problema, você pode usar tanto system ou utilização fork() para criar um processo filho e na sua utilização execl processo filho ou qualquer outra função da família exec.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top