LINUX.ORG.RU

Проблема с записью в pipe

 ,


0

1

Добрый вечер, не могу понять как правильно реализовать «<<» Например при вызове «cat << aa» heredoc вроде нормально срабатывает и в pipe записывает все но кот не завершает работу и его даже никак не убить. Запись в пайп идет при флаге = 4 https://github.com/Quickaxe-Martina/beta21sh вот весь проект на всякий случай

 int 	ft_fd_flag(char **av, int *fd_in, int *p0, int *p1)
{
	int flag = 0;
	int i = -1;
	int st = 1;
	int fd;
	int b = 0;
	int f[2];
	char *str;//////////
	int j;/////////

	while (av[++i])
	{
		if (b == 0 && av[i][0] >= '0' && av[i][0] <= '9')
		{
			st = ft_atoi(av[i]);
		}
		else if ((av[i][0] == '>' || av[i][0] == '<' || av[i][0] == '&'))
		{
			ft_strcmp(av[i], ">") == 0 ? flag = 1 : flag;//Направить стандартный поток вывода в файл. Если файл не существует, он будет создан; если существует — перезаписан сверху.
			ft_strcmp(av[i], ">>") == 0 ? flag = 2 : flag;//Направить стандартный поток вывода в файл. Если файл не существует, он будет создан; если существует — данные будут дописаны к нему в конец.
			ft_strcmp(av[i], "<") == 0 ? flag = 3 : flag;//Использовать файл как источник данных для стандартного потока ввода.
			ft_strcmp(av[i], "<<") == 0 ? flag = 4 : flag;//Весь текст между блоками EOF (в общем случае вместо EOF можно использовать любое слово) будет выведен на экран. Важно: перед последним EOF не должно быть пробелов! (heredoc синтаксис).
			ft_strcmp(av[i], ">&-") == 0 ? flag = 5 : flag;//Закрыть поток вывода перед вызовом команды
			ft_strcmp(av[i], ">&") == 0 ? flag = 6 : flag;//Направить стандартный поток вывода и стандартный поток ошибок в файл. Другая форма записи: >файл 2>&1.
			ft_strcmp(av[i], "&>") == 0 ? flag = 6 : flag;
			b = 1;
		}
		else if (b == 1 && flag != 0)
		{
			if (flag == 1 || flag == 6)
				fd = open(av[i], O_CREAT | O_RDWR | O_TRUNC,
						S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);//добавить ошибки
			else if (flag == 2)
				fd = open(av[i], O_CREAT | O_RDWR | O_APPEND,
						S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
			else if (flag == 3)
				*fd_in = open(av[i], O_RDONLY);
			if (flag == 1 || flag == 2)
			{
				dup2(fd, st);
				close(fd);
			}
			else if (flag == 6)
			{
				dup2(fd, 1);
				dup2(fd, 2);
				close(fd);
			}
			else if (flag == 5)///////////
			{
				pipe(f);
				*p0 = f[0];
				*p1 = f[1];
				;
			}
			else if (flag == 4)
			{
				pipe(f);
				str = ft_strnew(1);
				set_input_mode();
				while (ft_strcmp(str, av[i]) != 0)
				{
					j = -1;
					while(str[++j])
						write(f[1], &str[j], 1);
					write(f[1], "\n", 1);
					free(str);
					str = ft_read_8(ft_main_norm(2), NULL, 2);//FIX IT
					write(2, "\n", 1);
				}
				ft_putchar_fd(EOF, f[1]);
				reset_input_mode();
				*fd_in = f[0];
			}
			b = 0;
			flag = 0;
			st = 1;
		}
	}
	return (fd);
}

void    ft_infinit_pipe(t_exectoken *head)
{
	int		p[2];
	pid_t	pid;
	int		fd_in = 0;
	int		fd;

	while (head)
	{
		pipe(p);
		if ((pid = fork()) == -1)
		{
			exit(1);
		}
		else if (pid == 0)
		{
			if (head->left != NULL)///////////////////////////////
			{
				dup2(p[1], 1);
				close(p[1]);
			}
			if (head->file_opt)
				fd = ft_fd_flag(head->file_opt, &fd_in, &p[0], &p[1]);
			dup2(fd_in, 0);
			close(p[0]);
			if (ft_path_fork(head->file_args, pid) == -1)
			{
				ft_putstr_fd("21sh: command not found: ", 2);
				ft_putendl_fd(&(head->file_args[0][1]), 2);
			}
			exit(0);
		}
		else
		{
			wait(NULL);
			close(p[1]);
			fd_in = p[0];
			head = head->left;
		}
	}
}


// <<

А почему не считать сначала во временный файл, отправить его кату на вход, после чего этот временный файл удалить. Это перенаправление уже работает, как я понимаю? Зачем тогда дополнительные сложности?

anonymous
()
Ответ на: комментарий от anonymous

Записать в пайп как я понимаю. У меня нет в списке разрешенных функций той которая сможет удалить файл, если конечно это опен это не может сделать. Единственное что я не понимаю почему у меня кот не завершает работу, хотя вывод он правильный делает

diosio
() автор топика
Последнее исправление: diosio (всего исправлений: 3)
Ответ на: комментарий от diosio

Нельзя unlink? Тоталитаризм. А виснет он наверное потому, что где-то поток не закрыт. Почему бы не прогнать через valgrind или strace (лучше и то, и другое) и не проследить по шагам, что происходит, а что нет (но должно было).

anonymous
()
Ответ на: комментарий от anonymous

Может подсказать какие флаги валгриндом надо ставить чтобы по шагам отследить, а то я только умею им утечки искать

diosio
() автор топика
Ответ на: комментарий от diosio

Не только утечки, я в основном неинициализированные (но используемые) переменные имел ввиду. Тот же memcheck в валгринде их ищет, не помню по умолчанию или –track-origins=yes нужен.

Но да, в основном strace.

anonymous
()

ft_strcmp(av[i], «>») == 0 ? flag = 1 : flag;//Направить стандартный поток вывода в файл. Если файл не существует, он будет создан; если существует — перезаписан сверху.

Ты хотя бы enum сделай. А то код читать невозможно.

hateyoufeel ★★★★★
()
Ответ на: комментарий от anonymous

==82927== execve(0x100baee40(/bin/ls), 0x100babb40, 0x100ba6b10) failed, errno 2

==82927== EXEC FAILED: I can’t recover from execve() failing, so I’m dying.

==82927== Add more stringent tests in PRE(sys_execve), or work out how to recover.

Скажи пожалуйста почему он даже на ls ругается хотя он нормально работает?

diosio
() автор топика
Ответ на: комментарий от hateyoufeel

Согласен, но вопрос не по этой части кода. А про то что при heredoc у меня ничего не работает:(

 			else if (flag == 4)
			{
				pipe(f);
				str = ft_strnew(1);
				set_input_mode();
				while (ft_strcmp(str, av[i]) != 0)
				{
					j = -1;
					while(str[++j])
						write(f[1], &str[j], 1);
					write(f[1], "\n", 1);
					free(str);
					str = ft_read_8(ft_main_norm(2), NULL, 2);//FIX IT
					write(2, "\n", 1);
				}
				ft_putchar_fd(EOF, f[1]);
				reset_input_mode();
				*fd_in = f[0];
			}

diosio
() автор топика
Ответ на: комментарий от diosio

Как я понимаю проблема в том что в пайп нет EOF и кот из за этого не может завершить работу, но как туда записать EOF не понятно

diosio
() автор топика
Ответ на: комментарий от diosio

Я же говорил, наверняка где-то поток не закрытый висит. С форками и пайпами такая фигня часто происходит. Чтобы с ними гладко работать, man fork, man pipe и примеры их использования нужно выучить наизусть.

anonymous
()
Ответ на: комментарий от diosio

Не встречал ранее. С другой стороны, программы с форками под ним гонял редко. Ну а поиск в сети показал, что конкретно это - возможно и внутренний глюк валгринда.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.