minishell - KimTaebin-ai/study_posts GitHub Wiki

ํ•„์š” ๊ฐœ๋… ๋ฐ ํ•™์Šต ๋‚ด์šฉ

https://github.com/42-gyeongsan-minishell

history ๊ดœ์ฐฎ์€ ๋ธ”๋กœ๊ทธ ๊ทผ๋ฐ history ๋ช…๋ น์–ด๋ฅผ ๊ตฌํ˜„ํ•˜๋Š”๊ฒŒ ์•„๋‹ˆ๋ผ readline ํ•จ์ˆ˜๋กœ ๋ช…๋ น์–ด๋ฅผ ๋„ฃ์„ ๋•Œ add_history ํ•จ์ˆ˜๋กœ ๊ฐ’์„ ์ €์žฅ ์ด ๋‚ด์šฉ์€ ํ™”์‚ดํ‘œ ์œ„ ๋ฐฉํ–ฅ์„ ๋ˆ„๋ฅด๋ฉด ๋ฐ”๋กœ๋ฐ”๋กœ ๋‚˜์˜ด

$? ๊ฐ€์žฅ ์ตœ๊ทผ์— ์‹คํ–‰ํ•œ ๋ช…๋ น์–ด์˜ ๊ฒฐ๊ณผ๊ฐ’์„ ์ถœ๋ ฅํ•จ 0์ผ ๊ฒฝ์šฐ true, 127์ผ ๊ฒฝ์šฐ false์ด๋‹ค. ์•„์‹œ๊ฒ ๋ƒ

image

๊ณผ์ œ ์š”๊ตฌ ์‚ฌํ•ญ

  1. History ๊ธฐ๋Šฅ ๊ตฌํ˜„
  2. ์œ„์น˜๋ฅผ ์ฐพ์•„ (PATH๋ณ€์ˆ˜, ์ƒ๋Œ€, ์ ˆ๋Œ€ ๊ฒฝ๋กœ) ํŒŒ์ผ ์‹คํ–‰ ๊ตฌํ˜„
  3. ๋‹ซํžˆ์ง€ ์•Š์€ ๋”ฐ์˜ดํ‘œ๋‚˜ ๋ช…์‹œ๋˜์ง€ ์•Š์€ ํŠน์ˆ˜๋ฌธ์ž (\๋‚˜ ; ๋“ฑ...) ์„ ํ•ด์„ํ•˜์ง€ ์•Š์•„์•ผ ํ•ฉ
  4. ๋”ฐ์˜ดํ‘œ (') valid ์ฒดํฌ
  5. '' ์•ˆ์— ์žˆ๋Š” metacharacter (์ •๊ทœ์‹) ํ•ด์„ ๋…ธ๋…ธ
  6. "" ์•ˆ์— ์žˆ๋Š” $ (๋‹ฌ๋Ÿฌ๋ฅผ ์ œ์™ธํ•œ) metacharacter (์ •๊ทœ์‹) ํ•ด์„ ๋…ธ๋…ธ
  7. ๋ฆฌ๋‹ค์ด๋ ‰์…˜ >, >> ๊ธฐ๋Šฅ ๊ตฌํ˜„
  8. ํŒŒ์ดํ”„ ( | ๋ฌธ์ž) ๊ตฌํ˜„
  9. $ ๋’ค์— ์˜ค๋Š” ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ํ™œ์šฉ ๊ฐ€๋Šฅ
  10. $? ๊ฐ€์žฅ ์ตœ๊ทผ์— ์‹คํ–‰ํ•œ ํฌ๊ทธ๋ผ์šด๋“œ ํŒŒ์ดํ”„๋ผ์ธ์˜ ์ข…๋ฃŒ ์ƒํƒœ๋กœ ํ™•์žฅ
  11. ctrl-C, ctrl-D, ctrl-\ ๊ธฐ๋Šฅ ๊ตฌํ˜„

ctrl-C๋Š” ์ƒˆ๋กœ์šด ์ค„์— ์ƒˆ๋กœ์šด ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ถœ๋ ฅ

ctrl-D๋Š” ์…ธ์„ ์ข…๋ฃŒ

ctrl-\์€ ์•„๋ฌด๋Ÿฐ ๋™์ž‘๋„ ํ•˜์ง€ ์•Š์Œ

  1. -n ์˜ต์…˜์„ ํฌํ•จํ•œ echo
  2. ์ƒ๋Œ€ ๋˜๋Š” ์ ˆ๋Œ€ ๊ฒฝ๋กœ๋งŒ ์ฒ˜๋ฆฌํ•˜๋Š” cd
  3. ์˜ต์…˜์ด ์—†๋Š” pwd
  4. ์˜ต์…˜์ด ์—†๋Š” export
  5. ์˜ต์…˜์ด ์—†๋Š” unset
  6. ์˜ต์…˜์ด๋‚˜ ์ธ์ž๊ฐ€ ์—†๋Š” env
  7. ์˜ต์…˜์ด ์—†๋Š” exit

๊ฐœ๋ฐœ ์ˆœ์„œ

  1. readline Makefile์— -lreadline flag ์ถ”๊ฐ€ ํ•„์š”
  2. add_history() ํ•จ์ˆ˜ ์ฒ˜๋ฆฌ
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <string.h>

void ft_putchar_err(char c)
{
	write(STDERR_FILENO, &c, 1);
}

int error(char* str)
{
	while (*str)
		ft_putchar_err(*str++);
	return (1);
}

int fatal(char** free_ptr)
{
	free(free_ptr);
	exit(error("error: fatal\n"));
}

int size_cmd(char **cmd)
{
	if (!cmd)
		return (0);
	int i = -1;
	while (cmd[++i]);
	return (i);
}

int size_cmd_char(char **cmd, char *str)
{
	if (!cmd)
		return (0);
	int i = -1;
	while (cmd[++i])
		if (!strcmp(cmd[i], str))
			return (i);
	return (i);
}

char** find_next_pipe(char **cmd)
{
	if (!cmd)
		return (NULL);
	int i = -1;
	while (cmd[++i])
		if (!strcmp(cmd[i], "|"))
			return (&cmd[i + 1]);
	return (NULL);
}

char** add_cmd(char **av, int *i)
{
	int size = size_cmd_char(&av[*i], ";"); 
	if (!size)
		return (NULL); 

	char **tmp = NULL;
	if (!(tmp = malloc(sizeof(*tmp) * (size + 1))))
		fatal(NULL);

	int j = -1;
	while (++j < size)
		tmp[j] = av[j + *i];
	tmp[j] = NULL;
	*i += size; 
	return (tmp);
}

int builtin_cd(char **cmd)
{
	if (size_cmd(cmd) != 2)
		return (error("error: cd: bad arguments\n"));
	if (chdir(cmd[1]) < 0)
	{
		error("error: cd: cannot change directory ");
		error(cmd[1]);
		error("\n");
	}
	return (0);
}

int exec_cmd(char **cmd, char **env, char **free_ptr)
{
	pid_t pid;

	if ((pid = fork()) < 0)
		fatal(free_ptr);
	if (!pid)
	{
		if (execve(cmd[0], cmd, env) < 0)
		{
			error("error: cannot execute ");
			error(cmd[0]);
			free(free_ptr); 
			exit(error("\n"));
		}
	}
	waitpid(0, NULL, 0);
	return (0);
}

int exec_son(char** free_ptr, char** env, char** tmp, int fd_in, int fd_pipe[2])
{
	if (dup2(fd_in, STDIN_FILENO) < 0)
		fatal(free_ptr);
	if (find_next_pipe(tmp) && dup2(fd_pipe[1], STDOUT_FILENO) < 0) // If there is still a pipe after this command
		fatal(free_ptr);

	close(fd_in);
	close(fd_pipe[0]);
	close(fd_pipe[1]);

	tmp[size_cmd_char(tmp, "|")] = NULL;
	exec_cmd(tmp, env, free_ptr);
	
	free(free_ptr);
	exit(0);
}

int execute(char **cmd, char **env)
{
	if (!find_next_pipe(cmd))
		return (exec_cmd(cmd, env, cmd));

	int fd_in;
	int fd_pipe[2];
	char **tmp = cmd;
	int nb_wait = 0;
	pid_t pid;

	if ((fd_in = dup(STDIN_FILENO)) < 0)
		return (fatal(cmd));

	while (tmp)
	{
		if (pipe(fd_pipe) < 0 || (pid = fork()) < 0)
			fatal(cmd);
			
		if (!pid)
			exec_son(cmd, env, tmp, fd_in, fd_pipe);
		
		else
		{
			if (dup2(fd_pipe[0], fd_in) < 0)	
				fatal(cmd);						
			close(fd_pipe[0]);
			close(fd_pipe[1]);
			++nb_wait;
			tmp = find_next_pipe(tmp); 
		}
	}

	close(fd_in); 

	while (nb_wait-- >= 0)
		waitpid(0, NULL, 0);
	return (0);
}

int main(int ac, char **av, char **env)
{
	char **cmd = NULL;
	int i = 0;

	while (++i < ac)
	{
		cmd = add_cmd(av, &i);
		
		if (cmd && !strcmp(cmd[0], "cd"))
			builtin_cd(cmd);
		else if (cmd)
			execute(cmd, env);

		free(cmd);
		cmd = NULL;
	}
	return (0);
}
โš ๏ธ **GitHub.com Fallback** โš ๏ธ