سؤال

أنا أكتب شل الخاص بي في C.يجب أن يكون قادرًا على عرض الدليل الحالي للمستخدمين وتنفيذ الأوامر بناءً على المسار الكامل (يجب استخدام execv)، والسماح للمستخدم بتغيير الدليل باستخدام القرص المضغوط.

هذا هو الواجب المنزلي.لقد أعطانا المعلم فقط كتابًا تمهيديًا أساسيًا عن لغة C وهيكلًا موجزًا ​​جدًا عن كيفية عمل البرنامج.نظرًا لأنني لست من الأشخاص الذين يستسلمون بسهولة، فقد كنت أبحث عن كيفية القيام بذلك لمدة ثلاثة أيام، لكنني الآن في حيرة من أمري.

هذا ما لدي حتى الآن:

  • يعرض اسم المستخدم الخاص بالمستخدم واسم الكمبيوتر والدليل الحالي (الإعدادات الافتراضية للدليل الرئيسي).
  • يطالب المستخدم بالإدخال، ويحصل على الإدخال
  • يقسم مدخلات المستخدم حسب " " إلى مجموعة من الوسائط
  • يقسم متغير البيئة PATH بمقدار ): "إلى مجموعة من الرموز المميزة

لست متأكدًا من كيفية المتابعة من هنا.أعلم أنه يجب علي استخدام الأمر execv ولكن في بحثي على Google لم أجد مثالًا أفهمه حقًا.على سبيل المثال، إذا كان الأمر bin/ls، فكيف يعرف execv عرض جميع الملفات/المجلدات من الدليل الرئيسي؟كيف أخبر النظام أنني غيرت الدليل؟

لقد كنت أستخدم هذا الموقع كثيرًا وكان مفيدًا: http://linuxgazette.net/111/ramankutty.html ولكن مرة أخرى، أنا في حيرة من أمري.

شكرا لمساعدتك.اسمحوا لي أن أعرف إذا كان ينبغي لي نشر بعض التعليمات البرمجية الموجودة لدي، فأنا لم أكن متأكدًا مما إذا كان ذلك ضروريًا أم لا.

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

المحلول

لتنفيذ الأمر cd، تحتاج فقط إلى استدعاء النظام chdir.

#include <unistd.h>

int chdir(
    const char *path /* the path name */
);

لذا يمكنك فقط الاتصال بشيء مثل:

int ret1 = chdir("../foo/bar");

قيمة الإرجاع chdir هو 0 عندما كان من الممكن التغيير إلى هذا الدليل و-1 إذا حدث خطأ.بالنسبة للخطأ، يجب عليك دمج صفحة الدليل.

يمكن التحقق من الدليل الحالي بواسطة أي برنامج، لذلك إذا قمت بتنفيذه ls بدون أية وسائط، يتحقق ls من الدليل الذي يعمل عليه ويستخدم هذا الدليل باعتباره الوسيط الوحيد.هذه ميزة لـ ls وليست لـ execv يتصل.

للجزء الثاني.

#include <unistd.h>
int execv(
     const char *path, /* programm path*/
     char *const argv[]/* argument vector*/
);

execv ينفذ ملفًا قابلاً للتنفيذ في المعطى path ومع الحجج الواردة في argv.لذلك إذا كنت تريد التنفيذ /bin/ls ../foo /bar, ، أنت بحاجة إلى شيء مماثل ل

char *cmd_str = "/bin/ls";
char *argv[] = {cmd_str, "../foo", "/bar", NULL };
if (execv(cmd_str, argv) == -1 ){
    /* an error occurred */
}

الخطأ الذي تم إرجاعه بواسطة execv هو -1.إذا كنت تريد معرفة سبب عدم تنفيذ الأمر، فراجع صفحات الدليل.

ال NULL في char *argv[] = {cmd_str, "../foo", "/bar", NULL }; هل هناك للإشارة إلى أنه لا توجد وسائط أخرى بعد NULL.

الجزء الثالث.عادةً ما يتعامل النظام القائم على Unix مع الأوامر التي تحتوي على / بداخلها كأوامر يمكن تنفيذها مباشرة.مما يعني أنك تتحقق أولاً مما إذا كانت هناك شرطة مائلة في سلسلة الأمر المحددة.

int ret_value;
if (strchr(cmd_str, '/')
    if (execv(cmd_str, argv) == -1 ){
        /* an error occurred */
    }

إذا لم يكن هناك شرطة مائلة، فأنت بحاجة إلى تصفح جميع الدلائل الموجودة فيها PATH وتحقق مما إذا كان يمكنك تنفيذ الأمر.لذا فإن الأمر المعطى هو ls ../foo /bar ويتيح لنا أن نفترض قيمة PATH يكون ".:/sbin:/bin:/usr/bin".سنحاول بعد ذلك التنفيذ أولاً ./ls ../foo /bar ثم /usr/bin/ls ../foo /bar وايضا الاخير /bin/ls ../foo /bar.

أتمنى أن يساعدك هذا.

نصائح أخرى

على سبيل المثال، إذا كان الأمر bin/ls, ، كيف execv هل تعرف عرض كافة الملفات/المجلدات من الدليل الرئيسي؟كيف أخبر النظام أنني غيرت الدليل؟

تحتوي كل عملية على دليل العمل الحالي، والذي يمكن تعديله باستخدام chdir.سوف ترث العمليات الفرعية دليل العمل من الوالدين.لذا بشكل عام، ستقوم شركة Shell الخاصة بك بإدارة دليل العمل الحالي الخاص بها استجابةً لـ cd الأوامر التي يدخلها المستخدم.عندما يتم إدخال أمر ليس مضمنًا، فسوف تقوم بذلك fork لإنشاء عملية فرعية ثم الاتصال execv هناك لتنفيذ الثنائي.

إذا كنت النمل أن تأخذ PATH في حالة أسماء البرامج التي لا تحتوي على أي جزء من الدليل، فيجب عليك تجربة جميع المجموعات الممكنة من ملف PATH العنصر واسم البرنامجيمكنك إما التحقق من وجود الملف المحدد، أو ببساطة محاولة تنفيذه ومتابعة الملف التالي في حالة فشل ذلك.أنا أسقط execv فشلت المكالمات، سيكون عليك الاتصال _exit من أجل إنهاء عملية الطفل.

لاحظ أن معظم الأصداف ستتعامل مع أي أمر يحتوي على ملف / كمسار يتم تمريره إليه execv مباشرة.إذا كان المسار لا يبدأ مع /, ، فهو مسار نسبي، وسيحله نظام التشغيل فيما يتعلق بدليل العمل الحالي.وبعبارة أخرى، bin/ls من المثال الخاص بك سوف يشير إلى ls ثنائي في bin الدليل وهو دليل فرعي لدليل العمل الحالي.الأوامر فقط التي لا تحتوي على أي منها / على الإطلاق يتم تفسيرها على أنها أمر مدمج (مثل cd) أو اسم بعض الثنائيات الموجودة على PATH.

الحجة الأولى ل execv هو المسار كما حسبته.العنصر الأول من argv القائمة تساوي تقليديًا الاسم كما تم إدخاله، أي.بدون اضافة PATH الدليل.بعد تلك الوسيطة الأولى، يتم تمرير أي معلمات سطر أوامر إضافية، متبوعة بـ a NULL لإنهاء القائمة.

أعتقد أن المشكلة تكمن في اعتقادك أن شركة Shell هي المسؤولة عن القيام بهذا العمل ls. ls ليس في الواقع "جزءًا" من الصدفة (في هذه الحالة على الأقل).القشرة ينفذ برنامج يسمى ls.يبدو أن معظم التعليقات تشرح كيفية العثور عليها ls, ، لكنني لا أعتقد أن هذا ما أنت في حيرة بشأنه.

يجب أن تفكر جيدًا في الهدف من الصدفة قبل أن تكتبها.أشارت التعليقات بشكل غير مباشر إلى حقيقة أن الصدفة "ببساطة" يجب أن "تستدعي" برامج مثل ls و chdir, ، وعدم أداء مهامهم.

ls يعرف من تلقاء نفسه أنه إذا لم يتم تقديم أي وسيطات، فمن المفترض أن يقوم بإدراج الملفات في دليل العمل الحالي كما تم إرجاعها بواسطة getcwd

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