C 코드로 셸을 만드는 작업이 있으며 대부분의 경우 작동하는 솔루션이 있습니다. 내 솔루션은 프로그램이 존재하는 경우 작동하며 Control-D 또는 종료를 입력하여 쉘을 종료 할 수 있습니다. 그러나 내가 알지 못하는 명령을 실행하려고하면 쉘이 명령을 찾을 수 없다는 오류 메시지를 출력하지만 exit 나 press를 입력해야합니다. Control-D 유효하지 않은 명령과 동일한 시간이 경과했습니다. 즉, 잘못된 명령을 3 번 입력하면 컨트롤 -D 번을 3 번 누르십시오. 나는 정말로 여기서 무슨 일이 일어나고 있는지 모른다. Control-D을 누르면 모든 변수를 검사하고 -1이 읽히지 만 if 문은 건너 뛴 것처럼 보입니다.execvp()가 실패한 후 필자가 작성한 셸이 올바르게 종료되지 않는다.
comp20200Shell.c
#include "comp20200Shell_header.h"
#include <signal.h>
/*
* Name: ****
* Student Number: ****
* Email: ****
*
* This is the main function of my shell implementation.
*
*/
int main(void)
{
bool end_program = false;
size_t length = 0;
ssize_t read;
char* current_directory = NULL;
char* current_time = NULL;
/* Sets up signal handler to catch SIGINT*/
if(signal(SIGINT, sigintHandler) == SIG_ERR)
{
error("An error occured while setting a signal handler\n");
}
/* Infinitive loop, so after command or invalid comman will prompt again*/
while(end_program != true)
{
char* input = NULL;
/* Gets current working directory */
current_directory = return_current_directory();
/* Gets current date and time */
current_time = return_time();
/* Prints Prompt */
printf("%s\x5b%s\x5d %s%s %s%s%s", MAGENTA_TEXT, current_time, GREEN_TEXT, current_directory, BLUE_TEXT, PROMPT, RESET_COLOUR);
/* Frees the pointers returned by return_time() and return_current_directory() */
free(current_time);
free(current_directory);
/* Reads one line from standard input */
read = getline(&input, &length, stdin);
/* Checks if ctrl d, i.e. end of file is found or exit is typed */
if(strcmp(input, "exit\n") == 0 || read == -1)
{
if(read == -1)
{
putchar('\n');
}
/* Frees input */
free(input);
return(0);
}
/* Removes newline character that will be at the end */
remove_trailing_newline(input);
/* Passes input to process input, and the return value is passed in to process errors */
process_errors(process_input(&input));
/* Frees input */
free(input);
}
return(0);
}
process_input.c
#include "comp20200Shell_header.h"
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
/*
* Name: ****
* Student Number: ****
* Email: ****
*
* This function is used to process the command entered by the user
*
* return: the error value or 0 when everything whent ok
* arguments: the command entered by the user
*
*/
int process_input(char** input)
{
bool redirect_stdout = false;
bool redirect_stderr = false;
pid_t child_pid;
int child_status;
char** argument = malloc(sizeof(char*));
int count = 0;
char* temp = strtok(*input, " ");
while(temp != NULL)
{
argument[count] = temp;
count ++;
argument = realloc(argument, (count+2) * sizeof(char *));
temp = strtok(NULL, " ");
}
argument[count] = NULL;
if(argument[0] == NULL)
{
return(0);
}
else if(strcmp(argument[0], "cd") == 0)
{
return(change_directory(argument[1]));
}
int index;
for(index = 1; argument[index] != NULL; index++)
{
if(strcmp(argument[index], ">0") == 0)
{
if(argument[index + 1] == NULL)
{
return(EINVAL);
}
redirect_stdout = true;
break;
}
else if(strcmp(argument[index], ">2") == 0)
{
if(argument[index + 1] == NULL)
{
return(EINVAL);
}
redirect_stderr = true;
break;
}
}
child_pid = fork();
if(child_pid == 0)
{
int file;
if(redirect_stdout == true)
{
file = open(argument[index + 1], O_WRONLY|O_CREAT|O_TRUNC, 0666);
dup2(file, 1);
edit_arguments(argument, index);
execvp(argument[0], argument);
return(-1);
}
else if(redirect_stderr == true)
{
file = open(argument[index + 1], O_WRONLY|O_CREAT|O_TRUNC, 0666);
dup2(file, 2);
edit_arguments(argument, index);
execvp(argument[0], argument);
return(-1);
}
execvp(argument[0], argument);
return(-1);
}
else
{
wait(&child_status);
}
return(child_status);
}
comp20200Shell_header.h
: 여기 내가 문제가있는 생각 내 소스 코드의 일부입니다/*
* Name: ****
* Student Number: ****
* Email: ****
*
* This is my header file, It includes all common used headerfiles on the top.
* Any specific header file that is only used once will be included with the .c file that needs it.
*
*/
/* included headerfiles begin */
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <stdbool.h>
/* included headerfiles end */
/* defenitions begin */
#define PROMPT "# "
#define BUFFER_SIZE 1024
#define BLUE_TEXT "\x1B[34m"
#define MAGENTA_TEXT "\x1B[35m"
#define GREEN_TEXT "\x1B[32m"
#define RESET_COLOUR "\x1B[0m"
/* defenitions end */
/* Function prototypes begin */
void remove_trailing_newline(char *input);
void sigintHandler(int sig_num);
int process_input(char** input);
char* return_time(void);
void error(const char *fmt, ...);
int change_directory(char* path);
char* return_current_directory(void);
void process_errors(int return_value);
void edit_arguments(char** argument, int index);
/* Function prototypes end */
나는 문제가 있다고 생각하지 않기 때문에 나머지 소스 코드를 생략했다.
자식과 아버지는 백그라운드 작업을 지원하지 않으므로 (즉, 아버지가 포크 직후에 wait (& child_status)를 수행하므로) 구현에서 싸우지 않게됩니다. –