为什么 execvp 仅适用于在我的 shell 中输入的第一个命令

Why does execvp only work for the first command entered in my shell?

本文关键字:输入 第一个 命令 shell 我的 execvp 适用于 为什么      更新时间:2023-10-16
#include <stdio.h>
#include <string.h>
#include <cstring>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/wait.h>
char input[100];
#define DELIMITERS " tn"
char * tokens[100];
int numTokens = 0;
int i = 0;
int n = 0;
char * cmd;
// function prototype
void nonBuiltin(char * inputs[]);
void handlePipe(char * cmds[]);
// this breaks the input into tokens and returns them
char * tokenize(char input[100])
{
  n = 0;
  // grabs input and separates by delimiters until the char is null
  for(cmd = strtok(input, DELIMITERS); cmd; cmd = strtok(NULL, DELIMITERS))
    {
      if(n >= 100)
       {
         break;
       }
      tokens[n++] = cmd;
      numTokens++;
    } 
    for(size_t i = 0; i != n; i++)
      {
        printf("Tokens %zu is %sn", i, tokens[i]);
      }
    return * tokens;
}
// handles the commands you enter
// checks if builtin or non builtin command
// if builtin, execute command
// else, send command to nonbuiltin function
void handleCommands(char * inputs)
{
  // changes directory
  if(strcmp(tokens[0], "cd") == 0)
    {
      int change = chdir(tokens[1]);
      if(change == 0)
        {
          chdir(tokens[1]);
        }
      else
        {
          perror("Cannot find path specified...n");
        }
    }
  // prints working directory
  else if(strcmp(tokens[0], "pwd") == 0)
    {
      printf("Your current working directory is: %sn", getenv("PWD"));
    }
  // implements set command
  else if(strcmp(tokens[0], "set") == 0)
    {
      // do this
    }
  // exits program
  else if(strcmp(tokens[0], "exit") == 0)
    {
      printf("Now exiting...n");
      exit(3);
    }
  // input contains a nonbuiltin command
  // sends input to nonbuiltin function
  else
    {
      printf("Your command is a nonbuilt-in commandn");
      nonBuiltin(tokens);
    }
}
void nonBuiltin(char * inputs[])
{
  int fp;
  int status;
  // create a new process
  pid_t pid;
  pid = fork();
  // process creation was unsuccessful
  if(pid < 0)
    {
      perror("Fork unsuccessful...n");
      exit(-1);
    }
  // child process
  else if(pid == 0)
    {
      // printf("Fork successful...n");
      if(numTokens >= 3)
    {
      for(int i = 0; i < numTokens; i++)
        {
          if(strcmp(tokens[i], "<") == 0)
          {
            tokens[i] = tokens[i+1];
            fp = open(tokens[i], O_RDONLY, 0);
            dup2(fp, 0);
            execvp(tokens[0], tokens);
          }
          else if(strcmp(tokens[i], ">") == 0)
          {
            tokens[i] = tokens[i+1];
            fp = open(tokens[i], O_WRONLY | O_CREAT | O_TRUNC, S_IWUSR | S_IRUSR | S_IRGRP | S_IWGRP);
            dup2(fp, 1);
            close(fp);
            tokens[i]= NULL;
            execvp(tokens[0], tokens);
          }
          else if(strcmp(tokens[i], "|") == 0)
            {
              tokens[i] = tokens[i+1];
              handlePipe(tokens);
            }
        }
    }
      else
      {
       // printf("Nothing special as far as commands gon");
       execvp(tokens[0], tokens); 

      }
    }
  // wait for child process to end
  else
    {
      waitpid(-1, &status, WUNTRACED);
      printf("the child process has now terminatedn");
     // exit(0);
    }
}

void handlePipe(char * cmds[])
{
    printf("Initiate pipingn");
    // file descriptors
    int fd[2];
    // fd[0] is the read end of pipe
    // fd[1] is the write end of pipe
    pipe(fd);
    if(!fork())
      {
        // first close the write end
        close(1);
        // fd[1] can now take stdout
        dup(fd[1]);
        close(fd[0]);
        execvp(cmds[0], cmds);
      }
     else
      {
        // close read end
        close(0);
        // fd[1] can now take stdin
        dup(fd[0]);
        close(fd[1]);
        execvp(cmds[1], cmds);
      }

}
// starts the program and asks the user to enter input
// loops until the user enters 'exit'
int main()
{
  while(1)
    {
      printf("Enter a command...n");
      fgets(input, 100, stdin);
      handleCommands(tokenize(input));
    }
}

当我运行我的 shell 程序时,我输入一个命令,如 ls 或 cat,然后 命令将正确执行。如果我在那之后运行另一个命令 第一,命令根本不会执行。它甚至可能是相同的 命令作为我输入的第一个命令,它仍然不会运行 第二次。未给出任何错误消息。它只是不输出什么 该命令调用它进行输出。我目前正在使用 execvp,我相信我目前正在传递参数,所以我不确定从这里开始。有人可以给我一些意见吗 为什么会这样?

只要你觉得合适(它在主循环中对我有用,尽管我会把设计留给你):

numTokens = 0;

您不会重置在标记化函数中递增的令牌数。使用全局变量很容易错过这样的小东西。