تنفيذ البرنامج النصي php من برنامج C تخزين النتائج في متغير

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

  •  20-08-2019
  •  | 
  •  

سؤال

أود أن تنفيذ البرنامج النصي PHP من برنامج 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";
?>

البيئة:

  • PHP 5.2.6
  • أباتشي 2.0
  • Fedora Core 10

تشير أيضا إلى أي طريقة أفضل للقيام بذلك.

هل كانت مفيدة؟

المحلول

الجواب القصير هنا هو استخدام system() أو popen() بدلا من execl().كما نرى جيسون وقد نشرت بالفعل إجابة جيدة عن استخدام popen(), أنا سوف تخطي هذا شرح كيفية استخدام execl() فقط في حال كنت تهتم فعلا.على الأرجح هذا هو كل شيء لا لزوم لها التقنية الجامبو--ولكن اللعنة ، لقد كان معظم هذا كتبته بالفعل طويل مقدمة قبل مناقشة popen() و أنا لا رمي بعيدا الآن!

أولا...

عند الاتصال execl() كل من سطر الأوامر تحتاج إلى تمرير على حدة.أيضا ، فإن الحجة الأولى يجب أن تتكرر مثل argv[0] في أي برنامج main() تقليديا اسم البرنامج.لذلك الثابتة الدعوة ينبغي أن تبدو وكأنها:

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

(أضفت المدلى بها إلى (char *) لضمان أن مؤشر فارغة يتم تمرير النهائية الحجة بدلا من صحيح 0, إذا NULL يحدث أن يكون تعريف 0 و لا (void *) 0, الذي هو قانوني.)

ومع ذلك...

هذا يحصل execl() دعوة الحق, ولكن هناك مشكلة أكبر.على exec الأسرة من الوظائف هي دائما تقريبا تستخدم في تركيبة مع fork() وبعض معقدة pipe() شعوذة.وذلك لأن exec وظائف لا تقم بتشغيل البرنامج في عملية منفصلة;فإنها في الواقع تحل محل العملية الحالية!لذلك بمجرد الاتصال execl(), كود الخاص بك هو القيام به.انتهى. execl() لا يعود أبدا.إذا كنت فقط كما فعلت أنت لن تحصل على رؤية ما يحدث الخاص بك البرنامج سوف سحرية تحول إلى /usr/bin/php العملية.

حسنا, ماذا عن fork() و pipe()?على مستوى عال ، ما عليك فعله هو تقسيم العملية إلى العمليتين.الوالد العملية سوف تستمر في أن تكون "الخاص بك" العملية ، بينما الطفل عملية الاتصال فورا execl() وتحويل نفسها إلى /usr/bin/php.ثم إذا كنت قد حولت الأم والطفل العمليات معا بشكل صحيح سوف تكون قادرة على التواصل مع بعضها البعض.

لجعل قصة قصيرة طويلة, إذا كنت لا تزال هنا و لم نمت يجب عليك استشارة الحكماء أوراكل جوجل عن طريق مزيد من التفاصيل حول كل هذا.هناك الكثير من المواقع على شبكة الإنترنت تقدم أكثر (!) في عمق التفاصيل حول كيفية القيام fork/exec الرقص.

أنا لن أترك لكم شنقا على الرغم من.وهنا وظيفة يمكنني استخدام بلدي البرامج التي لا بالضبط ما كنت المبينة.أنها مشابهة جدا popen() في الواقع, والفرق الوحيد هو أن المتصل يمكن الوصول إلى الطفل stderr تيار بالإضافة إلى stdin و stdout.

رمز...

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

نصائح أخرى

ربما أسهل طريقة لاستخدام popen وظيفة:(مقتطف من ربط الصفحة):

يوضح المثال التالي استخدام popen() و pclose() لتنفيذ الأمر ls * للحصول على قائمة من الملفات في الدليل الحالي:

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

بيد أن الرغبة في قراءة الناتج من البرنامج النصي PHP من خلال برنامج C هو نوع من العلم الأحمر ، وأظن أن هناك على الأرجح بعض نظافة الحل الشامل إلى هذا, ولكن من الصعب أن أقول أكثر من ذلك دون أعلى مستوى وصف ما كنت تحاول القيام به.

تذكر عند استخدام execl() وسوف "الخروج على النجاح".لذا لن ترى "End وظيفة php" لأنه لن تحصل على هذا الخط من التعليمات البرمجية.

للتغلب على هذه المشكلة يمكنك إما استخدام system أو استخدام fork() لخلق طفل العملية في طفلك عملية استخدام execl أو أي وظيفة أخرى من exec الأسرة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top