main()
কোনও সি বা সি ++ অ্যাপ্লিকেশনে আর্গুমেন্ট পাস করার সময় , argv[0]
সর্বদা মৃত্যুদন্ড কার্যকর করার নাম থাকবে? বা এটি কি কেবল একটি সাধারণ সম্মেলন এবং সময়টির 100% সত্য হওয়ার নিশ্চয়তা নেই?
main()
কোনও সি বা সি ++ অ্যাপ্লিকেশনে আর্গুমেন্ট পাস করার সময় , argv[0]
সর্বদা মৃত্যুদন্ড কার্যকর করার নাম থাকবে? বা এটি কি কেবল একটি সাধারণ সম্মেলন এবং সময়টির 100% সত্য হওয়ার নিশ্চয়তা নেই?
উত্তর:
অনুমান করা (এমনকি শিক্ষিত অনুমানক) মজাদার তবে নিশ্চিত হওয়ার জন্য আপনার অবশ্যই স্ট্যান্ডার্ড ডকুমেন্টগুলিতে যেতে হবে। উদাহরণস্বরূপ, আইএসও সি 11 বলেছেন (আমার জোর):
মানটি যদি
argc
শূন্যের চেয়ে বেশি হয় তবে নির্দেশিত স্ট্রিং প্রোগ্রামটির নামargv[0]
উপস্থাপন করে;argv[0][0]
হোস্ট পরিবেশ থেকে প্রোগ্রামের নামটি উপলব্ধ না হলে নাল অক্ষর হবে shall
সুতরাং না, এটির নামটি উপলব্ধ থাকলে এটি কেবল প্রোগ্রামের নাম । এবং এটা "প্রতিনিধিত্ব করে" প্রোগ্রাম নাম, কোনো অগত্যা হয় প্রোগ্রাম নাম। তার আগের বিভাগটি বলে:
মানটি যদি
argc
শূন্যের চেয়ে বেশিargv[0]
হয় তবেargv[argc-1]
অন্তর্ভুক্তির মাধ্যমে অ্যারে সদস্যগুলিতে স্ট্রিংয়ের পয়েন্টার থাকতে হবে, যা প্রোগ্রাম শুরু হওয়ার আগে হোস্ট পরিবেশ দ্বারা বাস্তবায়ন-সংজ্ঞায়িত মান দেওয়া হয়।
এটি পূর্ববর্তী মান, সি 99 থেকে অপরিবর্তিত এবং এর অর্থ এটি এমনকি মানগুলি মান দ্বারা নির্ধারিত হয় না - এটি সম্পূর্ণরূপে বাস্তবায়নের উপর নির্ভর করে।
এই উপায়ে প্রোগ্রাম নাম যদি হোস্ট পরিবেশ খালি হতে পারে না এটি প্রদান, এবং অন্য কিছু যদি হোস্ট পরিবেশ নেই প্রদান করা যে, "অন্য কিছু" একরকম প্রোগ্রাম নাম প্রতিনিধিত্ব করে, এটা প্রদান। আমার আরও দুঃখজনক মুহুর্তগুলিতে, আমি এটি সোয়াহিলি ভাষায় অনুবাদ করার বিষয়টি বিবেচনা করব এবং এটি একটি বিকল্প সাইফারের মাধ্যমে চালিয়ে তারপরে বিপরীত বাইট ক্রমে সংরক্ষণ করব :-)।
যাইহোক, বাস্তবায়ন-সংজ্ঞায়িত করে বাস্তবায়ন আবশ্যক ডকুমেন্ট কিভাবে এটি কাজ করে - আইএসও মান একটি নির্দিষ্ট অর্থ আছে। এমনকি ইউনিক্স, যা কলগুলির পরিবারের argv[0]
সাথে এটি পছন্দ করে এমন কোনও জিনিস রাখতে exec
পারে, এটি এটিকে নথিভুক্ত করতে (এবং করবে) করতে হবে।
argv[0]
বাস্তব বিশ্বের প্রোগ্রামিংয়ের জন্য অ্যাপ্রোপোস os
কল *nix
সহ টাইপ সিস্টেমের অধীনে exec*()
, argv[0]
কলারের মধ্যে স্পটটিতে যা কিছু argv0
স্থাপন করা হবেexec*()
কল।
শেলটি কনভেনশনটি ব্যবহার করে যে এটি প্রোগ্রামের নাম এবং অন্যান্য বেশিরভাগ প্রোগ্রাম একই কনভেনশন অনুসরণ করে argv[0]
সাধারণত প্রোগ্রামটির নাম।
তবে একটি দুর্বৃত্ত ইউনিক্স প্রোগ্রাম কল করতে exec()
এবং argv[0]
এটির পছন্দমতো যে কোনও কিছু তৈরি করতে পারে, তাই সি স্ট্যান্ডার্ড যাই বলুক না কেন, আপনি এই 100% সময়ের উপর নির্ভর করতে পারবেন না।
সি ++ স্ট্যান্ডার্ড অনুসারে বিভাগ ৩.6.১:
আরজিভি [0] হ'ল এনটিএমবিএসের প্রাথমিক চরিত্রের নির্দেশক হবে যা প্রোগ্রামটি বা প্রার্থনার জন্য ব্যবহৃত নামটি উপস্থাপন করে ""
সুতরাং না, এটি নিশ্চিত নয়, কমপক্ষে মানক দ্বারা।
আইএসও-আইইসি 9899 বলেছেন:
5.1.2.2.1 প্রোগ্রাম সূচনা
মানটির মান
argc
শূন্যের চেয়ে বেশি হলে, নির্দেশিত স্ট্রিংargv[0]
প্রোগ্রামটির নাম উপস্থাপন করে;argv[0][0]
হোস্ট পরিবেশ থেকে প্রোগ্রামের নামটি উপলব্ধ না হলে নাল অক্ষর হবে shall তাহলে এর মান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
সিমিলিংকটি সোলারিস 10 এবং তার বেশি ব্যবহারের জন্য কার্যকর হতে পারে।
GetModuleFileNameW
কোনও পথ পুনরুদ্ধার করতে সক্ষম হওয়া উচিত, তবে কোডের উপস্থিতিই সঠিক দিকনির্দেশনা গঠন করে)।
argv[0] !=
এক্সিকিউটেবল নাম থাকার অ্যাপ্লিকেশন
অনেকগুলি শেল চেক করে লগইন শেল কিনা তা নির্ধারণ করে argv[0][0] == '-'
। লগইন শেলগুলির বিভিন্ন বৈশিষ্ট্য রয়েছে, উল্লেখযোগ্যভাবে তারা কিছু ডিফল্ট ফাইল যেমন উত্স করে /etc/profile
।
এটি সাধারণত ডিআইডি নিজেই থাকে বা getty
এটি নেতৃস্থানীয় যোগ করে -
, এগুলিও দেখুন: /unix/299408/how-to-login-automatic-without-typing-the-root-username-or-password -ইন-বিল্ড / 300152 # 300152
মাল্টি-কল বাইনারিগুলি, সম্ভবত সর্বাধিক উল্লেখযোগ্য ব্যস্তবক্স । এই সিমিলিংক একাধিক নাম যেমন /bin/sh
and /bin/ls
এবং একক বেনিফিটযোগ্য /bin/busybox
, যা কোন সরঞ্জামটি ব্যবহার করতে হবে তা স্বীকার করে argv[0]
।
এটি একক ছোট স্ট্যাটিকালি লিঙ্কযুক্ত এক্সিকিউটেবল যা একাধিক সরঞ্জামকে উপস্থাপন করে এবং এটি মূলত যে কোনও লিনাক্স পরিবেশে কাজ করবে makes
আরও দেখুন: /unix/315812/why-does-argv-incolve-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 এ পরীক্ষা করা হয়েছে।
এই পৃষ্ঠাতে বলা হয়েছে:
আরগভি [0] উপাদানটি সাধারণত প্রোগ্রামটির নাম ধারণ করে তবে এটির উপর নির্ভর করা উচিত নয় - যাইহোক কোনও প্রোগ্রামের নিজের নাম না জানা এটি অস্বাভাবিক!
যাইহোক, অন্যান্য পৃষ্ঠাগুলি এটি সত্যই কার্যকর করার নাম হিসাবে ব্যাক আপ করে। এই এক বলে:
আপনি দেখতে পাবেন যে আরগভি [0] হ'ল প্রোগ্রামেরই পথ এবং নাম। এটি প্রোগ্রামটিকে নিজের সম্পর্কে তথ্য আবিষ্কার করতে দেয়। এটি প্রোগ্রাম আর্গুমেন্টের অ্যারেতে আরও একটি যোগ করে, সুতরাং কমান্ড-লাইন আর্গুমেন্টগুলি আনার সময় একটি সাধারণ ত্রুটি হ'ল আপনি যখন আরগভি [1] চান তখন আরগভি [0] কে দখল করতে হয়।
argv[0]="-/bin/sh"
? আমি যে সমস্ত মেশিন ব্যবহার করেছি, সে ক্ষেত্রে এটিই ঘটেছে।
এটি প্রায় সর্বজনীন সম্মেলন বা মানক কিনা তা আমি নিশ্চিত নই, তবে যেভাবেই আপনি এটি মেনে চলা উচিত। যদিও আমি ইউনিক্স এবং ইউনিক্সের মতো সিস্টেমগুলির বাইরে এটি কখনও দেখেনি। ইউনিক্স পরিবেশে - এবং সম্ভবত বিশেষত পুরানো দিনগুলিতে - প্রোগ্রামগুলির নাম অনুসারে যেগুলি চাওয়া হয়েছে তার উপর নির্ভর করে উল্লেখযোগ্যভাবে বিভিন্ন আচরণ থাকতে পারে।
সম্পাদনা: আমি অন্য পোস্টগুলি থেকে আমার হিসাবে একই সাথে দেখছি যে কেউ এটি নির্দিষ্ট মানের থেকে আগত বলে চিহ্নিত করেছে, তবে আমি নিশ্চিত যে কনভেনশনটি দীর্ঘকাল মানটির পূর্বে রয়েছে।
execl("/home/hacker/.hidden/malicious", "/bin/ls", "-s", (char *)0);
। এক্সিকিউটেবলের নামের মানটির সাথে কোনও সম্পর্ক নেইargv[0]
।