क्या "argv [0] = नाम-का-निष्पादन योग्य" एक स्वीकृत मानक या सिर्फ एक आम सम्मेलन है?


102

main()C या C ++ एप्लिकेशन में तर्क पास करते समय , argv[0]हमेशा निष्पादन योग्य का नाम होगा ? या यह सिर्फ एक आम सम्मेलन है और 100% सच होने की गारंटी नहीं है?


20
यूनिक्स पर, विचार करें execl("/home/hacker/.hidden/malicious", "/bin/ls", "-s", (char *)0);:। निष्पादन योग्य भालू का नाम मूल्य के संबंध में नहीं है argv[0]
जोनाथन लेफ़लर

जवाबों:


119

अनुमान (शिक्षित अंदाज़ा भी) मज़ेदार है लेकिन आपको वास्तव में सुनिश्चित होने के लिए मानकों के दस्तावेजों में जाने की आवश्यकता है। उदाहरण के लिए, आईएसओ सी 11 में कहा गया है (मेरा जोर):

यदि मान argcशून्य से अधिक है, तो इसके द्वारा इंगित स्ट्रिंग प्रोग्राम के नाम का argv[0] प्रतिनिधित्व करती है; argv[0][0]यदि प्रोग्राम का नाम होस्ट वातावरण से उपलब्ध नहीं है, तो अशक्त वर्ण होगा।

तो नहीं, यह केवल कार्यक्रम का नाम है यदि वह नाम उपलब्ध है। और यह प्रोग्राम के नाम का "प्रतिनिधित्व" करता है, जरूरी नहीं कि यह प्रोग्राम का नाम ही हो। इससे पहले का खंड बताता है:

यदि मान argcशून्य से अधिक है, तो समावेशी के argv[0]माध्यम से सरणी सदस्यों में argv[argc-1]स्ट्रिंगर्स को पॉइंटर्स होंगे, जिन्हें प्रोग्राम स्टार्टअप से पहले होस्ट वातावरण द्वारा कार्यान्वयन-परिभाषित मान दिए जाते हैं।

यह C99, पिछले मानक से अपरिवर्तित है, और इसका मतलब है कि यहां तक ​​कि मान भी मानक द्वारा निर्धारित नहीं हैं - यह पूरी तरह से कार्यान्वयन तक है।

इसका मतलब यह है कि यदि होस्ट वातावरण प्रदान नहीं करता है, और होस्ट वातावरण यदि कुछ और है तो प्रोग्राम का नाम खाली हो सकता है प्रदान करता है , बशर्ते कि "कुछ और" किसी भी तरह प्रोग्राम नाम का प्रतिनिधित्व करता है। अपने अधिक दुखद क्षणों में, मैं इसे स्वाहिली में तब्दील करने पर विचार करूंगा, इसे एक प्रतिस्थापन सिफर के माध्यम से चलाने के बाद इसे रिवर्स बाइट क्रम में संग्रहीत किया जाएगा :-)।

हालांकि, कार्यान्वयन से परिभाषित करता है कार्यान्वयन जरूरी दस्तावेज यह कैसे काम करता - आईएसओ मानक में एक विशेष अर्थ है। यहां तक ​​कि UNIX, जो कॉल argv[0]के execपरिवार के साथ अपनी पसंद के अनुसार कुछ भी रख सकता है , उसे दस्तावेज़ करना (और करना) है।


3
यह मानक हो सकता है, लेकिन यूनिक्स बस इसे लागू नहीं करता है, और आप इस पर भरोसा नहीं कर सकते।
dmckee --- पूर्व-संचालक बिल्ली का बच्चा

4
सवाल यूनिक्स का उल्लेख नहीं था सब पर । यह एक सी प्रश्न सादा और सरल था, इसलिए आईएसओ सी संदर्भ का दस्तावेज है। कार्यक्रम का नाम कार्यान्वयन मानक में परिभाषित किया गया है इसलिए एक कार्यान्वयन ऐसा करने के लिए स्वतंत्र है, जिसमें कुछ ऐसा करने की अनुमति है जिसमें वास्तविक नाम नहीं है - मुझे लगा कि मैं उस वाक्य को स्पष्ट करूंगा।
paxdiablo

2
पैक्स, मैं तुम्हें नीचे मतदान नहीं किया था, और जो लोग किया क्योंकि इस जवाब के रूप में आधिकारिक है, क्योंकि यह की मंजूरी नहीं देते कर सकते हैं मिलता है। लेकिन मुझे लगता है कि argv[0]वास्तविक दुनिया में प्रोग्रामिंग के लिए एप्रोपोस के मूल्य की अविश्वसनीयता है ।
dmckee --- पूर्व-मध्यस्थ ने बिल्ली का बच्चा

4
@caf, यह सही है। मैंने इसे कार्यक्रम के पूर्ण पथ ('/ progpath / prog'), केवल फ़ाइल नाम ('ठेला'), थोड़ा संशोधित नाम ('-प्रोग'), एक वर्णनात्मक नाम (') के रूप में इस तरह की विविध चीजों को पकड़े हुए देखा है। प्रोग - 'प्रोगिंग' के लिए एक प्रोग्राम) और कुछ नहीं ('')। कार्यान्वयन को परिभाषित करना है कि यह क्या रखता है लेकिन यह सभी मानक की आवश्यकता है।
paxdiablo

3
सबको धन्यवाद! (एक प्रतीत होता है) सरल प्रश्न से महान चर्चा। यद्यपि रिचर्ड का उत्तर * निक्स ऑपरेटिंग सिस्टम के लिए मान्य है, मैंने पैक्सिडैब्लो का उत्तर चुना क्योंकि मैं एक विशिष्ट ओएस के व्यवहार में कम दिलचस्पी रखता हूं, और मुख्य रूप से एक स्वीकृत मानक के अस्तित्व (या अनुपस्थिति) में दिलचस्पी रखता हूं। (यदि आप उत्सुक हैं: मूल प्रश्न के संदर्भ में - मेरे पास कोई ऑपरेटिंग सिस्टम नहीं है। मैं एक एम्बेडेड डिवाइस पर लोड किए गए निष्पादन योग्य के लिए कच्चे argc / argv बफर बनाने के लिए कोड लिख रहा हूं और यह जानने की जरूरत है कि मुझे क्या करना चाहिए argv के साथ [को ०]। भयानक होने के लिए +1 StackOverflow!
माइक विलेक्स

49

कॉल के *nixसाथ टाइप सिस्टम के तहत exec*(), argv[0]कॉलर जो भी argv0स्पॉट में डालता है, वह होगाexec*()

शेल कन्वेंशन का उपयोग करता है कि यह प्रोग्राम का नाम है, और अधिकांश अन्य प्रोग्राम एक ही सम्मेलन का पालन करते हैं, इसलिए argv[0] आमतौर पर प्रोग्राम का नाम।

लेकिन एक दुष्ट यूनिक्स कार्यक्रम कॉल कर सकता है exec()और argv[0]इसे कुछ भी पसंद कर सकता है, इसलिए कोई भी बात नहीं है कि सी मानक क्या कहता है, आप इस 100% समय पर भरोसा नहीं कर सकते।


4
यह पैक्सिडाब्लो के ऊपर से बेहतर उत्तर है। मानक इसे केवल "प्रोग्राम नाम" कहता है, लेकिन यह मेरे ज्ञान के लिए कहीं भी लागू नहीं है। यूनिक्स गुठली समान रूप से बच्चे की प्रक्रिया को अपरिवर्तित करने के लिए पारित स्ट्रिंग () को पास करती है।
एंडी रॉस

4
C मानक सीमित है जो वह कह सकता है क्योंकि यह 'निष्पादित ()' आदि के बारे में नहीं जानता है। POSIX मानक ( opengroup.org/onlinepubs/9699919799/functions/execve.html ) के पास कहने के लिए और अधिक है - इसे स्पष्ट करना कि argv में क्या है [0] इस प्रक्रिया के चक्कर में है कि 'निष्पादित ()' (या संबंधित) सिस्टम कॉल को निष्पादित करता है।
जोनाथन लेफ्लर

1
@ और, आप अपनी राय देने के लिए स्वतंत्र हैं :-) लेकिन आप प्रवर्तन के बारे में गलत हैं। यदि कोई कार्यान्वयन मानक का पालन नहीं करता है, तो यह गैर-अनुरूप है। और वास्तव में, के बाद से यह के कार्यान्वयन से परिभाषित क्या "कार्यक्रम का नाम" है, यूनिक्स की तरह एक ओएस के रूप में किया जाता है जब तक कि यह निर्दिष्ट करता है क्या नाम है अनुरूप है। इसमें कॉल के एक्जीक्यूटिव परिवार में वांछित किसी भी चीज के साथ argv [0] को लोड करके प्रोग्राम नाम को नकली रूप से नकली करने में सक्षम होना शामिल है।
पैक्साडब्लो

यह मानक में "प्रतिनिधित्व" शब्द की सुंदरता है जब यह argv को संदर्भित करता है [0] ("यह प्रोग्राम नाम का प्रतिनिधित्व करता है") और argv [1..N] ("वे प्रोग्राम तर्क का प्रतिनिधित्व करते हैं")। "अनलैडल स्वैलोज़" एक वैध प्रोग्राम नाम है।
रिचर्ड पेनिंग्टन

9

सी ++ मानक के अनुसार, खंड 3.6.1:

argv [0] एक NTMBS के प्रारंभिक चरित्र का सूचक होगा जो प्रोग्राम को लागू करने के लिए उपयोग किए जाने वाले नाम का प्रतिनिधित्व करता है या ""

तो नहीं, यह गारंटी नहीं है, कम से कम मानक द्वारा।


5
मुझे लगता है कि अशक्त बहु-बाइट स्ट्रिंग को समाप्त कर दिया गया है?
पाक्सिडाब्लो

6

आईएसओ-आईईसी 9899 राज्य:

5.1.2.2.1 प्रोग्राम स्टार्टअप

यदि मान argcशून्य से अधिक है, तो इसके द्वारा इंगित स्ट्रिंग argv[0]प्रोग्रामनाम का प्रतिनिधित्व करती है; argv[0][0]यदि प्रोग्राम का नाम होस्ट वातावरण से उपलब्ध नहीं है, तो अशक्त वर्ण होगा। यदि का मान argcएक से अधिक है, तार द्वारा की ओर इशारा किया argv[1]के माध्यम से argv[argc-1]प्रतिनिधित्व कार्यक्रम मानकों

मैंने भी उपयोग किया है:

#if defined(_WIN32)
  static size_t getExecutablePathName(char* pathName, size_t pathNameCapacity)
  {
    return GetModuleFileNameA(NULL, pathName, (DWORD)pathNameCapacity);
  }
#elif defined(__linux__) /* elif of: #if defined(_WIN32) */
  #include <unistd.h>
  static size_t getExecutablePathName(char* pathName, size_t pathNameCapacity)
  {
    size_t pathNameSize = readlink("/proc/self/exe", pathName, pathNameCapacity - 1);
    pathName[pathNameSize] = '\0';
    return pathNameSize;
  }
#elif defined(__APPLE__) /* elif of: #elif defined(__linux__) */
  #include <mach-o/dyld.h>
  static size_t getExecutablePathName(char* pathName, size_t pathNameCapacity)
  {
    uint32_t pathNameSize = 0;

    _NSGetExecutablePath(NULL, &pathNameSize);

    if (pathNameSize > pathNameCapacity)
      pathNameSize = pathNameCapacity;

    if (!_NSGetExecutablePath(pathName, &pathNameSize))
    {
      char real[PATH_MAX];

      if (realpath(pathName, real) != NULL)
      {
        pathNameSize = strlen(real);
        strncpy(pathName, real, pathNameSize);
      }

      return pathNameSize;
    }

    return 0;
  }
#else /* else of: #elif defined(__APPLE__) */
  #error provide your own implementation
#endif /* end of: #if defined(_WIN32) */

और फिर आपको पथ से निष्पादन योग्य नाम निकालने के लिए बस स्ट्रिंग को पार्स करना होगा।


2
/proc/self/path/a.outसिमलिंक Solaris 10 और अप पर प्रयोग करने योग्य हो सकता है।
ephemient

कोड के लिए अपवोट किया गया (यह आदर्श या सही नहीं है, उदाहरण के लिए विंडोज पर GetModuleFileNameWकिसी भी पथ को पुनः प्राप्त करने में सक्षम होने के लिए उपयोग किया जाना चाहिए, लेकिन कोड की उपस्थिति अच्छे मार्गदर्शन का गठन करती है)।
चीयर्स एंड हीथ। - अल्फ

4

argv[0] !=निष्पादन योग्य नाम रखने के अनुप्रयोग

  • कई गोले यह निर्धारित करते हैं कि क्या वे जाँच द्वारा एक लॉगिन शेल हैं argv[0][0] == '-'। लॉगिन शेल में अलग-अलग गुण होते हैं, विशेष रूप से यह कि वे कुछ डिफ़ॉल्ट फ़ाइलों को स्रोत बनाते हैं /etc/profile

    यह आमतौर पर init ही होता है या gettyजो अग्रणी जोड़ता है -, यह भी देखें: /unix/299408/how-to-login-automatically-without-typing-the-root-username-or-password -इन-निर्माण / 300,152 # 300,152

  • बहु-कॉल बायनेरिज़, शायद सबसे ज्यादा व्यस्त बिजीबॉक्स । ये सिमलिंक कई नामों जैसे /bin/shऔर /bin/lsएक एकल छूट के लिए /bin/busybox, जो पहचानता है कि किस उपकरण का उपयोग करना है argv[0]

    यह एक छोटे से सांख्यिकीय रूप से जुड़े निष्पादन योग्य को संभव बनाता है जो कई उपकरणों का प्रतिनिधित्व करता है, और मूल रूप से किसी भी लिनक्स वातावरण पर काम करेगा।

इसे भी देखें: /unix/315812/why-does-argv-include-the-program-name/315817

चलने योग्य POSIX execveउदाहरण जहां argv[0] !=निष्पादन योग्य नाम

दूसरों का उल्लेख किया exec , लेकिन यहाँ एक उदाहरण है।

एसी

#define _XOPEN_SOURCE 700
#include <unistd.h>

int main(void) {
    char *argv[] = {"yada yada", NULL};
    char *envp[] = {NULL};
    execve("b.out", argv, envp);
}

बीसी

#include <stdio.h>

int main(int argc, char **argv) {
    puts(argv[0]);
}

फिर:

gcc a.c -o a.out
gcc b.c -o b.out
./a.out

देता है:

yada yada

हाँ, argv[0]यह भी हो सकता है:

उबंटू 16.10 पर परीक्षण किया गया।


3

यह पृष्ठ बताता है:

तत्व argv [0] आम तौर पर कार्यक्रम का नाम शामिल है, लेकिन यह पर भरोसा नहीं किया जाना चाहिए - वैसे भी एक कार्यक्रम के लिए असामान्य है कि उसका खुद का नाम नहीं पता!

हालांकि, अन्य पृष्ठ इस तथ्य का समर्थन करते हैं कि यह हमेशा निष्पादन योग्य का नाम है। यह बताता है:

आप देखेंगे कि argv [0] कार्यक्रम का मार्ग और नाम है। यह प्रोग्राम को अपने बारे में जानकारी खोजने की अनुमति देता है। यह प्रोग्राम तर्क के सरणी में एक और जोड़ देता है, इसलिए कमांड-लाइन तर्क प्राप्त करते समय एक सामान्य त्रुटि argv [0] को हथियाने के लिए होती है जब आप argv [1] चाहते हैं।


11
कुछ कार्यक्रम इस तथ्य का लाभ उठाते हैं कि वे उस नाम को नहीं जानते हैं जो उन्हें आमंत्रित करने के लिए उपयोग किया गया था। मेरा मानना ​​है कि बिजीबॉक्स ( busybox.net/about.html ) इस तरह से काम करता है। कई अलग-अलग कमांड-लाइन उपयोगिताओं को लागू करने वाला केवल एक निष्पादन योग्य है। यह प्रतीकात्मक लिंक का एक गुच्छा और argv का उपयोग करता है [0] यह निर्धारित करने के लिए कि कमांड-लाइन टूल को क्या चलाया जाना चाहिए
Trent

हाँ, मुझे याद है कि "गनज़िप" "गज़िप" का एक प्रतीकात्मक लिंक था, और एक पल के लिए आश्चर्य हुआ कि यह कैसे काम करता है।
डेविड थॉर्नले

2
कई कार्यक्रम सूचना के लिए argv [0] को देखते हैं; उदाहरण के लिए, यदि नाम का अंतिम घटक डैश ('/ बिन / -श', उदाहरण के लिए) से शुरू होता है, तो शेल प्रोफाइल और अन्य सामान को एक लॉगिन शेल के रूप में चलाएगा।
जोनाथन लेफ्लर

2
@Jon: मैंने सोचा कि लॉगिन गोले किसके साथ शुरू किए गए थे argv[0]="-/bin/sh"? मैंने जितनी भी मशीनें इस्तेमाल की हैं, उन पर यही स्थिति है।
ephemient

3

मुझे यकीन नहीं है कि यह लगभग सार्वभौमिक सम्मेलन या एक मानक है, लेकिन किसी भी तरह से आपको इसका पालन करना चाहिए। मैंने इसे यूनिक्स और यूनिक्स जैसी प्रणालियों के बाहर कभी नहीं देखा है, हालांकि। यूनिक्स वातावरण में - और शायद विशेष रूप से पुराने दिनों में - कार्यक्रमों में उस नाम के आधार पर काफी भिन्न व्यवहार हो सकते हैं जिसके तहत उन्हें आमंत्रित किया गया है।

संपादित करें: मैं अन्य पदों से उसी समय को देखता हूं जैसे कि किसी ने इसे किसी विशेष मानक से आने के रूप में पहचाना है, लेकिन मुझे यकीन है कि सम्मेलन लंबे समय तक मानक का अनुमान लगाता है।


1
मुझे यकीन है कि अगर लोग मेरी प्रतिक्रिया को "चिह्नित" करने जा रहे हैं तो वे कुछ संकेत देंगे कि उन्हें इसके बारे में क्या पसंद नहीं है।
जोबेल

0

यदि आप वर्कबेन्च arvv द्वारा अमिगा कार्यक्रम शुरू करते हैं [0], केवल CLI द्वारा सेट नहीं किया जाएगा।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.