main()
C या C ++ एप्लिकेशन में तर्क पास करते समय , argv[0]
हमेशा निष्पादन योग्य का नाम होगा ? या यह सिर्फ एक आम सम्मेलन है और 100% सच होने की गारंटी नहीं है?
main()
C या C ++ एप्लिकेशन में तर्क पास करते समय , argv[0]
हमेशा निष्पादन योग्य का नाम होगा ? या यह सिर्फ एक आम सम्मेलन है और 100% सच होने की गारंटी नहीं है?
जवाबों:
अनुमान (शिक्षित अंदाज़ा भी) मज़ेदार है लेकिन आपको वास्तव में सुनिश्चित होने के लिए मानकों के दस्तावेजों में जाने की आवश्यकता है। उदाहरण के लिए, आईएसओ सी 11 में कहा गया है (मेरा जोर):
यदि मान
argc
शून्य से अधिक है, तो इसके द्वारा इंगित स्ट्रिंग प्रोग्राम के नाम काargv[0]
प्रतिनिधित्व करती है;argv[0][0]
यदि प्रोग्राम का नाम होस्ट वातावरण से उपलब्ध नहीं है, तो अशक्त वर्ण होगा।
तो नहीं, यह केवल कार्यक्रम का नाम है यदि वह नाम उपलब्ध है। और यह प्रोग्राम के नाम का "प्रतिनिधित्व" करता है, जरूरी नहीं कि यह प्रोग्राम का नाम ही हो। इससे पहले का खंड बताता है:
यदि मान
argc
शून्य से अधिक है, तो समावेशी केargv[0]
माध्यम से सरणी सदस्यों मेंargv[argc-1]
स्ट्रिंगर्स को पॉइंटर्स होंगे, जिन्हें प्रोग्राम स्टार्टअप से पहले होस्ट वातावरण द्वारा कार्यान्वयन-परिभाषित मान दिए जाते हैं।
यह C99, पिछले मानक से अपरिवर्तित है, और इसका मतलब है कि यहां तक कि मान भी मानक द्वारा निर्धारित नहीं हैं - यह पूरी तरह से कार्यान्वयन तक है।
इसका मतलब यह है कि यदि होस्ट वातावरण प्रदान नहीं करता है, और होस्ट वातावरण यदि कुछ और है तो प्रोग्राम का नाम खाली हो सकता है प्रदान करता है , बशर्ते कि "कुछ और" किसी भी तरह प्रोग्राम नाम का प्रतिनिधित्व करता है। अपने अधिक दुखद क्षणों में, मैं इसे स्वाहिली में तब्दील करने पर विचार करूंगा, इसे एक प्रतिस्थापन सिफर के माध्यम से चलाने के बाद इसे रिवर्स बाइट क्रम में संग्रहीत किया जाएगा :-)।
हालांकि, कार्यान्वयन से परिभाषित करता है कार्यान्वयन जरूरी दस्तावेज यह कैसे काम करता - आईएसओ मानक में एक विशेष अर्थ है। यहां तक कि UNIX, जो कॉल argv[0]
के exec
परिवार के साथ अपनी पसंद के अनुसार कुछ भी रख सकता है , उसे दस्तावेज़ करना (और करना) है।
argv[0]
वास्तविक दुनिया में प्रोग्रामिंग के लिए एप्रोपोस के मूल्य की अविश्वसनीयता है ।
कॉल के *nix
साथ टाइप सिस्टम के तहत exec*()
, argv[0]
कॉलर जो भी argv0
स्पॉट में डालता है, वह होगाexec*()
।
शेल कन्वेंशन का उपयोग करता है कि यह प्रोग्राम का नाम है, और अधिकांश अन्य प्रोग्राम एक ही सम्मेलन का पालन करते हैं, इसलिए argv[0]
आमतौर पर प्रोग्राम का नाम।
लेकिन एक दुष्ट यूनिक्स कार्यक्रम कॉल कर सकता है exec()
और argv[0]
इसे कुछ भी पसंद कर सकता है, इसलिए कोई भी बात नहीं है कि सी मानक क्या कहता है, आप इस 100% समय पर भरोसा नहीं कर सकते।
सी ++ मानक के अनुसार, खंड 3.6.1:
argv [0] एक NTMBS के प्रारंभिक चरित्र का सूचक होगा जो प्रोग्राम को लागू करने के लिए उपयोग किए जाने वाले नाम का प्रतिनिधित्व करता है या ""
तो नहीं, यह गारंटी नहीं है, कम से कम मानक द्वारा।
आईएसओ-आईईसी 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) */
और फिर आपको पथ से निष्पादन योग्य नाम निकालने के लिए बस स्ट्रिंग को पार्स करना होगा।
/proc/self/path/a.out
सिमलिंक Solaris 10 और अप पर प्रयोग करने योग्य हो सकता है।
GetModuleFileNameW
किसी भी पथ को पुनः प्राप्त करने में सक्षम होने के लिए उपयोग किया जाना चाहिए, लेकिन कोड की उपस्थिति अच्छे मार्गदर्शन का गठन करती है)।
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 पर परीक्षण किया गया।
यह पृष्ठ बताता है:
तत्व argv [0] आम तौर पर कार्यक्रम का नाम शामिल है, लेकिन यह पर भरोसा नहीं किया जाना चाहिए - वैसे भी एक कार्यक्रम के लिए असामान्य है कि उसका खुद का नाम नहीं पता!
हालांकि, अन्य पृष्ठ इस तथ्य का समर्थन करते हैं कि यह हमेशा निष्पादन योग्य का नाम है। यह बताता है:
आप देखेंगे कि argv [0] कार्यक्रम का मार्ग और नाम है। यह प्रोग्राम को अपने बारे में जानकारी खोजने की अनुमति देता है। यह प्रोग्राम तर्क के सरणी में एक और जोड़ देता है, इसलिए कमांड-लाइन तर्क प्राप्त करते समय एक सामान्य त्रुटि argv [0] को हथियाने के लिए होती है जब आप argv [1] चाहते हैं।
argv[0]="-/bin/sh"
? मैंने जितनी भी मशीनें इस्तेमाल की हैं, उन पर यही स्थिति है।
मुझे यकीन नहीं है कि यह लगभग सार्वभौमिक सम्मेलन या एक मानक है, लेकिन किसी भी तरह से आपको इसका पालन करना चाहिए। मैंने इसे यूनिक्स और यूनिक्स जैसी प्रणालियों के बाहर कभी नहीं देखा है, हालांकि। यूनिक्स वातावरण में - और शायद विशेष रूप से पुराने दिनों में - कार्यक्रमों में उस नाम के आधार पर काफी भिन्न व्यवहार हो सकते हैं जिसके तहत उन्हें आमंत्रित किया गया है।
संपादित करें: मैं अन्य पदों से उसी समय को देखता हूं जैसे कि किसी ने इसे किसी विशेष मानक से आने के रूप में पहचाना है, लेकिन मुझे यकीन है कि सम्मेलन लंबे समय तक मानक का अनुमान लगाता है।
execl("/home/hacker/.hidden/malicious", "/bin/ls", "-s", (char *)0);
:। निष्पादन योग्य भालू का नाम मूल्य के संबंध में नहीं हैargv[0]
।