PA2

ewillwin·2022년 6월 8일
0

System Programming Lab

목록 보기
15/15
post-thumbnail

Make a swsh shell works under linux environment
-> which covers the files, signals, and IPC

Problem specification

A shell is a program that takes 1) input from a user, 2) interprets it, and 3) executes a command. swsh is a shell that implements only a small amount of functionality and can execute specific commands. It supports input / output redirection and pipeline functions.


The function of each symbol is the same as what we learned in the IPC class.

  • Pipeline: Connect the standard output of the preceding process through a pipe to the standard input of that later process
  • Input redirection: Replace the standard input (fd 0) of the process with the file [filename]
  • Output redirection: Replace the standard output (fd 1) of the process with the file [filename]
    -> If redirected by >, the file is initialized and rewritten
    -> If redirected by >>, append from the end of the file

Evaluating inputs

1) Determine the number of commands (when commands are connected by pipeline, etc.) (For each command)

2) Determine if input / output redirection was used

3) Analyzes the command type,
A. If you implement it yourself, create a child process (if necessary) to call that routine.
B. If you not implemented it yourself, create a child process to load and run the program.

4) If you create a child process, wait until it terminates

Process group

If swsh creates a new child process, make sure that it belongs to the new process group. (Make the pgid of that child process match its own pid)
If you create more than one process due to the use of pipes, make sure all processes belong to the group of processes you created first. (The pgido f the process must match the pid of the first child process created)

Reaping child process

If swsh has created a child process, use the wait series system call to identify and remove the child process so that no zombie processes are created.
If a process receives a SIGTSTP signal generated by the Ctrl + Z key during execution, it will stop and halt the execution of the process as usual. At the same time, the parent process receives the SIGCHLD signal and returns true if the parent executes the WIFSTOPPED macro on the status value obtained by calling waitpid as follows: (option WUNTRACED of the waitpid system call)

If a child process is stopped (when WIFSTOPPED is true), it kills all associated processes by sending a SIGKILL signal to the process group to which the child belongs.

Errors

If an error occurs while executing the mv, rm, cd command(cmd_type3), the message specified in the table below is combined as follows according to the type of the error and output as standard error. (This problem can be solved by using <errno.h>)

#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <errno.h>
#include <sys/msg.h>
#include <sys/types.h>

void handler(int sig)
{
	exit(0);
}

int main()
{
	char *cmd = NULL;
	size_t size = 0;
	char *arg[11];

	while(1){
		int i = 0;
		getline(&cmd, &size, stdin);
		cmd[strlen(cmd) - 1] = '\0';
		if(strlen(cmd) == 0)
			continue;

		char *ptr = strtok(cmd, " ");
		while(ptr != NULL){
			arg[i++] = ptr;
			ptr = strtok(NULL, " ");
		}
		arg[i] = NULL;
		if(strcmp("quit", arg[0]) == 0) //"quit"
			break;

		char path[100];
		sprintf(path, "/bin/%s", arg[0]);

		for(int x = 0; x < i; x++){
			if(strcmp(">", arg[x]) == 0){ //output redirection
				int fd = open(arg[x+1], O_RDWR|O_CREAT|O_TRUNC, 0644);
				
				if(fork() == 0){
					dup2(fd, STDOUT_FILENO);
					arg[x] = NULL;
					execv(path, arg);
				}
				wait(NULL);
				close(fd);
				break;
			}
			else if(strcmp(">>", arg[x]) == 0){ //output redirection (appending)
				int fd = open(arg[x+1], O_RDWR|O_APPEND, 0644);
				
				if(fork() == 0){
					dup2(fd, STDOUT_FILENO);
					arg[x] = NULL;
					execv(path, arg);
				}
				wait(NULL);
				close(fd);
				break;
			}
			else if(strcmp("<", arg[x]) == 0){ //input redirection
				int fd = open(arg[x+1], O_RDONLY);

				if(fork() == 0){
					dup2(fd, STDIN_FILENO);
					arg[x] = NULL;
					execv(path, arg);
				}
				wait(NULL);
				close(fd);
				break;
			}
			else if(strcmp("|", arg[x]) == 0){ //pipeline
				int fd[2];
				pid_t pid1, pid2;

				if(pipe(fd) < 0) exit(1);
				if((pid1 = fork()) == 0){ //parent
					close(fd[0]);
					dup2(fd[1], STDOUT_FILENO);
					arg[x] = NULL;
					execv(path, arg);
				}
				wait(NULL);

				if((pid2 = fork()) == 0){ //child
					close(fd[1]);
					char **arg2 = &arg[x + 1];
					sprintf(path, "/bin/%s", arg2[0]);
					dup2(fd[0], STDIN_FILENO);
					execv(path, arg2);
				}
				close(fd[0]);
				close(fd[1]);
				wait(NULL);
				break;
			}
			else if(strcmp("exit", arg[x]) == 0){ //exit
				if(arg[x+1] != NULL){
					int no = atoi(arg[x+1]);
					printf("%d\n", no);
					exit(no);
				}
				else{
					printf("%d\n", 0);
					exit(0);
				}
			}
			else if(strcmp("cd", arg[x]) == 0){ //cd
				if(chdir(arg[x+1]) != 0){
					perror("cd");
				}
				break;
			}

			if(x == i - 1){ //ls, man, grep, sort, head, tail, cat, mv, rm, cp, pwd
				if(fork() == 0){
					execv(path, arg);
				}
				wait(NULL);
				break;
			}
			
		} //for loop end
	}
}
profile
💼 Software Engineer @ LG Electronics | 🎓 SungKyunKwan Univ. CSE

0개의 댓글