为什么这两个execvp产生不同的结果?

时间:2019-05-10 03:20:17

标签: c posix

我想知道为什么下面的结果会有所不同:

char *const temp[] = {"cal","4","2019",NULL};


    execvp(temp[0],temp);
    perror("Return from execlp not expected");
    exit(EXIT_FAILURE);

执行时将生成仅包含4月的日历

char *const temp[] = {"cal"};
char *const temp2[] ={"4","2019",NULL};

    execvp(temp[0],temp2);
    perror("Return from execlp not expected");
    exit(EXIT_FAILURE);

执行时将产生一个包含所有月份的日历

我想让第二种形式正常工作,因为我的问题是我有2个数组,一个数组存储我的所有命令,另一个数组存储我的所有命令参数。例如

array1[0] = command
array2[0] = arg1 ar2 arg3  // the arguments for the command in array1[0]

在一个循环中,直到我到达命令数组的末尾为止,使用fork并在子类中执行这些命令,以便我可以遍历并执行数组中的所有命令。

2 个答案:

答案 0 :(得分:2)

按照execvp man

int execvp(const char *file, char *const argv[]);
  

execv(),execvp()和execvpe()函数提供了一个数组   指向代表参数列表的以空值终止的字符串的指针   适用于新程序。 按照惯例,第一个参数   应该指向与正在执行的文件关联的文件名。   指针数组必须以NULL指针终止

答案 1 :(得分:0)

始终假定

argv[0]是程序的名称,即使您的情况下execvp不使用它,也是如此。 cal程序本身开始从argv[1]解释命令行。 (请参阅@kiran Biradar的答案。)

您需要将(指针指向)参数复制到更大的数组中,并为argv[0]设置一个虚拟参数。这是一些简短的代码:

char **combine_args(char *arg0, char **tail) {
    size_t n = 0;
    while(tail[n]) ++n;
    char **ret = malloc(sizeof(char*)*(n+2));
    ret[0] = arg0;
    memcpy(ret + 1, tail, sizeof(char*)*n);
    ret[n+1] = 0;
    return ret;
}

接下来,您可以像这样使用它:

char *const temp[] = {"cal"};
char *const temp2[] ={"4","2019",NULL};

char **argv = combine_args(temp[0], temp2);

execvp(argv[0], argv);
perror("Return from execlp not expected");
exit(EXIT_FAILURE);

如果您循环执行此操作,并且可以更改temp2数组,则可以这样进行,而无需进行任何分配:

char *const temp[] = {"cal", "cal2", "cal3", NULL};
char *temp2[] ={NULL, "4","2019",NULL};

for(int i = 0; temp[i]; ++i)
{
    // ... fork here ...
    {
        temp2[0] = temp[i];
        execvp(temp2[0], temp2);
        perror("Return from execlp not expected");
        exit(EXIT_FAILURE);
    }
}