[英]Trying to use execvp() in C with user input in 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
$
有任何想法嗎?
您需要為字符串分配內存。 以下行僅分配了num_args
char
指針:
char *cmd[num_args];
首先,您將獲得num_args + 1
字符串(不要忘記命令本身是cmd[0]
)。 最簡單的方法是將內存靜態分配為字符緩沖區數組:
const unsigned int MAX_LEN = 512; // Arbitrary number
char cmd[num_args + 1][MAX_LEN];
但是,現在您不能使用scanf
讀取行,因為用戶可以輸入比字符緩沖區長的字符串。 相反,您必須使用fgets
,它可以限制用戶可以輸入的字符數:
fgets(cmd[i], MAX_LEN, stdin);
請記住, fgets
還會讀取換行符,因此請確保刪除出現的所有雜散字符(但不要假定它們在那里)。
如果您的實現支持它,則應該在scanf()
或fgets()
上使用更安全的getline()
fgets()
。 getline()
將安全地處理長行和NULL字符。 它將分配足夠的內存以適合整行。 getline()
可以分配內存,因此稍后您必須自己釋放內存。
這是使用getline的快速修改方法(它仍然需要工作,進行錯誤檢查,並且我還沒有完全檢查它的正確性):
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main()
{
printf("Enter number of arguments (Example: \"ls -la\" has 1 argument): \n");
char *num = NULL;
size_t sz = 0;
getline(&num, &sz, stdin);
int num_args;
sscanf(num, "%d", &num_args);
char *cmd[num_args+2];
memset(cmd, 0, sizeof(char*) * (num_args+2));
printf("Enter command name: \n");
int len = getline(&cmd[0], &sz, stdin);
cmd[0][len-1] = '\0';
int i;
for (i = 1; i < num_args+1; i++)
{
printf("Enter parameter: \n");
sz = 0;
len = getline(&cmd[i], &sz, stdin);
cmd[i][len-1] = '\0';
}
return execvp(cmd[0], cmd);
}
另外,您還需要在傳遞給execvp
的argv
另一個條目,該條目必須為(char *)NULL
才能使其知道已到達列表的末尾。
您實際上並未為cmd數組所指向的字符串分配任何內存。
看一下scanf()的手冊頁。 它可以做的最巧妙的事情之一是自動動態分配字符串緩沖區,您需要提供一個指向字符串的指針,而不是僅僅傳遞字符串並提供%as格式。
char *my_string;
scanf("%as", &my_string);
這樣,您就不必為預分配而煩惱,也不必為緩沖區溢出而煩惱,等等。只需記住在完成操作后將其釋放()即可。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.