system(3)

الاسم
system - تنفيذ أمر شل

المكتبة
مكتبة سي المعيارية (libc، -lc)

موجز
#include <stdlib.h>

int system(const char *command);

الوصف
تتصرف دالة المكتبة system() كما لو أنها استخدمت fork(2) لإنشاء عملية فرعية تنفذ أمر الشل المحدد في command باستخدام execl(3) كالتالي:

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

تعود system() بعد اكتمال الأمر.

أثناء تنفيذ الأمر، يُحجب SIGCHLD، ويُتجاهل SIGINT و SIGQUIT، في العملية التي تستدعي system(). (تُعالج هذه الإشارات وفقًا لمبدئياتها داخل العملية الفرعية التي تنفذ command.)

إذا كان command فارغًا، تعيد system() حالة تشير إلى توفر شل في النظام.

قيمة الإرجاع
قيمة عودة system() هي إحدى التالية:

•   إذا كان command فارغًا، فقيمة غير صفرية إذا توفر شل، أو 0 إذا لم يتوفر شل.

•   إذا تعذر إنشاء عملية فرعية، أو تعذر استرداد حالتها، تكون قيمة العودة -1 ويُضبط errno للإشارة إلى الخطأ.

•   إذا تعذر تنفيذ شل في العملية الفرعية، تكون قيمة العودة كما لو أن شل الفرعية أنهيت باستدعاء _exit(2) بالحالة 127.

•   إذا نجحت جميع استدعاءات النظام، تكون قيمة العودة هي حالة إنهاء شل الفرعية المستخدمة لتنفيذ command. (حالة إنهاء شل هي حالة إنهاء آخر أمر تنفذه.)

في الحالتين الأخيرتين، قيمة العودة هي "حالة انتظار" يمكن فحصها باستخدام الكليّات الموصوفة في waitpid(2). (أي WIFEXITED()، WEXITSTATUS()، وهكذا).

لا تؤثر system() على حالة انتظار أي أطفال آخرين.

الأخطاء
قد تفشل system() بأي من نفس الأخطاء مثل fork(2).

السمات
للاطلاع على شرح للمصطلحات المستخدمة في هذا القسم، انظر attributes(7).
الواجهة | السمة | القيمة
system() | سلامة الخيوط | MT-Safe

المعايير
C11, POSIX.1-2008.

التاريخ
POSIX.1-2001، C89.

ملاحظات
توفر system() البساطة والراحة: فهي تعالج جميع تفاصيل استدعاء fork(2) و execl(3) و waitpid(2)، بالإضافة إلى التلاعبات الضرورية بالإشارات؛ بالإضافة إلى ذلك، ينفذ الشل الاستبدالات المعتادة وإعادة توجيه الإدخال/الإخراج لـ command. التكلفة الرئيسية لـ system() هي عدم الكفاءة: استدعاءات نظام إضافية مطلوبة لإنشاء العملية التي تشغل الشل وتنفيذ الشل.

إذا عُرفت كليّة اختبار الميزة _XOPEN_SOURCE (قبل تضمين أي ملفات رأس)، فتُتاح الكليّات الموصوفة في waitpid(2) (WEXITSTATUS()، إلخ) عند تضمين <stdlib.h>.

كما ذُكر، تتجاهل system() SIGINT و SIGQUIT. قد يجعل هذا البرامج التي تستدعيها من حلقة غير قابلة للمقاطعة، إلا إذا اهتمت بنفسها بفحص حالة خروج الطفل. على سبيل المثال:

    while (something) {
        int ret = system("foo");

        if (WIFSIGNALED(ret) &&
            (WTERMSIG(ret) == SIGINT || WTERMSIG(ret) == SIGQUIT))
                break;
    }

وفقًا لـ POSIX.1، لم يُحدد ما إذا كانت المعالجات المسجلة باستخدام pthread_atfork(3) تُستدعى أثناء تنفيذ system(). في تطبيق glibc، لا تُستدعى هذه المعالجات.

قبل glibc 2.1.3، لم يُجرَ التحقق من توفر /bin/sh فعليًا إذا كان command فارغًا؛ بل كان يُفترض دائمًا أنه متوفر، وكانت system() تُرجع 1 دائمًا في هذه الحالة. منذ glibc 2.1.3، يُجرى هذا التحقق لأنه، على الرغم من أن POSIX.1-2001 يتطلب من التطبيق المطابق توفير غلاف، إلا أن هذا الغلاف قد لا يكون متوفرًا أو قابلًا للتنفيذ إذا كان البرنامج المُستدعي قد استدعى سابقًا chroot(2) (وهو غير محدد بواسطة POSIX.1-2001).

من الممكن أن ينهي أمر الغلاف بحالة 127، مما يُنتج قيمة إرجاع من system() لا يمكن تمييزها عن الحالة التي لم يُنفذ فيها غلاف في العملية الابنة.

  تحذيرات
لا تستخدم system() من برنامج مُمتاز (برنامج set-user-ID أو set-group-ID، أو برنامج ذو صلاحيات) لأن القيم الغريبة لبعض متغيرات البيئة قد تُستخدم لتقويض سلامة النظام. على سبيل المثال، يمكن التلاعب بـ PATH لتنفيذ برنامج عشوائي بامتيازات. استخدم عائلة دوال exec(3) بدلاً من ذلك، ولكن ليس execlp(3) أو execvp(3) (والتي تستخدم أيضًا متغير البيئة PATH للبحث عن ملف قابل للتنفيذ).

في الواقع، لن تعمل system() بشكل صحيح من البرامج ذات امتيازات set-user-ID أو set-group-ID على الأنظمة التي يكون فيها /bin/sh هو bash الإصدار 2: كإجراء أمني، يُسقط bash 2 الامتيازات عند بدء التشغيل. (يستخدم Debian غلافًا مختلفًا، dash(1)، والذي لا يفعل ذلك عند استدعائه كـ sh.)

يجب تعقيم أي إدخال مستخدم يُستخدم كجزء من command بعناية، لضمان عدم تنفيذ أوامر غلاف أو خيارات أوامر غير متوقعة. هذه المخاطر خطيرة بشكل خاص عند استخدام system() من برنامج مُمتاز.

العلل
إذا بدأ اسم الأمر بواصلة، يُفسر sh(1) اسم الأمر كخيار، ويكون السلوك غير محدد. (انظر الخيار -c لـ sh(1).) لتجاوز هذه المشكلة، أسبق الأمر بمسافة كما في الاستدعاء التالي:

        system(" -unfortunate-command-name");

انظر أيضًا
sh(1), execve(2), fork(2), sigaction(2), sigprocmask(2), wait(2), exec(3), signal(7)

ترجمة
تُرجمت هذه الصفحة من الدليل بواسطة زايد السعيدي <zayed.alsaidi@gmail.com>

هذه الترجمة هي وثيقة مجانية؛ راجع رخصة جنو العامة الإصدار 3 (https://www.gnu.org/licenses/gpl-3.0.html) أو ما بعده للاطلاع على شروط حقوق النشر. لا توجد أي ضمانات.

إذا وجدت أي أخطاء في ترجمة صفحة الدليل هذه، يرجى إرسال بريد إلكتروني إلى قائمة بريد المترجمين: kde-l10n-ar@kde.org.