简体   繁体   English

在C中实现Unix shell:检查文件是否可执行

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM