के उपयोग /proc/self/exe
गैर पोर्टेबल और अविश्वसनीय है। मेरे उबंटू 12.04 सिस्टम पर, आपको सिमलिंक पढ़ने / पालन करने के लिए रूट होना चाहिए। यह बूस्ट का उदाहरण देगा और शायद whereami()
पोस्ट किए गए समाधान विफल हो जाएंगे ।
यह पद बहुत लंबा है, लेकिन वास्तविक मुद्दों पर चर्चा करता है और कोड प्रस्तुत करता है जो वास्तव में एक परीक्षण सूट के खिलाफ सत्यापन के साथ काम करता है।
आपके प्रोग्राम को खोजने का सबसे अच्छा तरीका सिस्टम द्वारा उपयोग किए जाने वाले चरणों को वापस करना है। यह argv[0]
फ़ाइल सिस्टम रूट, pwd, पथ वातावरण और सिम्बलिंक्स और pathname विहितीकरण पर विचार करके हल किया गया है। यह स्मृति से है, लेकिन मैंने अतीत में इसे सफलतापूर्वक किया है और विभिन्न स्थितियों में इसका परीक्षण किया है। यह काम करने की गारंटी नहीं है, लेकिन अगर यह आपके पास बहुत बड़ी समस्याएं नहीं है और यह चर्चा की गई अन्य विधियों की तुलना में अधिक विश्वसनीय है। एक यूनिक्स सुसंगत प्रणाली पर स्थितियां हैं जिनमें से निपटने का उचित प्रबंध हैargv[0]
अपने कार्यक्रम के लिए नहीं मिलेगा, लेकिन फिर आप एक प्रमाणित रूप से टूटे हुए वातावरण में निष्पादित कर रहे हैं। यह 1970 के आसपास से सभी यूनिक्स व्युत्पन्न प्रणालियों और यहां तक कि कुछ गैर-यूनिक्स व्युत्पन्न प्रणालियों के लिए भी काफी पोर्टेबल है क्योंकि यह मूल रूप से libc () मानक कार्यक्षमता और मानक कमांड लाइन कार्यक्षमता पर निर्भर है। यह लिनक्स (सभी संस्करणों), एंड्रॉइड, क्रोम ओएस, मिनिक्स, मूल बेल लैब्स यूनिक्स, फ्रीबीएसडी, नेटबीएसडी, ओपनबीएसडी, बीएसडी एक्सएक्सएक्स, सनोस, सोलारिस, एसवाईएसवी, एचपीयूएक्स, कॉन्सेंट्रिक्स, एससीओ, डार्विन, एआईएक्स, ओएस एक्स पर काम करना चाहिए। Nextstep, आदि और थोड़ा संशोधन के साथ शायद VMS, VM / CMS, DOS / Windows, ReactOS, OS / 2, आदि। यदि कोई प्रोग्राम सीधे GUI वातावरण से लॉन्च किया गया था, तो इसे argv[0]
एक निरपेक्ष पथ पर सेट किया जाना चाहिए ।
यह समझें कि हर यूनिक्स संगत ऑपरेटिंग सिस्टम पर लगभग हर शेल जो कभी जारी किया गया है, मूल रूप से प्रोग्राम उसी तरह पाता है और ऑपरेटिंग वातावरण को लगभग उसी तरह सेट करता है (कुछ वैकल्पिक एक्स्ट्रा के साथ)। और किसी प्रोग्राम को लॉन्च करने वाले किसी अन्य प्रोग्राम से उस प्रोग्राम के लिए एक ही वातावरण (argv, एन्वायरनमेंट स्ट्रिंग्स, इत्यादि) बनाने की उम्मीद की जाती है, जैसे कि इसे किसी वैकल्पिक एक्स्ट्रा के साथ शेल से चलाया गया हो। एक प्रोग्राम या उपयोगकर्ता एक पर्यावरण को सेटअप कर सकता है जो इस सम्मेलन से अन्य अधीनस्थ कार्यक्रमों के लिए विचलित होता है जो इसे लॉन्च करता है लेकिन अगर ऐसा होता है, तो यह एक बग है और कार्यक्रम को कोई उचित उम्मीद नहीं है कि अधीनस्थ कार्यक्रम या इसके अधीनस्थ सही ढंग से काम करेंगे।
शामिल करने के संभावित मान argv[0]
:
/path/to/executable
- पूर्ण पथ
../bin/executable
- pwd के सापेक्ष
bin/executable
- pwd के सापेक्ष
./foo
- pwd के सापेक्ष
executable
- बेसन, पथ में खोजें
bin//executable
- पीडब्ल्यूडी के सापेक्ष, गैर-विहित
src/../bin/executable
- पीडब्ल्यूडी, गैर-विहित, बैकट्रैकिंग के सापेक्ष
bin/./echoargc
- पीडब्ल्यूडी के सापेक्ष, गैर-विहित
मान जिन्हें आपको नहीं देखना चाहिए:
~/bin/executable
- अपने कार्यक्रम को चलाने से पहले फिर से लिखा।
~user/bin/executable
- अपने कार्यक्रम को चलाने से पहले फिर से लिखा
alias
- अपने कार्यक्रम को चलाने से पहले फिर से लिखा
$shellvariable
- अपने कार्यक्रम को चलाने से पहले फिर से लिखा
*foo*
- वाइल्डकार्ड, आपके प्रोग्राम के चलने से पहले फिर से लिखे, बहुत उपयोगी नहीं है
?foo?
- वाइल्डकार्ड, आपके प्रोग्राम के चलने से पहले फिर से लिखे, बहुत उपयोगी नहीं है
इसके अलावा, इनमें गैर-विहित पथ नाम और प्रतीकात्मक लिंक की कई परतें हो सकती हैं। कुछ मामलों में, एक ही कार्यक्रम के लिए कई हार्ड लिंक हो सकते हैं। उदाहरण के लिए, /bin/ls
, /bin/ps
, /bin/chmod
, /bin/rm
, आदि के लिए हार्ड लिंक हो सकता है /bin/busybox
।
अपने आप को खोजने के लिए, नीचे दिए गए चरणों का पालन करें:
Pwd, PATH, और argv [0] को अपने प्रोग्राम में प्रवेश करने पर (या अपने पुस्तकालय के आरंभ में) सहेजें क्योंकि वे बाद में बदल सकते हैं।
वैकल्पिक: विशेष रूप से गैर-यूनिक्स प्रणालियों के लिए, अलग-अलग लेकिन पथनाम होस्ट / उपयोगकर्ता / ड्राइव उपसर्ग भाग को न छोड़ें, यदि मौजूद हो; वह हिस्सा जो अक्सर एक बृहदान्त्र से पहले या एक प्रारंभिक "//" का अनुसरण करता है।
यदि argv[0]
एक निरपेक्ष मार्ग है, तो उसे एक प्रारंभिक बिंदु के रूप में उपयोग करें। एक निरपेक्ष पथ शायद "/" से शुरू होता है, लेकिन कुछ गैर-यूनिक्स प्रणालियों पर यह "\" या एक ड्राइव लेटर या नाम उपसर्ग के बाद शुरू हो सकता है।
यदि argv[0]
कोई रिश्तेदार पथ है ("/" या "\" शामिल है, लेकिन इसके साथ शुरू नहीं होता है, जैसे "../../bin/foo", तो pwd + "/" + argv [0] को संयोजित करें (उपयोग करें) वर्तमान कार्यशील निर्देशिका जब कार्यक्रम शुरू हुआ, वर्तमान नहीं)।
इसके अलावा अगर argv [0] एक सादा बेसन (कोई स्लैश नहीं) है, तो इसे बारी-बारी से PATH पर्यावरण चर में प्रत्येक प्रविष्टि के साथ मिलाएं और उन लोगों को आज़माएं और पहले वाले का उपयोग करें जो सफल होता है।
वैकल्पिक: एल्से बहुत ही विशिष्ट प्लेटफ़ॉर्म /proc/self/exe
, /proc/curproc/file
(BSD) और (char *)getauxval(AT_EXECFN)
, और dlgetname(...)
यदि मौजूद हो, कोशिश करें। argv[0]
यदि आप उपलब्ध हैं और आप अनुमति के मुद्दों का सामना नहीं करते हैं, तो आप इन- आधारित विधियों की कोशिश कर सकते हैं। कुछ हद तक अप्रत्याशित घटना में (जब आप सभी प्रणालियों के सभी संस्करणों पर विचार करते हैं) कि वे मौजूद हैं और असफल नहीं होते हैं, तो वे अधिक आधिकारिक हो सकते हैं।
वैकल्पिक: कमांड लाइन पैरामीटर का उपयोग करके पारित किए गए पथ के नाम की जांच करें।
वैकल्पिक: यदि आपके आवरण स्क्रिप्ट द्वारा स्पष्ट रूप से पारित कर दिया गया है, तो पर्यावरण में एक मार्गनाम के लिए जाँच करें।
वैकल्पिक: अंतिम उपाय के रूप में पर्यावरण चर "_" का प्रयास करें। यह पूरी तरह से एक अलग कार्यक्रम को इंगित कर सकता है, जैसे कि उपयोगकर्ता शेल।
सीमलिंक का समाधान करें, कई परतें हो सकती हैं। अनंत छोरों की संभावना है, हालांकि यदि वे आपके कार्यक्रम में मौजूद हैं, तो संभवत: आह्वान नहीं किया जाएगा।
"/Foo/../bar/" से "/ बार /" जैसे सब्सट्रिंग को हल करके कैनन का नाम दें। ध्यान दें कि यह संभावित रूप से अर्थ बदल सकता है यदि आप एक नेटवर्क माउंट बिंदु को पार करते हैं, तो केनोनेज़ेशन हमेशा एक अच्छी बात नहीं है। नेटवर्क सर्वर पर, सिम्लिंक में ".." का उपयोग क्लाइंट के बजाय सर्वर संदर्भ में किसी अन्य फ़ाइल के पथ को पार करने के लिए किया जा सकता है। इस मामले में, आप संभवतः ग्राहक संदर्भ चाहते हैं ताकि विहितकरण ठीक हो। साथ ही "/ //" को "/" और "//" को "/" जैसे पैटर्न में परिवर्तित करें। शेल में, readlink --canonicalize
कई सीमलिंक और कैनोनिकलाइज़ नाम को हल करेगा। चेस समान हो सकता है लेकिन स्थापित नहीं है। realpath()
या canonicalize_file_name()
, यदि मौजूद हो, तो मदद कर सकता है।
यदि realpath()
संकलन समय पर मौजूद नहीं है, तो आप एक लाइसेंस प्राप्त लायसेंसधारी लायब्रेरी वितरण से एक प्रति उधार ले सकते हैं, और इसे पहिया को फिर से स्थापित करने के बजाय अपने आप में संकलित कर सकते हैं। यदि आप PATH_MAX से कम बफर का उपयोग कर रहे हैं, तो संभावित बफर ओवरफ़्लो को पास करें (साइज़ोफ़ आउटपुट बफर में पास करें, strncpy () बनाम strcpy ()) के बारे में सोचें। यदि यह मौजूद है तो परीक्षण के बजाय इसका नाम बदलकर निजी कॉपी का उपयोग करना आसान हो सकता है। Android / darwin / bsd से अनुज्ञापत्र लाइसेंस प्रति:
https://android.googlesource.com/platform/bionic/+/f077784/libc/upstream-freebsd/lib/libc/stdlib/realpath.c
इस बात से अवगत रहें कि कई प्रयास सफल या आंशिक रूप से सफल हो सकते हैं और वे सभी एक ही निष्पादन योग्य नहीं हो सकते हैं, इसलिए अपने निष्पादन योग्य को सत्यापित करने पर विचार करें; हालाँकि, आपने पढ़ने की अनुमति नहीं दी है - यदि आप इसे नहीं पढ़ सकते हैं, तो इसे असफलता न मानें। या अपने निष्पादन योग्य निकटता में कुछ सत्यापित करें जैसे कि "../lib/" निर्देशिका जिसे आप ढूंढने का प्रयास कर रहे हैं। आपके पास कई संस्करण, पैकेज्ड और स्थानीय रूप से संकलित संस्करण, स्थानीय और नेटवर्क संस्करण, और स्थानीय और यूएसबी-ड्राइव पोर्टेबल संस्करण, आदि हो सकते हैं और एक छोटी सी संभावना है कि आपको पता लगाने के विभिन्न तरीकों से दो असंगत परिणाम प्राप्त हो सकते हैं। और "_" केवल गलत प्रोग्राम को इंगित कर सकता है।
एक प्रोग्राम का उपयोग करके execve
जानबूझकर प्रोग्राम argv[0]
को लोड करने के लिए उपयोग किए जाने वाले वास्तविक पथ के साथ असंगत होने के लिए सेट किया जा सकता है और PATH, "_", pwd इत्यादि को लोड करने के लिए उपयोग किया जाता है, हालांकि आमतौर पर ऐसा करने का कोई कारण नहीं है; लेकिन इसका सुरक्षा निहितार्थ हो सकता है यदि आपके पास असुरक्षित कोड है जो इस तथ्य को नजरअंदाज करता है कि आपके निष्पादन का वातावरण सहित विभिन्न तरीकों से बदला जा सकता है, लेकिन यह सीमित नहीं है, इस एक के लिए (चुरोट, फ़्यूज़ फाइल सिस्टम, हार्ड लिंक, आदि) संभव है। PATH को सेट करने के लिए शेल कमांड के लिए, लेकिन इसे निर्यात करने में विफल।
गैर-यूनिक्स प्रणालियों के लिए आपको कोड की आवश्यकता नहीं है, लेकिन कुछ विशिष्टताओं के बारे में पता होना एक अच्छा विचार होगा, ताकि आप कोड को इस तरह से लिख सकें कि बाद में पोर्ट करना किसी के लिए उतना कठिन न हो। । विदित हो कि कुछ सिस्टम (DEC VMS, DOS, URL इत्यादि) में ड्राइव नाम या अन्य उपसर्ग हो सकते हैं जो कि "C: \", "sys $ ड्राइव: [foo] बार", और "फ़ाइल" : /// foo / बार / baz "। पुराने DEC VMS सिस्टम पथ के निर्देशिका भाग को संलग्न करने के लिए "[" और "]" का उपयोग करते हैं, हालांकि यदि आपका कार्यक्रम POSIX वातावरण में संकलित किया गया है तो यह बदल सकता है। कुछ सिस्टम, जैसे VMS, का फ़ाइल संस्करण हो सकता है (अंत में अर्धविराम द्वारा अलग किया गया)। कुछ सिस्टम "// ड्राइव / पाथ / टू / फाइल" या "यूजर @ होस्ट: / पाथ / टू / फाइल" (scp कमांड) या "फाइल:" के रूप में दो लगातार स्लैश का उपयोग करते हैं। (रिक्त स्थान के साथ सीमांकित) और "पेट" कॉलोनों के साथ सीमांकित किया गया है, लेकिन आपके कार्यक्रम को पेटीएम प्राप्त करना चाहिए ताकि आपको पथ के लिए चिंता करने की आवश्यकता न हो। डॉस और कुछ अन्य प्रणालियों में एक पथ उपसर्ग के साथ शुरू होने वाले सापेक्ष पथ हो सकते हैं। C: foo.exe ड्राइव C पर वर्तमान निर्देशिका में foo.exe को संदर्भित करता है, इसलिए आपको C पर वर्तमान निर्देशिका देखने की आवश्यकता है: और pwd के लिए इसका उपयोग करें। (रिक्त स्थान के साथ सीमांकित) और "पेट" कॉलोनों के साथ सीमांकित किया गया है, लेकिन आपके कार्यक्रम को पेटीएम प्राप्त करना चाहिए ताकि आपको पथ के लिए चिंता करने की आवश्यकता न हो। डॉस और कुछ अन्य प्रणालियों में एक पथ उपसर्ग के साथ शुरू होने वाले सापेक्ष पथ हो सकते हैं। C: foo.exe ड्राइव C पर वर्तमान निर्देशिका में foo.exe को संदर्भित करता है, इसलिए आपको C पर वर्तमान निर्देशिका देखने की आवश्यकता है: और pwd के लिए इसका उपयोग करें।
मेरे सिस्टम पर सहानुभूति और आवरण का एक उदाहरण:
/usr/bin/google-chrome is symlink to
/etc/alternatives/google-chrome which is symlink to
/usr/bin/google-chrome-stable which is symlink to
/opt/google/chrome/google-chrome which is a bash script which runs
/opt/google/chome/chrome
ध्यान दें कि उपयोगकर्ता बिल HP के एक प्रोग्राम के ऊपर एक लिंक पोस्ट करता है जो तीन बुनियादी मामलों को संभालता है argv[0]
। हालांकि इसमें कुछ बदलावों की जरूरत है:
- यह सब के पुनर्लेखन के लिए जरूरी होगा
strcat()
और strcpy()
उपयोग करने के लिए strncat()
और strncpy()
। भले ही चर लंबाई PATHMAX की घोषित की गई हो, लंबाई का इनपुट मान PATHMAX-1 प्लस समतल स्ट्रैंथ की लंबाई है> PATHMAX और लंबाई PATHMAX का एक इनपुट मान है।
- इसे केवल एक लाइब्रेरी फंक्शन के रूप में फिर से लिखने की आवश्यकता है, न कि केवल परिणामों को प्रिंट करने के लिए।
- यह नामों को कैनोनिकलाइज़ करने में विफल रहता है (ऊपर दिए गए लिंक से संबंधित realpath कोड का उपयोग करें)
- यह प्रतीकात्मक लिंक को हल करने में विफल रहता है (realpath कोड का उपयोग करें)
इसलिए, यदि आप एचपी कोड और रियलपथ कोड दोनों को मिलाते हैं और बफर ओवरफ्लो के लिए प्रतिरोधी होने के लिए दोनों को ठीक करते हैं, तो आपके पास कुछ ऐसा होना चाहिए जो ठीक से व्याख्या कर सके argv[0]
।
निम्नलिखित argv[0]
उबंटू 12.04 पर एक ही कार्यक्रम को लागू करने के विभिन्न तरीकों के वास्तविक मूल्यों को दर्शाता है । और हां, कार्यक्रम को गलती से गूंज का नाम दिया गया था। यह साफ नकल के लिए एक स्क्रिप्ट का उपयोग करके किया गया था, लेकिन इसे मैन्युअल रूप से शेल में करना एक ही परिणाम प्राप्त करता है (जब तक आप स्पष्ट रूप से उन्हें सक्षम नहीं करते हैं, तब तक एलियास स्क्रिप्ट में काम नहीं करता है)।
cat ~/src/echoargc.c
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
main(int argc, char **argv)
{
printf(" argv[0]=\"%s\"\n", argv[0]);
sleep(1); /* in case run from desktop */
}
tcc -o ~/bin/echoargc ~/src/echoargc.c
cd ~
/home/whitis/bin/echoargc
argv[0]="/home/whitis/bin/echoargc"
echoargc
argv[0]="echoargc"
bin/echoargc
argv[0]="bin/echoargc"
bin//echoargc
argv[0]="bin//echoargc"
bin/./echoargc
argv[0]="bin/./echoargc"
src/../bin/echoargc
argv[0]="src/../bin/echoargc"
cd ~/bin
*echo*
argv[0]="echoargc"
e?hoargc
argv[0]="echoargc"
./echoargc
argv[0]="./echoargc"
cd ~/src
../bin/echoargc
argv[0]="../bin/echoargc"
cd ~/junk
~/bin/echoargc
argv[0]="/home/whitis/bin/echoargc"
~whitis/bin/echoargc
argv[0]="/home/whitis/bin/echoargc"
alias echoit=~/bin/echoargc
echoit
argv[0]="/home/whitis/bin/echoargc"
echoarg=~/bin/echoargc
$echoarg
argv[0]="/home/whitis/bin/echoargc"
ln -s ~/bin/echoargc junk1
./junk1
argv[0]="./junk1"
ln -s /home/whitis/bin/echoargc junk2
./junk2
argv[0]="./junk2"
ln -s junk1 junk3
./junk3
argv[0]="./junk3"
gnome-desktop-item-edit --create-new ~/Desktop
# interactive, create desktop link, then click on it
argv[0]="/home/whitis/bin/echoargc"
# interactive, right click on gnome application menu, pick edit menus
# add menu item for echoargc, then run it from gnome menu
argv[0]="/home/whitis/bin/echoargc"
cat ./testargcscript 2>&1 | sed -e 's/^/ /g'
#!/bin/bash
# echoargc is in ~/bin/echoargc
# bin is in path
shopt -s expand_aliases
set -v
cat ~/src/echoargc.c
tcc -o ~/bin/echoargc ~/src/echoargc.c
cd ~
/home/whitis/bin/echoargc
echoargc
bin/echoargc
bin//echoargc
bin/./echoargc
src/../bin/echoargc
cd ~/bin
*echo*
e?hoargc
./echoargc
cd ~/src
../bin/echoargc
cd ~/junk
~/bin/echoargc
~whitis/bin/echoargc
alias echoit=~/bin/echoargc
echoit
echoarg=~/bin/echoargc
$echoarg
ln -s ~/bin/echoargc junk1
./junk1
ln -s /home/whitis/bin/echoargc junk2
./junk2
ln -s junk1 junk3
./junk3
ये उदाहरण बताते हैं कि इस पोस्ट में वर्णित तकनीकों को विस्तृत परिस्थितियों में काम करना चाहिए और कुछ कदम क्यों आवश्यक हैं।
संपादित करें: अब, जो प्रोग्राम प्रिंट करता है वह argv [0] को वास्तव में खुद को खोजने के लिए अपडेट किया गया है।
// Copyright 2015 by Mark Whitis. License=MIT style
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <limits.h>
#include <assert.h>
#include <string.h>
#include <errno.h>
// "look deep into yourself, Clarice" -- Hanibal Lector
char findyourself_save_pwd[PATH_MAX];
char findyourself_save_argv0[PATH_MAX];
char findyourself_save_path[PATH_MAX];
char findyourself_path_separator='/';
char findyourself_path_separator_as_string[2]="/";
char findyourself_path_list_separator[8]=":"; // could be ":; "
char findyourself_debug=0;
int findyourself_initialized=0;
void findyourself_init(char *argv0)
{
getcwd(findyourself_save_pwd, sizeof(findyourself_save_pwd));
strncpy(findyourself_save_argv0, argv0, sizeof(findyourself_save_argv0));
findyourself_save_argv0[sizeof(findyourself_save_argv0)-1]=0;
strncpy(findyourself_save_path, getenv("PATH"), sizeof(findyourself_save_path));
findyourself_save_path[sizeof(findyourself_save_path)-1]=0;
findyourself_initialized=1;
}
int find_yourself(char *result, size_t size_of_result)
{
char newpath[PATH_MAX+256];
char newpath2[PATH_MAX+256];
assert(findyourself_initialized);
result[0]=0;
if(findyourself_save_argv0[0]==findyourself_path_separator) {
if(findyourself_debug) printf(" absolute path\n");
realpath(findyourself_save_argv0, newpath);
if(findyourself_debug) printf(" newpath=\"%s\"\n", newpath);
if(!access(newpath, F_OK)) {
strncpy(result, newpath, size_of_result);
result[size_of_result-1]=0;
return(0);
} else {
perror("access failed 1");
}
} else if( strchr(findyourself_save_argv0, findyourself_path_separator )) {
if(findyourself_debug) printf(" relative path to pwd\n");
strncpy(newpath2, findyourself_save_pwd, sizeof(newpath2));
newpath2[sizeof(newpath2)-1]=0;
strncat(newpath2, findyourself_path_separator_as_string, sizeof(newpath2));
newpath2[sizeof(newpath2)-1]=0;
strncat(newpath2, findyourself_save_argv0, sizeof(newpath2));
newpath2[sizeof(newpath2)-1]=0;
realpath(newpath2, newpath);
if(findyourself_debug) printf(" newpath=\"%s\"\n", newpath);
if(!access(newpath, F_OK)) {
strncpy(result, newpath, size_of_result);
result[size_of_result-1]=0;
return(0);
} else {
perror("access failed 2");
}
} else {
if(findyourself_debug) printf(" searching $PATH\n");
char *saveptr;
char *pathitem;
for(pathitem=strtok_r(findyourself_save_path, findyourself_path_list_separator, &saveptr); pathitem; pathitem=strtok_r(NULL, findyourself_path_list_separator, &saveptr) ) {
if(findyourself_debug>=2) printf("pathitem=\"%s\"\n", pathitem);
strncpy(newpath2, pathitem, sizeof(newpath2));
newpath2[sizeof(newpath2)-1]=0;
strncat(newpath2, findyourself_path_separator_as_string, sizeof(newpath2));
newpath2[sizeof(newpath2)-1]=0;
strncat(newpath2, findyourself_save_argv0, sizeof(newpath2));
newpath2[sizeof(newpath2)-1]=0;
realpath(newpath2, newpath);
if(findyourself_debug) printf(" newpath=\"%s\"\n", newpath);
if(!access(newpath, F_OK)) {
strncpy(result, newpath, size_of_result);
result[size_of_result-1]=0;
return(0);
}
} // end for
perror("access failed 3");
} // end else
// if we get here, we have tried all three methods on argv[0] and still haven't succeeded. Include fallback methods here.
return(1);
}
main(int argc, char **argv)
{
findyourself_init(argv[0]);
char newpath[PATH_MAX];
printf(" argv[0]=\"%s\"\n", argv[0]);
realpath(argv[0], newpath);
if(strcmp(argv[0],newpath)) { printf(" realpath=\"%s\"\n", newpath); }
find_yourself(newpath, sizeof(newpath));
if(1 || strcmp(argv[0],newpath)) { printf(" findyourself=\"%s\"\n", newpath); }
sleep(1); /* in case run from desktop */
}
और यहां आउटपुट है जो दर्शाता है कि पिछले परीक्षणों में से प्रत्येक में यह वास्तव में खुद को पाया था।
tcc -o ~/bin/echoargc ~/src/echoargc.c
cd ~
/home/whitis/bin/echoargc
argv[0]="/home/whitis/bin/echoargc"
findyourself="/home/whitis/bin/echoargc"
echoargc
argv[0]="echoargc"
realpath="/home/whitis/echoargc"
findyourself="/home/whitis/bin/echoargc"
bin/echoargc
argv[0]="bin/echoargc"
realpath="/home/whitis/bin/echoargc"
findyourself="/home/whitis/bin/echoargc"
bin//echoargc
argv[0]="bin//echoargc"
realpath="/home/whitis/bin/echoargc"
findyourself="/home/whitis/bin/echoargc"
bin/./echoargc
argv[0]="bin/./echoargc"
realpath="/home/whitis/bin/echoargc"
findyourself="/home/whitis/bin/echoargc"
src/../bin/echoargc
argv[0]="src/../bin/echoargc"
realpath="/home/whitis/bin/echoargc"
findyourself="/home/whitis/bin/echoargc"
cd ~/bin
*echo*
argv[0]="echoargc"
realpath="/home/whitis/bin/echoargc"
findyourself="/home/whitis/bin/echoargc"
e?hoargc
argv[0]="echoargc"
realpath="/home/whitis/bin/echoargc"
findyourself="/home/whitis/bin/echoargc"
./echoargc
argv[0]="./echoargc"
realpath="/home/whitis/bin/echoargc"
findyourself="/home/whitis/bin/echoargc"
cd ~/src
../bin/echoargc
argv[0]="../bin/echoargc"
realpath="/home/whitis/bin/echoargc"
findyourself="/home/whitis/bin/echoargc"
cd ~/junk
~/bin/echoargc
argv[0]="/home/whitis/bin/echoargc"
findyourself="/home/whitis/bin/echoargc"
~whitis/bin/echoargc
argv[0]="/home/whitis/bin/echoargc"
findyourself="/home/whitis/bin/echoargc"
alias echoit=~/bin/echoargc
echoit
argv[0]="/home/whitis/bin/echoargc"
findyourself="/home/whitis/bin/echoargc"
echoarg=~/bin/echoargc
$echoarg
argv[0]="/home/whitis/bin/echoargc"
findyourself="/home/whitis/bin/echoargc"
rm junk1 junk2 junk3
ln -s ~/bin/echoargc junk1
./junk1
argv[0]="./junk1"
realpath="/home/whitis/bin/echoargc"
findyourself="/home/whitis/bin/echoargc"
ln -s /home/whitis/bin/echoargc junk2
./junk2
argv[0]="./junk2"
realpath="/home/whitis/bin/echoargc"
findyourself="/home/whitis/bin/echoargc"
ln -s junk1 junk3
./junk3
argv[0]="./junk3"
realpath="/home/whitis/bin/echoargc"
findyourself="/home/whitis/bin/echoargc"
ऊपर वर्णित दो जीयूआई लॉन्च भी प्रोग्राम को सही ढंग से ढूंढते हैं।
एक संभावित नुकसान है। access()
समारोह अनुमतियाँ चला जाता है, तो कार्यक्रम परीक्षण से पहले setuid है। यदि ऐसी स्थिति है जहां कार्यक्रम को एक उन्नत उपयोगकर्ता के रूप में पाया जा सकता है, लेकिन एक नियमित उपयोगकर्ता के रूप में नहीं, तो ऐसी स्थिति हो सकती है जहां ये परीक्षण विफल होंगे, हालांकि यह संभावना नहीं है कि कार्यक्रम वास्तव में उन परिस्थितियों में निष्पादित किया जा सकता है। इसके बजाय यूरोपिडास () का उपयोग किया जा सकता है। हालाँकि, यह संभव है कि यह वास्तविक उपयोगकर्ता की तुलना में पहले पथ पर एक दुर्गम कार्यक्रम पा सकता है।