تنفيذ البرنامج النصي php من برنامج C تخزين النتائج في متغير
سؤال
أود أن تنفيذ البرنامج النصي 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
الأسرة.