[英]Implementing a Unix shell in C: check if file is executable
I am working on implementing a Unix shell in C and I'm currently dealing with the problem of relative paths. 我正在用C实现一个Unix shell,我正在处理相对路径的问题。 Notably while inputting commands.
特别是在输入命令时。 For now I have to enter the full path of the executable every time, when I would much rather simply put "ls" or "cat".
现在我每次都必须输入可执行文件的完整路径,而我更愿意简单地输入“ls”或“cat”。
I have managed to get the $PATH env variable. 我设法获得$ PATH env变量。 My idea is to split the variable at the ":" character, then append each new string to the command name and check if the file exists and is executable.
我的想法是将变量拆分为“:”字符,然后将每个新字符串附加到命令名称并检查文件是否存在且是否可执行。
For example if my PATH is: "/bin:/usr/bin" and I input "ls", I would like the program to check first if "/bin/ls" exists and is executable, if not move on to "/usr/bin/". 例如,如果我的PATH是:“/ bin:/ usr / bin”并且我输入“ls”,我希望程序首先检查“/ bin / ls”是否存在且是否可执行,如果没有继续“/ USR /斌/”。
Two questions: 两个问题:
1) Is it a good way to do it? 1)这是一个好方法吗? (Doesn't it have to be necessarily the best. I just want to make sure that it would work.
(它不一定是最好的。我只是想确保它会起作用。
2) More importantly, How can I check in C, if a file exists and is executable? 2)更重要的是,如果文件存在且可执行,我如何检入C?
I hope I'm clear enough, and ... well thanks :) 我希望我足够清楚,并且......非常感谢:)
Don't. 别。 Performing this check is wrong;
执行此检查是错误的; it's inherently subject to a race condition.
它固有地受到竞争条件的影响。 Instead, try executing it with the appropriate
exec
-family call. 相反, 尝试使用适当的
exec
-family调用执行它。 If it's not executable, you'll get an error. 如果它不可执行,您将收到错误。
Also note that you don't need to search the PATH
yourself; 另请注意,您不需要自己搜索
PATH
; execvp
can do this for you. execvp
可以为你做到这一点。
stat
? stat
? Psh. PSH。 Way more than you need.
超出你需要的方式。
Check out the access()
syscall. 查看
access()
系统调用。
if (access(filename, F_OK|X_OK) == 0)
{
/* You can execute this file. */
}
Note that any check for file access or existence of a file has an inherent race condition in it.
请注意,对文件访问或文件存在的任何检查都有固有的竞争条件 。 You can't guarantee at your call to
execve
that someone didn't remove the executable bit, change the ownership of the file, delete the file, etc., in the time since your check happened. 你不能在你的电话保证
execve
有人没有删除可执行位,更改文件的所有权,删除文件等,在时间,因为你的支票发生。 Keep this in mind when you write your code and decide how to handle error conditions. 编写代码并决定如何处理错误条件时,请记住这一点。
Use the stat
function: http://linux.die.net/man/2/stat 使用
stat
函数: http : //linux.die.net/man/2/stat
eg: 例如:
struct stat sb;
if(!stat(path, &sb))
{
if(IS_REG(sb.st_mode) && sb.st_mode & 0111)
printf("%s is executable\n", path);
}
Call stat
on the full pathname, and if it returns 0 (success), the target exists. 在完整路径名上调用
stat
,如果它返回0(成功),则目标存在。 In that case you can use the st_mode
field in the returned structure to test whether the target is a directory, device, named pipe, or ordinary file. 在这种情况下,您可以使用返回结构中的
st_mode
字段来测试目标是目录,设备,命名管道还是普通文件。 If it's a file, st_mode
will also contain the permission bits. 如果是文件,
st_mode
也将包含权限位。 (If it's a directory, some "executable" bits might be set, but that would imply "searchable" rather than "executable".) (如果它是一个目录,可能会设置一些“可执行”位,但这意味着“可搜索”而不是“可执行”。)
Edit: As others have noted, this is subject to a race condition, and there are better ways of accomplishing what you want to do in this particular situation. 编辑:正如其他人所说,这是一个竞争条件,并有更好的方法来完成你在这种特殊情况下想做的事情。
The access()
answer is the only sensible one. access()
答案是唯一明智的答案。 If you use stat, you'll have to parse /etc/group to find out all the groups you are in BESIDE
getgid()
and test them together with the group-executable bit. 如果使用stat,则必须解析/ etc / group以找出您在
BESIDE
getgid()
所有组, BESIDE
它们与组可执行位一起进行测试。
How are you creating the process?? 你是如何创建这个过程的?
Use execlp or execvp. 使用execlp或execvp。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.