c++ - Execlp() 不接受参数列表,只接受命令。 UNIX/LINUX编程

标签 c++ shell unix

我正在尝试创建一个微 shell 。它读入命令,解析并拆分,然后执行。要解析,首先我用定界符 || 分隔,如果有管道,最多可以得到两个命令。将每个命令拆分为一个字符串数组。

我认为这就是 execlp 的工作方式,但它只运行命令,即使 C 字符串“cmd1”确实包含参数。有人可以帮我理解我是如何将参数错误地传递给 execlp 函数的吗?

shell .h

   /****************************************************************
   PROGRAM:   MicroShell(assignment 4)
   FILE:      shell.h

   AUTHOR:    Nick Schuck

   FUNCTION:  This contains the header for the shell class   
   ****************************************************************/
   #ifndef _shell_h
   #define _shell_h

   #include <sys/types.h>
   #include <unistd.h>  
   #include <cstdio>
   #include <pwd.h>
   #include <cstring>
   #include <sys/wait.h>
   #include <cstdlib>
   #include <vector>


   class Shell
   {
        private:
        char buffer[1024];
        const char *cmd1[10];
        const char *cmd2[10];

        public:
        Shell();  //default constructor
        void askForCommand(); 
        void readCommandLine();
        void parseBuffer();
        void invokeCommand();
        void executeOneCommand();
        void executeTwoCommands();
        };

        #endif 

shell.cc

     /***************************************************************
         PROGRAM:   MicroShell(assignment 4)
         FILE:      shell.c

   AUTHOR:    Nick Schuck

   FUNCTION:  This file contains the implementation of 
              class shell from file "shell.h"
****************************************************************/
#include "shell.h"
#include <iostream>


Shell::Shell()
{
    /**Get current user*/
    struct passwd *p = getpwuid(getuid());
    if (!p) //Error handling
        puts("Welcome to Nick Schuck's MicroShell, Anonymous");

    /**Welcome message for my shell*/
    printf("\n\nWelcome to Nick Schuck's Microshell, user %s!\n\n", p->pw_name);
}


void Shell::askForCommand()
{
    /**Command Prompt*/
    printf("myshell>");
}


void Shell::readCommandLine()
{
    /**Read stdin into buffer array IF no*/
    /**errors occur                      */
    if (fgets(this->buffer, 1024, stdin) != NULL)
    {
        this->buffer[strlen(this->buffer) - 1] = 0;
    }
}


void Shell::parseBuffer()
{
    /**Variables*/
    int i = 0, u = 0,
        t = 0;
    char *ptr;  
    char parsingBuffer[2][512];


    /**Parse buffer for multiple commands*/
    strcpy(parsingBuffer[0], strtok(this->buffer, "||"));
    while ((ptr = strtok(NULL, "||")) != NULL)
    {
        i++;
        strcpy(parsingBuffer[i], ptr);
    }


    //**Get first command*/
    this->cmd1[0] = strtok(parsingBuffer[0], " ");
    while ((ptr = strtok(NULL, " ")) != NULL)
    {
        u++;
        this->cmd1[u] = ptr;
        this->cmd1[u+1] = '\0';
    }

    //!!!TESTING TO SEE COMMAND ARE IN CMD1
    int b = 0;
    while(cmd1[b] != '\0')
    {
        std::cout << cmd1[b] << "\n";
        b++;
    }


    /**Get second command*/
    this->cmd2[0] = strtok(parsingBuffer[1], " ");
    while ((ptr = strtok(NULL, " ")) != NULL)
    {
        t++;
        this->cmd2[t] = ptr;
    }
}


void Shell::invokeCommand()
{
    if (this->cmd1[0] == NULL)
    {
        //do nothing
    }
    else if(this->cmd1[0] != NULL && this->cmd2[0] == NULL)
    {
        executeOneCommand();
    }
    else if(this->cmd1[0] != NULL && cmd2[0] !=NULL)
    {
        executeTwoCommands();
    }
}


void Shell::executeOneCommand()
{
    pid_t pid; //pid for fork
    int status;
    char args[512];

    if ((pid = fork()) < 0)
    {
        printf("fork error\n");
        exit(-1);
    }
    else if(pid == 0)  //Child Process
        {
            execlp(cmd1[0], *cmd1);     
        }
        else  //Parent Process
        {
            if ((pid = waitpid(pid, &status, 0)) < 0)
            {
                printf("waitpid error in main\n");
                exit(-1);
            }
        }

    }

主.cc

#include "shell.h"
#include <iostream>
#include <vector>

int main()
{
    const int BUFFER_SIZE = 1024;
    const int MAX_COMMANDS_IN_BUFFER = 2;

    /**Initialize a new shell object*/
    Shell shell;

    /**Print command prompt to screen*/
    shell.askForCommand();

    /**Read users command*/
    shell.readCommandLine();

    /**parse buffer to find individual*/
    /**commands                        */
    shell.parseBuffer();

    /**Invoke command*/
    shell.invokeCommand();
}

最佳答案

您不能使用 execlp() — 您必须使用 execvp() .

execvp(cmd1[0], cmd1);

要使用 execlp(),您必须在编译时知道命令的固定参数列表 — 您必须能够编写:

execlp(cmd_name, arg0, arg1, …, argN, (char *)0);

您对 execlp() 的调用也是错误的,因为您没有提供 (char *)0 参数来指示参数列表的结尾。

您的代码还需要处理 exec*() 返回,这意味着命令失败。通常这意味着它应该打印一条错误消息(该命令未找到,或权限被拒绝,或其他),然后以适当的非零错误状态退出。

关于c++ - Execlp() 不接受参数列表,只接受命令。 UNIX/LINUX编程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36202117/

相关文章:

c++重载方法参数与原始方法的参数派生类

linux - 强制 bash 扩展从文件加载的字符串中的变量

bash - "set -- ${@:2} "在 bash shell 中意味着什么

c++ - xterm:无法 execvp:没有文件或目录

c++ - 'ld : unknown option: -rpath=./libs' - 在 mac os 10.7.5 上构建 openframework 插件时出现链接错误

c++ - 仅在一个特定的类文件中使用命名空间

c++ - 怎么注释几行,里面有注释

shell - 如何查找 PWD 中引用 PWD 之外的文件的所有符号链接(symbolic link)? UNIX

c++ - UNIX/OSX 版本的 semtimedop

perl - 如何在 Perl 中同时运行一个大队列中的多个作业?