从cmd行读取命令,并在C中执行它们

时间:2012-09-21 23:06:06

标签: c unix command-line execv

我正在编写一个程序来从命令行(linux / unix命令)获取用户输入,并在我的程序中执行它们。

到目前为止我的步骤:

  1. 询问用户输入的命令数
  2. 用于创建子进程的Fork()
  3. 输出子PID和父PID
  4. 允许用户输入每个命令,将每个输入读入argv的索引
  5. 使用execv运行argv中的每个命令

  6. 主要问题是,当它执行时,它只执行execv命令中的“bin / ls /”。

    以下是运行程序的示例输出:

    输入命令数:2
    孩子的PID是3487.父母的PID是3485
    输入UNIX命令:ls
    输入UNIX命令:-al

    如果在CMD线上键入“LS”,文件列表

    流程完成。


    这是我的源代码:

    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <sys/types.h>
    
    void main(int argc, char *argv[20])
    {
            int pid;
            int num = 0;
    
            printf("Enter number of commands: ");
            scanf("%d", &argc);
    
            pid = fork();
    
            if(pid == 0)
            {
                    printf("Child's PID is %d. Parent's PID is %d\n", (int)getpid(), (int)getppid());
    
                    for(num=0; num < argc; num++)
                    {
                            printf("Enter a UNIX command: ");
                            scanf("%s", argv[num]);
                    }
    
                    argv[num+1] = 0;
    
                    execv("bin/ls/", argv);
            }
            else
            {
                    wait(pid);
                    printf("Process Complete.\n");
                    exit(0);
            }
    }
    

3 个答案:

答案 0 :(得分:0)

您的代码存在的一个特定问题是您必须将argv [idx]作为exec的参数传递。你通过argv传递一个char指针数组。

还请注意,argc包含完整的参数计数,并且完整计数包括程序本身。 argv [0]包含要传递参数的程序名称。我没有看到你的for循环反映出来。那就是你正在处理你自己的程序并运行它。

我写这些的方法是在一段时间内遍历argv(或者,如果你愿意的话),使用int变量 - 例如int idx=0; - 直到我找到一个argv [idx]指针那是空的。

例如,如果你有三个参数,argc将是4,而argv [3]将是你要处理的最后一个参数。 argv [4]将为null。

根据你收到的一些答案,这里有一个discussion的execv和fork。

答案 1 :(得分:0)

  1. 你的逻辑错误。在execv之前使用fork
  2. 将execv(与fork一起)移出循环;
  3. execv的第一个参数 - 是要执行的二进制文件的路径; 2nd - 传递给二进制文件的参数数组。这是对的吗? 当前目录名为'Assignments'的子目录和此目录 目录包含名为'ls'的可执行文件?而且,请仔细阅读'man execv'
  4. 更新:

    忽略上述第1点和第2点。

    man execv:

       The execv(), execvp(), and execvpe()  functions  provide  an  array  of
       pointers  to  null-terminated  strings that represent the argument list
       available to the new  program.   The  first  argument,  by  convention,
       should  point  to the filename associated with the file being executed.
       The array of pointers must be terminated by a NULL pointer.
    

答案 2 :(得分:0)

首先,您要在char* argv[20]中定义main,这不是一个好主意。如果您传递的参数超过20个,则会超出数组的范围。

其次,您试图将scanf("%s", argv[num])的字符串读入到我未能初始化的地址空间中。

当你的程序被调用时,操作系统会初始化argv []数组的“strings”,如果你没有向你的程序传递任何参数,你将没有任何“字符串”,这意味着你将写入你可能不拥有的随机记忆。

如果您真的想按照现在的方式加载命令,请尝试以下操作:

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

void main(int argc, char *argv[])
{
    int pid;
    int num = 0;
    int argc2 = 0;
    char* argv2[20]; // argv2 will point inside of buffer for convenience.
    char* buffer[2000]; // note each array has a limit of 100 characters.

    printf("Enter number of commands: ");
    scanf("%d", &argc2);

    pid = fork();

    if(pid == 0)
    {
            printf("Child's PID is %d. Parent's PID is %d\n", (int)getpid(), (int)getppid());

            for(num=0; num < argc2 && num < 20; num++) // your array is 20 long
            {
                    argv2[num] = &buffer[num * 100];
                    printf("Enter a UNIX command: ");
                    scanf("%s", argv2[num]);
            }

            argv[num] = 0; // no need to add + 1 because the for loop did already anyway.

            execv("Assignments/ls", argv2);
    }
    else
    {
            wait(pid);
            printf("Process Complete.\n");
            exit(0);
    }
}

或者你可以将参数传递给你的主程序,它只是将它们传递给被调用的程序,如下所示:

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

void main(int argc, char *argv[])
{
    int pid;
    int num = 0;

    printf("You entered %d commands: \n", argc);

    for (num = 0; num < argc; ++num)
    {
        printf("\t%s\n", argv[num]);
    }

    pid = fork();

    if(pid == 0)
    {
            printf("Child's PID is %d. Parent's PID is %d\n", (int)getpid(), (int)getppid());

            execv("Assignments/ls", &argv[1]);
    }
    else
    {
            wait(pid);
            printf("Process Complete.\n");
            exit(0);
    }
}