Execlp()不接受参数列表,只接受命令.UNIX/LINUX编程



我正在尝试创建一个微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 

外壳.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("nnWelcome to Nick Schuck's Microshell, user %s!nn", 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] = '';
    }
    //!!!TESTING TO SEE COMMAND ARE IN CMD1
    int b = 0;
    while(cmd1[b] != '')
    {
        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 errorn");
        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 mainn");
                exit(-1);
            }
        }
    }

main.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*()返回,这意味着命令失败。通常情况下,这意味着它应该打印一条错误消息(命令未找到,或权限被拒绝,或其他什么),然后以适当的非零错误状态退出。

最新更新