#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 " \t\n"
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 %s\n", 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: %s\n", 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 command\n");
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 go\n");
execvp(tokens[0], tokens);
}
}
// wait for child process to end
else
{
waitpid(-1, &status, WUNTRACED);
printf("the child process has now terminated\n");
// exit(0);
}
}
void handlePipe(char * cmds[])
{
printf("Initiate piping\n");
// 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));
}
}
Wenn ich meine Shell-Programm auszuführen, geben Sie ich in einem Befehl wie ls oder eine Katze, und der Befehl korrekt ausgeführt. Wenn ich einen weiteren Befehl nach dem One ausführe, wird der Befehl überhaupt nicht ausgeführt. Es könnte sogar der gleiche Befehl als der erste sein, den ich eingegeben habe, und es wird immer noch nicht für das zweite Mal laufen. Es werden keine Fehlermeldungen ausgegeben. Es gibt nur nicht aus, was der Befehl ruft, um es auszugeben. Ich benutze zur Zeit execvp, und ich glaube, dass ich die Argumente derzeit übergebe, also bin ich mir nicht sicher, wohin ich von hier aus gehen soll. Könnte mir jemand eine Eingabe zu geben, warum das passiert?Warum funktioniert execvp nur für den ersten Befehl in meiner Shell?
Bitte teilen Sie, was Sie getestet haben (falls vorhanden) und was Sie herausgefunden haben. Haben Sie beispielsweise Ihr Programm in einem Debugger ausgeführt und/oder weitere Debug-Print-Anweisungen hinzugefügt, um die Ausführung Ihres Programms nachzuverfolgen? – kaylum