尝试在 C 中使用 execvp() 并在 unix 中使用用户输入
我正在尝试制作一个程序,提示用户输入命令,然后使用 exec 执行该命令。
例如,如果他们给我“ls -la”,我就必须执行该命令。我已经尝试过以下代码:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main()
{
int ret, num_args;
printf("Enter number of arguments (Example: \"ls -la\" has 1 argument): ");
scanf("%d", &num_args);
char *cmd[num_args];
printf("Enter command name: ");
scanf("%s", &cmd[0]);
int i;
for (i = 0; i < num_args; i++)
{
printf("Enter parameter: ");
scanf("%s", &cmd[i]);
}
execvp(cmd[0], cmd);
}
但是,当我尝试以下运行时,它给了我一个“分段错误”
$ ./a.out
Enter number of arguments (Example: "ls -la" has 1 argument): 2
Enter command name: ls
Enter parameter: -la
Enter parameter: .
Segmentation fault
$
有什么想法吗?
I'm trying to make a program that will prompt the user for a command, then use exec to execute that command.
For instance if they gave me "ls -la" I would have to execute that command. I've tried the following code:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main()
{
int ret, num_args;
printf("Enter number of arguments (Example: \"ls -la\" has 1 argument): ");
scanf("%d", &num_args);
char *cmd[num_args];
printf("Enter command name: ");
scanf("%s", &cmd[0]);
int i;
for (i = 0; i < num_args; i++)
{
printf("Enter parameter: ");
scanf("%s", &cmd[i]);
}
execvp(cmd[0], cmd);
}
However, when I tried the following run it gave me a "segmentation fault"
$ ./a.out
Enter number of arguments (Example: "ls -la" has 1 argument): 2
Enter command name: ls
Enter parameter: -la
Enter parameter: .
Segmentation fault
$
Any ideas?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
如果您的实现支持它,您应该使用更安全的
getline()
而不是scanf()
或fgets()
。getline()
将安全地处理长行和 NULL 字符。它将分配足够的内存来容纳整行。getline()
可以分配内存,因此您稍后必须自己释放它。这是 glibc
getline()文档
。
这是使用 getline 的快速修改(它仍然需要工作、错误检查,我还没有完全检查它的正确性):
If your implementation supports it you should use the safer
getline()
instead onscanf()
orfgets()
.getline()
will safely handle long lines and NULL characters. It will allocate enough memory to fit the entire line.getline()
can allocate memory so you will have to free it yourself later on.Here is the glibc
getline()
documentation.Here is a quick modification to use getline (It still needs work, error checking and I haven't fully checked it for correctness yet):
您需要为字符串分配内存。以下行仅分配
num_args
值指向char
的指针:首先,您将获得
num_args + 1
字符串(不要忘记命令本身是cmd[0]
)。最简单的方法是将内存静态分配为字符缓冲区数组:但是,现在您不能使用
scanf
读取一行,因为用户可以输入比字符缓冲区长的字符串。相反,您必须使用fgets
,它可以限制用户可以输入的字符数:请记住,
fgets
还会读取换行符,因此请确保剥去所有出现的杂散的东西(但不要假设它们在那里)。You need to allocate memory for your strings. The following line only allocates
num_args
worth of pointers tochar
:First of all, you'll be getting
num_args + 1
strings (don't forget that the command itself iscmd[0]
). The easiest way is to statically allocate the memory as an array of character buffers:However, now you can't use
scanf
to read in a line because the user could input a string that's longer than your character buffer. Instead, you'll have to usefgets
, which can limit the number of characters the user can input:Keep in mind that
fgets
also reads newline characters, so make sure to strip any stray ones that show up (but don't assume that they're there).此外,您还需要在传递给
execvp
的argv
中添加一个条目,该条目必须为(char *)NULL
以让它知道它已到达列表末尾。Also, you need one more entry in the
argv
you pass toexecvp
, which has to be(char *)NULL
to let it know that it's reached the end of the list.您实际上尚未为 cmd 数组指向的字符串分配任何内存。
You haven't actually allocated any memory for the strings pointed to by the cmd array.
查看 scanf() 的手册页。它可以做的最巧妙的事情之一是动态自动分配字符串缓冲区,您需要提供一个指向字符串的指针,而不是仅仅传递字符串并提供 %as 格式。
然后你就不需要费心去预分配,不需要费心缓冲区溢出等等。只要记住在使用完它之后 free() 它即可。
Take a look at the man page for scanf(). One of the neatest things it can do is automatically allocate the string buffers on the fly, you need to supply a pointer to a string instead of just passing the string and supply the %as format.
Then you don't need to bother with preallocating, don't need to bother with buffer overflows, etc. Just remember to free() it after you're done with it.