如何使用特定分隔符从 argv 执行多个命令

How to execute multiple commands from argv with an specific delimiter

最近我有一个任务,我必须编写一个程序,从命令行获取两个不同的命令,用“+”分隔,例如:

ps -lu myUsername + ls -la

程序的 objective 是通过使用 fork()exec() 同时 运行 任意两个订单,每个订单有任意数量的参数。这是我对这个问题的解决方案:

注意:原来的问题是 运行 在装有 Solaris 5.10 和 c89 或 c99 标准 (gcc 3.4.3) 的机器上

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <strings.h>

int main (int argc, char* argv[]) {
    char delimiter = '+';
    char* auxp; //auxiliar pointer
    int i = 1;
    int position;
    
    while(i < argc){
        if (strcmp("+", argv[i]) == 0) {
            argv[i] = NULL;
            position = i;
        }
        i++;
    }

    if (fork() == 0) {
        execvp(argv[1], &argv[1]);
        exit(1);
    }

    if (fork() == 0) {
        execvp(argv[position+1], &argv[position+1]);
        exit(1);
    }

    wait(NULL);
    wait(NULL);
    exit(0);
}

这对于作业来说已经足够了,但我想让它使用 N 个参数 而不是只有 2 个。我无法找到一个系统的方法来找到所有地址.感谢任何帮助,感谢建议。

只需将分叉移动到循环中:

int main (int argc, char* argv[])
{
    char** start = ++argv;
    unsigned int n = 0;
    for(; *argv; ++argv) // profiting from argv being null terminated, too...
    {
        if (strcmp("+", *argv) == 0)
        {
            *argv = NULL;
            if (fork() == 0)
            {
                execvp(*start, start);
                exit(1);
            }
            start = argv + 1;
            ++n; // but need to count how many times we actually forked!
        }
    }

    while(n--)
    {
        wait(NULL);
    }
    exit(0);
}

好的,我也对迭代进行了一些修改 - 指针更好(个人意见...)。

注意:这是未经测试的代码,如果您发现错误请自行修复...

对于 N 个命令的一般情况,需要跟踪每个命令的开始和结束位置,并在找到命令结尾时派生一个新的 child。这可能在 + 分隔符参数处,或者在原始参数列表的末尾。

#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main (int argc, char* argv[]) {
    /*
     * Note: argc could be in range 0 to INT_MAX.
     * Using unsigned int values to avoid arithmetic overflow.
     */
    unsigned int start = 1;
    unsigned int end = 1;
    unsigned int child_count = 0;

    /* Note: argv[argc] is a terminating null pointer. */
    while(end <= (unsigned int)argc){
        if(end == (unsigned int)argc || strcmp("+", argv[end]) == 0){
            /* Reached the terminating null pointer or a command separator. */
            argv[end] = NULL;
            if(start != end){
                /*
                 * Command is not empty.
                 * Fork a child process to execute the command.
                 */
                pid_t child = fork();
                if(child > 0){
                    /* Parent forked child successfully. */
                    child_count++;
                }else if(child == 0){
                    /* This is the child process. Execute command. */
                    execvp(argv[start], &argv[start]);
                    exit(1);
                }
            }
            /* Next command starts after this one. */
            start = end + 1;
        }
        /* Looking for terminating null pointer or command separator. */
        end++;
    }

    /* Wait for the child processes to terminate. */
    while(child_count){
        wait(NULL);
        child_count--;
    }
    exit(0);
}

注意:argv[end] = NULL; 行可以移动到 if(child == 0){ } 块中(但在调用 execvp 之前)以离开 parent的原始参数列表完好无损。