您将一个字符作为命令名称传递,并将名称字符串作为参数列表的开头传递 – 就好像execv()的原型是int execv(char cmd,char * args).
实际的原型是:int execv(char * cmd,char ** args),所以你需要:
char *args[2] = { fileName, 0 };
execv(args[0], args);
我假设您将fileName设置为某个有意义的值 – 未显示.例如,它可能是“./local_program”.它将被视为可执行文件的路径名.
如果要读取名称,则可以使用fgets()或getline(),但是您需要删除换行符:
if (fgets(fileName, sizeof(fileName), stdin) != 0)
{
fileName[strcspn(fileName, "\n")] = '\0';
…as before…
}
要么:
char *fileName = 0;
size_t length = 0;
if (getline(&fileName, &length, stdin) != -1) /* Not EOF! */
{
fileName[strcspn(fileName, "\n")] = '\0';
…as before…
}
free(fileName);
strcspn()的使用避免了特殊情况下过长的命令行,因此fileName中没有换行符.请注意,这不会尝试将输入行拆分为命令名和空格中的参数或类似的任何东西.这是shell实现的下一个级别:
#include
#include
#include
#include
int main(void)
{
char fileName[256];
if (fgets(fileName, sizeof(fileName), stdin) != 0)
{
fileName[strcspn(fileName, "\n")] = '\0';
char *args[129];
char **argv = args;
char *cmd = fileName;
const char *whisp = " \t\f\r\b\n";
/* Ugh — strtok()? OK while only handling white space separators */
char *token;
while ((token = strtok(cmd, whisp)) != 0)
{
*argv++ = token;
cmd = 0;
}
*argv = 0;
execv(args[0], args);
fprintf(stderr, "Oops!\n");
}
return 1;
}
我不需要检查args数组的溢出,因为输入的256个字符减去终止null,不能被分割以产生超过128个单字符参数,每个参数与相邻的一个空格字符分开.使用strtok()是一个临时的创可贴.一旦你需要处理真正的shell语法(管道,I / O重定向,引用带空格的字符串等),strtok()就是错误的工具. (它 – strtok() – 也是在任何库函数中使用的错误函数.如果必须在库代码中使用类似strtok()的函数,请在Unix上使用POSIX strtok_r()或在Windows上使用Microsoft的strtok_s().)