在C中,如何复制字符串数组的一部分以用作execve中的argv?

时间:2014-11-26 19:19:52

标签: c arrays string shell

我的代码现在非常混乱,所以我认为通过描述它来传达我想要做的事情会更容易。

我在shell上做家庭作业,需要能够将输出重定向到文件,就像默认的shell一样。我们提供了一个预先存在的shell并要求对其进行修改。 shell已经为execve设置了一个argv,但是为了实现重定向,我需要从程序构建的argv中删除最后两个条目(>和文件名),并在测试之后通过释放最后两个条目我认为最好只制作副本,减去这两个条目,因为这个程序处理释放argv,如果我在预先设定的时间之前尝试这样做,我会遇到问题当我尝试运行另一个命令时。

我的观点是,我很难复制一系列字符串,这些字符串将用作argv。我已经看过几个解决方案,但是他们都是用C ++编写的,我要求用C语言做这个。

或者,我想如果我可以正确清空argv的一部分也就足够了。这是我尝试过的代码:

for(i=0;i<10;i++)
{
    if(my_argv[i] == NULL)
    {
        break;
    }
    if(strcmp(my_argv[i], ">") == 0)
    {
        if(my_argv[i+1] != NULL)
        {
            strncpy(fileName, my_argv[i+1], strlen(my_argv[i+1]));
            strncat(fileName, "\0", 1);
            //bzero(my_argv[i+1], strlen(my_argv[i+1])+1);
            //my_argv[i+1] = NULL;
            //free(my_argv[i+1]);
        } else {
            printf("no file name given\n");
            return;
        }
        //bzero(my_argv[i], strlen(my_argv[i])+1);
        //my_argv[i] = NULL;
        //free(my_argv[i]);
        redirectOutput(cmd, fileName);
        return;
    }
}

注释部分是我从函数中复制的地方,该函数清空my_argv以尝试释放argv的内容,其中&gt;和文件名是。它仍然在没有这些线路的情况下运行,但随后我不得不处理我的redirectOutput()函数中的额外条目,这是绝对的火车残骸。 free_argv()函数如下所示:

void free_argv()
{
    int index;
    for(index=0;my_argv[index]!=NULL;index++) {
        bzero(my_argv[index], strlen(my_argv[index])+1);
        my_argv[index] = NULL;
        free(my_argv[index]);
    }
}

1 个答案:

答案 0 :(得分:1)

你要做的工作比你需要的要多得多。您可以安全地为预先准备好的argv做任何事情,只要您在<{em> fork()之后 <{1>},在execve()之前, 当然)。没有这样的修改会影响父级,并且您不需要担心任何清理,因为exec用新的替换旧的过程映像。

示例:

/* these are already provided: */
char *filename =    /* ... */;
char **child_argv = /* ... */;
char **child_env  = /* ... */;

pid_t pid = fork();

if (pid == 0) {
    /* the child */
    char **arg;

    for (arg = child_argv; *arg && strcmp(*arg, ">"); arg += 1) { /* empty */ }
    *arg = NULL; /* terminate the arg list at the ">", if present */

    /* no need to clean up anything before execve() */

    execve(filename, child_argv, child_env);
    exit(1);  /* execve() failed */
} else if (pid < 0) {
    /* handle error */
}

/* the parent continues ... */