Việc sử dụng /proc/self/exe
là không di động và không đáng tin cậy. Trên hệ thống Ubuntu 12.04 của tôi, bạn phải root để đọc / theo liên kết tượng trưng. Điều này sẽ làm cho ví dụ Boost và có thể các whereami()
giải pháp được đăng không thành công.
Bài đăng này rất dài nhưng thảo luận về các vấn đề thực tế và trình bày mã thực sự hoạt động cùng với xác nhận đối với bộ kiểm tra.
Cách tốt nhất để tìm chương trình của bạn là truy xuất các bước tương tự mà hệ thống sử dụng. Điều này được thực hiện bằng cách sử dụng argv[0]
giải quyết chống lại root hệ thống tập tin, pwd, môi trường đường dẫn và xem xét các liên kết tượng trưng, và chuẩn hóa tên đường dẫn. Đây là từ bộ nhớ nhưng tôi đã thực hiện điều này trong quá khứ thành công và đã thử nghiệm nó trong nhiều tình huống khác nhau. Nó không được đảm bảo để hoạt động, nhưng nếu nó không có thể bạn có vấn đề lớn hơn nhiều và nó đáng tin cậy hơn bất kỳ phương pháp nào khác được thảo luận. Có một số tình huống trên một hệ thống tương thích Unix trong đó xử lý đúng cáchargv[0]
sẽ không đưa bạn đến chương trình của bạn nhưng sau đó bạn đang thực hiện trong một môi trường bị phá vỡ chắc chắn. Nó cũng khá dễ mang theo cho tất cả các hệ thống có nguồn gốc Unix kể từ khoảng năm 1970 và thậm chí một số hệ thống có nguồn gốc không phải Unix vì về cơ bản nó phụ thuộc vào chức năng tiêu chuẩn libc () và chức năng dòng lệnh tiêu chuẩn. Nó nên hoạt động trên Linux (tất cả các phiên bản), Android, Chrome OS, Minix, Bell Labs Unix, FreeBSD, NetBSD, OpenBSD, BSD xx, SunOS, Solaris, SYSV, HPUX, Concentrix, SCO, Darwin, AIX, OS X, NeXTSTEP, vv Và với một chút thay đổi có lẽ VMS, VM / CMS, hệ điều hành DOS / Windows, ReactOS, OS / 2, vv Nếu một chương trình đã được đưa ra trực tiếp từ một môi trường GUI, nó cần phải có thiết lập argv[0]
một đường dẫn tuyệt đối.
Hiểu rằng hầu hết mọi shell trên mọi hệ điều hành tương thích Unix đã được phát hành về cơ bản đều tìm thấy các chương trình theo cùng một cách và thiết lập môi trường hoạt động gần giống như vậy (với một số tính năng bổ sung tùy chọn). Và bất kỳ chương trình nào khác khởi chạy một chương trình dự kiến sẽ tạo ra cùng một môi trường (argv, chuỗi môi trường, v.v.) cho chương trình đó như thể nó được chạy từ shell, với một số tính năng bổ sung tùy chọn. Một chương trình hoặc người dùng có thể thiết lập một môi trường lệch khỏi quy ước này cho các chương trình cấp dưới khác mà nó khởi chạy nhưng nếu có, đây là một lỗi và chương trình không có kỳ vọng hợp lý rằng chương trình cấp dưới hoặc cấp dưới của nó sẽ hoạt động chính xác.
Các giá trị có thể argv[0]
bao gồm:
/path/to/executable
- đường dẫn tuyệt đối
../bin/executable
- liên quan đến pwd
bin/executable
- liên quan đến pwd
./foo
- liên quan đến pwd
executable
- tên cơ sở, tìm trong đường dẫn
bin//executable
- liên quan đến pwd, không chính tắc
src/../bin/executable
- liên quan đến pwd, không chính tắc, quay lui
bin/./echoargc
- liên quan đến pwd, không chính tắc
Các giá trị bạn không nên thấy:
~/bin/executable
- viết lại trước khi chương trình của bạn chạy.
~user/bin/executable
- viết lại trước khi chương trình của bạn chạy
alias
- viết lại trước khi chương trình của bạn chạy
$shellvariable
- viết lại trước khi chương trình của bạn chạy
*foo*
- ký tự đại diện, viết lại trước khi chương trình của bạn chạy, không hữu ích lắm
?foo?
- ký tự đại diện, viết lại trước khi chương trình của bạn chạy, không hữu ích lắm
Ngoài ra, chúng có thể chứa các tên đường dẫn không chính tắc và nhiều lớp liên kết tượng trưng. Trong một số trường hợp, có thể có nhiều liên kết cứng đến cùng một chương trình. Ví dụ, /bin/ls
, /bin/ps
, /bin/chmod
, /bin/rm
, vv có thể được liên kết cứng đến /bin/busybox
.
Để tìm lại chính mình, hãy làm theo các bước dưới đây:
Lưu pwd, PATH và argv [0] khi vào chương trình của bạn (hoặc khởi tạo thư viện của bạn) vì chúng có thể thay đổi sau này.
Tùy chọn: đặc biệt đối với các hệ thống không phải Unix, tách riêng nhưng không loại bỏ phần tiền tố tên máy chủ / người dùng / ổ đĩa, nếu có; phần thường đi trước dấu hai chấm hoặc theo sau "//" ban đầu.
Nếu argv[0]
là một đường dẫn tuyệt đối, sử dụng nó làm điểm bắt đầu. Một đường dẫn tuyệt đối có thể bắt đầu bằng "/" nhưng trên một số hệ thống không phải là Unix, nó có thể bắt đầu bằng "\" hoặc một ký tự tên hoặc tiền tố tên theo sau là dấu hai chấm.
Khác nếu argv[0]
là một đường dẫn tương đối (chứa "/" hoặc "\" nhưng không bắt đầu với nó, chẳng hạn như "../../bin/foo", sau đó kết hợp pwd + "/" + argv [0] (sử dụng hiện tại thư mục làm việc từ khi chương trình bắt đầu, không hiện tại).
Khác nếu argv [0] là một tên cơ sở đơn giản (không có dấu gạch chéo), sau đó kết hợp nó với từng mục trong biến môi trường PATH lần lượt và thử những cái đó và sử dụng cái đầu tiên thành công.
Tùy chọn: Khác hãy thử chính nền tảng cụ thể /proc/self/exe
, /proc/curproc/file
(BSD) và (char *)getauxval(AT_EXECFN)
, dlgetname(...)
nếu có. Bạn thậm chí có thể thử các argv[0]
phương pháp dựa trên trước này , nếu chúng có sẵn và bạn không gặp phải vấn đề về quyền. Trong trường hợp hơi khó xảy ra (khi bạn xem xét tất cả các phiên bản của tất cả các hệ thống) mà chúng có mặt và không bị lỗi, chúng có thể có thẩm quyền hơn.
Tùy chọn: kiểm tra tên đường dẫn được truyền bằng cách sử dụng tham số dòng lệnh.
Tùy chọn: kiểm tra tên đường dẫn trong môi trường được truyền rõ ràng bằng tập lệnh trình bao bọc của bạn, nếu có.
Tùy chọn: Là giải pháp cuối cùng, hãy thử biến môi trường "_". Nó có thể trỏ đến một chương trình hoàn toàn khác, chẳng hạn như trình bao người dùng.
Giải quyết các liên kết tượng trưng, có thể có nhiều lớp. Có khả năng các vòng lặp vô hạn, mặc dù nếu chúng tồn tại, chương trình của bạn có thể sẽ không được gọi.
Canonicalize tên tệp bằng cách giải quyết các chuỗi con như "/foo/../bar/" thành "/ bar /". Lưu ý điều này có khả năng thay đổi ý nghĩa nếu bạn vượt qua điểm gắn kết mạng, do đó, việc chuẩn hóa không phải lúc nào cũng tốt. Trên máy chủ mạng, ".." trong symlink có thể được sử dụng để đi qua một đường dẫn đến một tệp khác trong ngữ cảnh máy chủ thay vì trên máy khách. Trong trường hợp này, bạn có thể muốn bối cảnh máy khách để chuẩn hóa là ok. Đồng thời chuyển đổi các mẫu như "/./" thành "/" và "//" thành "/". Trong shell, readlink --canonicalize
sẽ giải quyết nhiều liên kết tượng trưng và tên hợp quy. Chase có thể làm tương tự nhưng không được cài đặt. realpath()
hoặc canonicalize_file_name()
, nếu có, có thể giúp đỡ.
Nếu realpath()
không tồn tại vào thời gian biên dịch, bạn có thể mượn một bản sao từ bản phân phối thư viện được cấp phép cho phép và tự biên dịch nó thay vì phát minh lại bánh xe. Khắc phục lỗi tràn bộ đệm tiềm năng (chuyển vào bộ đệm đầu ra sizeof, nghĩ rằng strncpy () so với strcpy ()) nếu bạn sẽ sử dụng bộ đệm ít hơn PATH_MAX. Có thể dễ dàng hơn chỉ sử dụng một bản sao riêng được đổi tên thay vì kiểm tra nếu nó tồn tại. Bản quyền giấy phép cho phép từ android / darwin / bsd: https://android.googlesource.com/pl platform / bionic / + / f077784 / libc / upstream-freebsd / lib / libc / stdlib / realpath.c
Xin lưu ý rằng nhiều lần thử có thể thành công hoặc thành công một phần và chúng có thể không chỉ ra cùng một thực thi, vì vậy hãy xem xét việc xác minh thực thi của bạn; tuy nhiên, bạn có thể không có quyền đọc - nếu bạn không thể đọc nó, đừng coi đó là một thất bại. Hoặc xác minh một cái gì đó gần với thực thi của bạn, chẳng hạn như thư mục "../lib/" mà bạn đang cố gắng tìm. Bạn có thể có nhiều phiên bản, phiên bản được đóng gói và biên dịch cục bộ, phiên bản cục bộ và mạng và phiên bản di động ổ đĩa cục bộ và USB, v.v. và có một khả năng nhỏ là bạn có thể nhận được hai kết quả không tương thích từ các phương pháp định vị khác nhau. Và "_" có thể chỉ đơn giản là trỏ đến chương trình sai.
Một chương trình sử dụng execve
có thể cố tình đặt argv[0]
không tương thích với đường dẫn thực tế được sử dụng để tải chương trình và PATH bị hỏng, "_", pwd, v.v. mặc dù nhìn chung không có nhiều lý do để làm như vậy; nhưng điều này có thể có ý nghĩa bảo mật nếu bạn có mã dễ bị bỏ qua thực tế là môi trường thực thi của bạn có thể được thay đổi theo nhiều cách bao gồm, nhưng không giới hạn, đối với cách này (chroot, hệ thống tập tin cầu chì, liên kết cứng, v.v.) cho các lệnh shell để đặt PATH nhưng không xuất được nó.
Bạn không nhất thiết phải mã hóa cho các hệ thống không phải Unix nhưng sẽ là một ý tưởng tốt để nhận biết một số đặc thù để bạn có thể viết mã theo cách mà không khó để ai đó chuyển sang sau này . Xin lưu ý rằng một số hệ thống (DEC VMS, DOS, URL, v.v.) có thể có tên ổ đĩa hoặc các tiền tố khác kết thúc bằng dấu hai chấm như "C: \", "sys $ drive: [foo] bar" và "file : /// foo / bar / baz ". Các hệ thống DEC VMS cũ sử dụng "[" và "]" để đặt phần thư mục của đường dẫn mặc dù điều này có thể đã thay đổi nếu chương trình của bạn được biên dịch trong môi trường POSIX. Một số hệ thống, chẳng hạn như VMS, có thể có phiên bản tệp (được phân tách bằng dấu chấm phẩy ở cuối). Một số hệ thống sử dụng hai dấu gạch chéo liên tiếp như trong "// drive / path / to / file" hoặc "user @ host: / path / to / file" (lệnh scp) hoặc "file: (được phân cách bằng dấu cách) và "PATH" được phân cách bằng dấu hai chấm nhưng chương trình của bạn sẽ nhận được PATH vì vậy bạn không cần phải lo lắng về đường dẫn. DOS và một số hệ thống khác có thể có các đường dẫn tương đối bắt đầu bằng tiền tố ổ đĩa. C: foo.exe đề cập đến foo.exe trong thư mục hiện tại trên ổ C, vì vậy bạn cần phải tra cứu thư mục hiện tại trên C: và sử dụng nó cho pwd. (được phân cách bằng dấu cách) và "PATH" được phân cách bằng dấu hai chấm nhưng chương trình của bạn sẽ nhận được PATH vì vậy bạn không cần phải lo lắng về đường dẫn. DOS và một số hệ thống khác có thể có các đường dẫn tương đối bắt đầu bằng tiền tố ổ đĩa. C: foo.exe đề cập đến foo.exe trong thư mục hiện tại trên ổ C, vì vậy bạn cần phải tra cứu thư mục hiện tại trên C: và sử dụng nó cho pwd.
Một ví dụ về liên kết tượng trưng và trình bao bọc trên hệ thống của tôi:
/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
Lưu ý rằng hóa đơn người dùng đã đăng một liên kết ở trên lên một chương trình tại HP xử lý ba trường hợp cơ bản argv[0]
. Nó cần một số thay đổi, mặc dù:
- Nó sẽ là cần thiết để viết lại tất cả
strcat()
và strcpy()
để sử dụng strncat()
và strncpy()
. Mặc dù các biến được khai báo có độ dài PATHMAX, giá trị đầu vào có độ dài PATHMAX-1 cộng với độ dài của chuỗi được nối là> PATHMAX và giá trị đầu vào của độ dài PATHMAX sẽ bị hủy bỏ.
- Nó cần phải được viết lại như một chức năng của thư viện, thay vì chỉ in ra kết quả.
- Nó không hợp lệ hóa tên (sử dụng mã realpath mà tôi đã liên kết ở trên)
- Không thể giải quyết các liên kết tượng trưng (sử dụng mã realpath)
Vì vậy, nếu bạn kết hợp cả mã HP và mã realpath và sửa cả hai để có khả năng chống tràn bộ đệm, thì bạn nên có một cái gì đó có thể diễn giải đúng argv[0]
.
Phần sau đây minh họa các giá trị thực tế argv[0]
cho nhiều cách gọi cùng một chương trình trên Ubuntu 12.04. Và vâng, chương trình đã vô tình được đặt tên là echoargc thay vì echoargv. Điều này đã được thực hiện bằng cách sử dụng tập lệnh để sao chép sạch nhưng thực hiện thủ công trong shell sẽ có kết quả tương tự (ngoại trừ bí danh không hoạt động trong tập lệnh trừ khi bạn bật chúng một cách rõ ràng).
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
Những ví dụ này minh họa rằng các kỹ thuật được mô tả trong bài viết này sẽ hoạt động trong một loạt các trường hợp và tại sao một số bước là cần thiết.
EDIT: Bây giờ, chương trình in argv [0] đã được cập nhật để thực sự tìm thấy chính nó.
// 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 */
}
Và đây là đầu ra chứng minh rằng trong mỗi một thử nghiệm trước đó, nó thực sự đã tìm thấy chính nó.
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"
Hai khởi chạy GUI được mô tả ở trên cũng tìm thấy chính xác chương trình.
Có một cạm bẫy tiềm năng. Các access()
chức năng giảm quyền nếu chương trình được setuid trước khi thử nghiệm. Nếu có một tình huống mà chương trình có thể được tìm thấy như một người dùng nâng cao nhưng không phải là một người dùng thông thường, thì có thể có một tình huống mà các thử nghiệm này sẽ thất bại, mặc dù không chắc chương trình có thể được thực thi trong những trường hợp đó. Người ta có thể sử dụng euidaccess () thay thế. Tuy nhiên, có thể nó có thể tìm thấy một chương trình không thể truy cập sớm hơn trên đường dẫn so với người dùng thực tế có thể.