Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 31.05.2010, 17:31   #1
Card1nal
Пользователь
 
Регистрация: 31.10.2009
Сообщений: 44
По умолчанию Шелл на C

добрый день. Пишу в данный момент шелл, и никак не могу понять, как выполнять несколько перенаправлений, вроде ls | cat -e | wc -l > test.
Насколько я понимаю, в начале идет следуюшая последовательность действий:
fork -> pipe -> dup2;

а вот как дальше...
В данный момент эта строка в форме двойного массива символов:
ls
|
cat -e
|
wc -l
>
test

помогите пожалуйста
Card1nal вне форума Ответить с цитированием
Старый 31.05.2010, 17:36   #2
oleg kutkov
Unix C++ developer
Форумчанин
 
Аватар для oleg kutkov
 
Регистрация: 16.04.2007
Сообщений: 651
По умолчанию

Если потерпите до вечера, подкину вам исходники "самодельного" рабочего шелла, когда то писал сам, ради интереса
Там поддерживаются перенаправления и каналы.
oleg kutkov вне форума Ответить с цитированием
Старый 31.05.2010, 17:40   #3
ozo
Форумчанин
 
Аватар для ozo
 
Регистрация: 26.04.2010
Сообщений: 328
По умолчанию

А если нет - смотрите исходники sh( тот который gnu ), он самый простой из многих
Используй гугль, будь счастлив
hackme@yandex.ru
Блог об archlinux
ozo вне форума Ответить с цитированием
Старый 31.05.2010, 18:00   #4
Card1nal
Пользователь
 
Регистрация: 31.10.2009
Сообщений: 44
По умолчанию

Цитата:
Сообщение от oleg kutkov Посмотреть сообщение
Если потерпите до вечера, подкину вам исходники "самодельного" рабочего шелла, когда то писал сам, ради интереса
Там поддерживаются перенаправления и каналы.
естественно, потерплю)
Заранее спасибо

Последний раз редактировалось Card1nal; 01.06.2010 в 00:56.
Card1nal вне форума Ответить с цитированием
Старый 01.06.2010, 23:17   #5
oleg kutkov
Unix C++ developer
Форумчанин
 
Аватар для oleg kutkov
 
Регистрация: 16.04.2007
Сообщений: 651
По умолчанию

Прошу прощения за задержку.
Представляю исходный код простой шелл, можете взять за основу.

файл main.c

Код:
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <readline/readline.h>
#include <signal.h>
#include "shell.h"
#include "print_cmd.h"
using namespace std;

char *stripwhite (char *string);
void execute_line(char *line);

int main(int argc, char* argv[], char *envp[])
{
	char *line, *s;
	for (int i = 0; i < 20; i++) signal(i, SIG_IGN);
	setsid();
	for(;;) { 
		Print_cmd_line(getenv("HOME"), getenv("USERNAME"), getenv("HOSTNAME"), getenv("PWD"));
		line = readline (NULL);
		if (line) s = stripwhite(line);
		if (*s)	{
		  if (strstr(line, "exit"))
			 return 0; else
				execute_line (s);
		}
	}
	return 0;
}

char *stripwhite (char *string) {
  register char *s, *t;
  for (s = string; whitespace (*s); s++);
  if (*s == 0)
    return (s);
  t = s + strlen (s) - 1;
  while (t > s && whitespace (*t))
    t--;
  *++t = '\0';
  return s;
}

void execute_line(char *line) {
  CMD_INFO pCmd, sCmd;
	 char *word;
		word = strtok(line, " "); //разбивка введенной строки на отдельные слова, используя пробел, как разделитель	 
		while (word != NULL) //крутим цикл, пока не переберем все слова в строке
		{
					if (strstr(word, "<")) 
					{
						word = strtok(NULL, " ");
						pCmd.add_iofile(word, '<');						
					}
					else
					if (strstr(word, ">")) 
					{
						word = strtok(NULL, " ");
						pCmd.add_iofile(word, '>');						
					}
					else
					if (strstr(word, "|"))  
					{	
						while (word != NULL) 
						{							    
							word = strtok(NULL, " ");
							if (word != NULL)
								sCmd.add_arg(word);
						}
						pCmd.add_pipe(&sCmd);
					}
					else
					pCmd.add_arg(word);	
			word = strtok(NULL, " "); //выборка следующего слова		
		}
		exec_cmd (&pCmd);
}
oleg kutkov вне форума Ответить с цитированием
Старый 01.06.2010, 23:18   #6
oleg kutkov
Unix C++ developer
Форумчанин
 
Аватар для oleg kutkov
 
Регистрация: 16.04.2007
Сообщений: 651
По умолчанию

файл shell.h

Код:
/*  shell.h */
#ifndef SHELL_H
#define SHELL_H

#include <iostream>
#include <string.h>
#include <assert.h>
#include <malloc.h>
#include <memory.h>

class CMD_INFO {
	public:
		char**		argv;				// список команд и аргументов
		char* 			infile;    			// переназначенный файл стандартного ввода
	 	char*			outfile; 			// перенаправленный файл стандартного вывода
		int				background;	// значение 1 - признак того, что команду следует выполнять в фоновом режиме
		CMD_INFO*	Pipe;				// следующая команда, после ' | '
		
		// конструктор
		CMD_INFO() {
			argv = 0;
			infile = outfile = 0;
			background = 0;
			Pipe = 0;
		};
		
		// деструктор
		~CMD_INFO()	{
			if (infile) delete infile;
			if (outfile) delete outfile;
			for (int i=0; argv && argv[i]; i++) delete argv[i];
			delete argv;
		};
		
		// добавить одну строку аргументов в argv 
		void add_arg(char* str) {
			int len = 1;
			if (!argv)
				argv = (char**)malloc(sizeof(char*)*2);
			else
				{
					while (argv[len]) len++;
					len++;
					argv = (char**) realloc(argv, sizeof(char*)*(len+1));
				}
			assert(argv[len-1] = strdup(str));
			argv[len] = 0;
			};
		
		// добавить имя переназначенного файла стандартного ввода или вывода
		void add_iofile(char* iofile, char fnm) {
			if(fnm == '>') { 
				outfile = (char*)malloc(sizeof(char*)*2);	
				assert(outfile = strdup(iofile));
		     } else if(fnm == '<') {
				infile = (char*)malloc(sizeof(char*)*2);	
				assert(infile = strdup(iofile));					
				}
			};
		
		// добавить комадный канал
		void add_pipe(CMD_INFO* pCmd) {
			if (Pipe)
				Pipe->add_pipe(pCmd);
			else 
				Pipe = pCmd;
		};
};			

extern void exec_cmd(CMD_INFO *pCmd);
#endif
oleg kutkov вне форума Ответить с цитированием
Старый 01.06.2010, 23:21   #7
oleg kutkov
Unix C++ developer
Форумчанин
 
Аватар для oleg kutkov
 
Регистрация: 16.04.2007
Сообщений: 651
По умолчанию

файл print_cmd.c

Код:
#include <stdio.h>
#include <string.h>
#include "print_cmd.h"

void Print_cmd_line(char *Home, char *username, char *host, char *curdir)
{
	char prompt[255] = {0};
		if(username == NULL)
		strncat(prompt, "user", 4);
		else
		strncat(prompt, username, sizeof(username));
		strncat(prompt, "@", 1);
		if(host == NULL)
		strncat(prompt, "localhost", 9);
		else
		strncat(prompt, host, sizeof(host));
		strncat(prompt, ":", 1);
		if(!strcmp(Home, curdir))
			strcat(prompt, "~$ \0");
		else
		{
			strcat(prompt, curdir);
			strcat(prompt, "$ \0");
		}
	printf("%s", prompt);
}
файл print_cmd.h

Код:
void Print_cmd_line(char *Home, char *username, char *host, char *curdir);

Последний раз редактировалось oleg kutkov; 01.06.2010 в 23:29.
oleg kutkov вне форума Ответить с цитированием
Старый 01.06.2010, 23:22   #8
oleg kutkov
Unix C++ developer
Форумчанин
 
Аватар для oleg kutkov
 
Регистрация: 16.04.2007
Сообщений: 651
По умолчанию

файл exec_cmd.c

Код:
/* main.c */
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <readline/readline.h>
#include <signal.h>
#include "shell.h"
#include "print_cmd.h"
using namespace std;

char *stripwhite (char *string);
void execute_line(char *line);

int main(int argc, char* argv[], char *envp[])
{
	char *line, *s;
	for(int i = 0; i < 20; i++) signal(i, SIG_IGN);
	setsid();
	for(;;) { 
		Print_cmd_line(getenv("HOME"), getenv("USERNAME"), getenv("HOSTNAME"), getenv("PWD"));
		line = readline (NULL);
		if(line) s = stripwhite(line);
		if (*s)	{
		  if(strstr(line, "exit"))
			 return 0; else
				execute_line (s);
		}
	}
	return 0;
}

char *stripwhite (char *string) {
  register char *s, *t;
  for (s = string; whitespace (*s); s++);
  if (*s == 0)
    return (s);
  t = s + strlen (s) - 1;
  while (t > s && whitespace (*t))
    t--;
  *++t = '\0';
  return s;
}

void execute_line(char *line) {
  CMD_INFO pCmd, sCmd;
	 char *word;
		word = strtok(line, " "); //разбивка введенной строки на отдельные слова, используя пробел, как разделитель	 
		while(word != NULL) //крутим цикл, пока не переберем все слова в строке
		{
					if(strstr(word, "<")) 
					{
						word = strtok(NULL, " ");
						pCmd.add_iofile(word, '<');						
					}
					else
					if(strstr(word, ">")) 
					{
						word = strtok(NULL, " ");
						pCmd.add_iofile(word, '>');						
					}
					else
					if(strstr(word, "|"))  
					{	
						while(word != NULL) 
						{							    
							word = strtok(NULL, " ");
							if(word != NULL)
								sCmd.add_arg(word);
						}
						pCmd.add_pipe(&sCmd);
					}
					else
					pCmd.add_arg(word);	
			word = strtok(NULL, " "); //выборка следующего слова		
		}
		exec_cmd (&pCmd);
}
файл exec_cmd.h
Код:
void exec_cmd(CMD_INFO *pCmd);
oleg kutkov вне форума Ответить с цитированием
Старый 01.06.2010, 23:24   #9
oleg kutkov
Unix C++ developer
Форумчанин
 
Аватар для oleg kutkov
 
Регистрация: 16.04.2007
Сообщений: 651
По умолчанию

Понимаю, что не идеал, писалось когда-то давно, чисто для себя.
Надеюсь будет полезно
oleg kutkov вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Как содать шелл ? ScorpioN_T Помощь студентам 3 27.10.2008 15:47