Модераторы: xvr
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Отлавливание команд 
V
    Опции темы
Ak47black
  Дата 2.10.2010, 16:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2205
Регистрация: 2.12.2005

Репутация: нет
Всего: 0



Здравствуйте.
Вот такой у меня код вышел шелла
Код

//---------------------------------------------------------------------------

#pragma hdrstop

#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <netinet/in.h>
#include <resolv.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <iostream>
using namespace std;


void parseA(char* input);
void parseB(char* input);
void parseC(char* input);
void parseD(char* input);







char* cmdparams[20][20][20] = {NULL};
int block = 0;
int cmd = 0;
int param = 0;

void parseA(char* input)
{
    while (input[0] != 0)
    {
        cmd = 0;
        const char* delim = strchr(input, '|');
        if (delim)
        {
            int len = delim-input;
            char* subcmd = (char*)malloc(len);
            strncpy(subcmd, input, len);
            subcmd[len] = '\0';

            parseB(subcmd);
            block++;
            strcpy(input, delim+1);
        }
        else
        {
            parseB(input);
            return;
        }
    }
}

void parseB(char* input)
{
    while (input[0] != 0)
    {
        param = 0;
        char* delim = strchr(input, '&');
        if (delim)
        {
            int len = delim-input;
            char* subcmd = (char*)malloc(len);
            strncpy(subcmd, input, len);
            subcmd[len] = '\0';
            parseC(subcmd);
            cmd++;
            strcpy(input, delim+1);
        }
        else
        {
            parseC(input);
            return;
        }
    }
}

void parseC(char* input)
{
   while (input[0] == ' ') strcpy(input, input+1);
   while (input[strlen(input)-1] == ' ') input[strlen(input)-1] = '\0';

   while (input[0] != 0)
   {
        char* delim = strchr(input, ' ');
        if (delim)
        {
            int len = delim-input;
            char* subcmd = (char*)malloc(len);
            strncpy(subcmd, input, len);
            subcmd[len] = '\0';
            parseD(subcmd);
            param++;
            strcpy(input, delim+1);
        }
        else
        {
            parseD(input);
            return;
        }
   }
   
}

void parseD(char* input)
{
    cmdparams[block][cmd][param] = input;
}
//---------------------------------------------------------------------------




//---------------------------------------------------------------------------



int main(int argc, char* argv[])
{
    //char input[] = "ls -l | cut -c 1-20 | cut -c 1-1 \0";

    char input[] = "sleep 1 & sleep 5 \0";
    //getline(cin, input);
    parseA(input);
    if (input[0] == 0) {perror("no params"); exit(1);}

    int i = 0;
    int e = 0;
    int ids[20];
    int pipes[20][2];
    int count = 0;
    for (int i = 0; i < block; i++)
        pipe(pipes[i]);

    while (cmdparams[i][e][0] != NULL)
    {
        while (cmdparams[i][e][0] != NULL)
        {
            if (pipe(pipes[i]) == -1)    {perror("error creating pipe"); exit(1);}
            if (cmdparams[i][e][0] != NULL)
            {
                if ((ids[count] = fork()) == -1)   {perror("error creating child process"); exit(1);}
                if (ids[count] == 0)
                {
                    if (cmdparams[i-1][e][0] != NULL)
                    {
                        dup2(pipes[i-1][0], 0);
                        close(pipes[i-1][0]);
                        close(pipes[i-1][1]);
                    }
                    if (cmdparams[i+1][e][0] != NULL)
                    {
                        close(pipes[i][0]);
                        dup2(pipes[i][1], 1);
                        close(pipes[i][1]);
                    }

                    //printf("%s\n", cmdparams[i][e][0]);
                    execvp(cmdparams[i][e][0], cmdparams[i][e]);
                    printf("%s ", cmdparams[i][e][0]);
                    //perror("error executing child process");
                    exit(1);
                }
                else
                {
                    printf("process id = %d started.\n", ids[count]);
                    if (cmdparams[i-1][e][0] != NULL)
                    {
                        close(pipes[i-1][0]);
                        close(pipes[i-1][1]);
                    }
                    if (cmdparams[i+1][e][0] != NULL)
                    {
                         pipes[i-1][0] = pipes[i][0];
                         pipes[i-1][1] = pipes[i][0];
                    }

                    dup2(pipes[i][1], 0);
                }
                count++;
            }
            e++;
            //printf("here\n");
        }

        i++;
        e = 0;
    }

    /*int checkid;
    if ((checkid = fork()) == -1)   {perror("error creating child process"); exit(1);}
    if (checkid == 0)
    {
        while(1)
        {
            //std::cin.getline(input, 99);
            printf("%s\n", input);
        }
    }*/

    for (int i = 0; i < count; i++)
    {
        int childExitStatus;
        waitpid(ids[i], &childExitStatus, 0);
        printf("process id = %d ended with status = %d.\n", ids[i], childExitStatus);
    }




    printf("all exited.\n");


    //getchar();
    return 0;
}
//---------------------------------------------------------------------------

Он полностью рабочий, но мне осталось ещё реализовать следующие вещи:
  •   Завершение работы получив EOF (включая Ctrl+D от клавиатуры)
  •   Завершение работы если пользователь вводит слово/команду exit с клавиатуры
  •   Команду jobs которая показывала-бы все рабочие процессы (запущенные в этом шелле)
  •   Команду fg которая возвращает на последний запущенный процесс

Для меня очень туманна сама суть реализации всего этого.
Подскажите(подтолкните) пожалуйста как это можно реализовать?

На функции с именем начитаемся с parse не обращайте внимания (они очень громоздкие но работают).
Код

У меня тут главный процесс, после того как запустит все процессы переходит в ожидание их завершения и после завершения выходит.
    for (int i = 0; i < count; i++)
    {
        int childExitStatus;
        waitpid(ids[i], &childExitStatus, 0);
        printf("process id = %d ended with status = %d.\n", ids[i], childExitStatus);
    }


Незнаю совсем как например реализовать отлавливание EOF/Ctrl+D
Как мне следует это дело отлавливать?
Буду рад если кто-то хоть что-то подскажет
PM MAIL   Вверх
MAKCim
Дата 2.10.2010, 17:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 84
Всего: 207



Цитата(Ak47black @  2.10.2010,  16:40 Найти цитируемый пост)
Незнаю совсем как например реализовать отлавливание EOF/Ctrl+D

read возвращает в этом случае 0


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
Ak47black
Дата 2.10.2010, 17:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2205
Регистрация: 2.12.2005

Репутация: нет
Всего: 0



Хорошо, немного яснее стало.
А где мне-бы реализовать сам отлов вводимых команд?
Я могу например создать для этого дочерний процесс через fork, но как мне тогда из него остановить главный процесс со всеми дочерними?

Это сообщение отредактировал(а) Ak47black - 2.10.2010, 17:04
PM MAIL   Вверх
MAKCim
Дата 2.10.2010, 17:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 84
Всего: 207



что-то вы усложняете

в основном процессе принимайте ввод, парсите, создаете процессы для выполнения и дальше принимаете


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
Ak47black
Дата 2.10.2010, 18:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2205
Регистрация: 2.12.2005

Репутация: нет
Всего: 0



MAKCim, 
Вы правы. Мне тут действительно надо так делать.

А можно-ли как-то понять что запущенный процесс ничего не возвращает? (например sleep )

Это сообщение отредактировал(а) Ak47black - 2.10.2010, 18:54
PM MAIL   Вверх
MAKCim
Дата 2.10.2010, 19:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 84
Всего: 207



что вы имеете в виду под возвращением? вывод на stdout? 


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
Ak47black
Дата 2.10.2010, 21:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2205
Регистрация: 2.12.2005

Репутация: нет
Всего: 0



Да.
У меня проблема в том что getline (134 строка) по второму циклу проскальзывает (ничего не спрашивая пользователя выполняется например если ввести "sleep 2")
И я подозреваю что это из-за того что я делаю
dup2(pipes[i][1], 0); на 191 строке.
Вот такой код у меня на дынный момент
Код

//---------------------------------------------------------------------------

#pragma hdrstop

#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <netinet/in.h>
#include <resolv.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <iostream>
using namespace std;


void parseA(char* input);
void parseB(char* input);
void parseC(char* input);
void parseD(char* input);







char* cmdparams[20][20][20] = {NULL};
int block = 0;
int cmd = 0;
int param = 0;

void parseA(char* input)
{
    while (input[0] != 0)
    {
        cmd = 0;
        const char* delim = strchr(input, '|');
        if (delim)
        {
            int len = delim-input;
            char* subcmd = (char*)malloc(len);
            strncpy(subcmd, input, len);
            subcmd[len] = '\0';

            parseB(subcmd);
            block++;
            strcpy(input, delim+1);
        }
        else
        {
            parseB(input);
            return;
        }
    }
}

void parseB(char* input)
{
    while (input[0] != 0)
    {
        param = 0;
        char* delim = strchr(input, '&');
        if (delim)
        {
            int len = delim-input;
            char* subcmd = (char*)malloc(len);
            strncpy(subcmd, input, len);
            subcmd[len] = '\0';
            parseC(subcmd);
            cmd++;
            strcpy(input, delim+1);
        }
        else
        {
            parseC(input);
            return;
        }
    }
}

void parseC(char* input)
{
   while (input[0] == ' ') strcpy(input, input+1);
   while (input[strlen(input)-1] == ' ') input[strlen(input)-1] = '\0';

   while (input[0] != 0)
   {
        char* delim = strchr(input, ' ');
        if (delim)
        {
            int len = delim-input;
            char* subcmd = (char*)malloc(len);
            strncpy(subcmd, input, len);
            subcmd[len] = '\0';
            parseD(subcmd);
            param++;
            strcpy(input, delim+1);
        }
        else
        {
            parseD(input);
            return;
        }
   }
   
}

void parseD(char* input)
{
    cmdparams[block][cmd][param] = input;
}
//---------------------------------------------------------------------------




//---------------------------------------------------------------------------



int main(int argc, char* argv[])
{
    //char input[] = "ls -l | cut -c 1-20 | cut -c 1-1 \0";
    while (1)
    {    
        printf("start.\n");
        char input[255];
     memset(input, 0, 255);
        std::cin.getline(input, 255);
        printf("got.\n");
        if (input[0] == 0) {return 0;}
        parseA(input);
        printf("%s\n", input);

        int i = 0;
        int e = 0;
        int ids[20];
        int pipes[20][2];
        int count = 0;
        for (int i = 0; i < block; i++)
            pipe(pipes[i]);

        while (cmdparams[i][e][0] != NULL)
        {
            while (cmdparams[i][e][0] != NULL)
            {
                if (pipe(pipes[i]) == -1)    {perror("error creating pipe"); exit(1);}
                if (cmdparams[i][e][0] != NULL)
                {
                    if ((ids[count] = fork()) == -1)   {perror("error creating child process"); exit(1);}
                    if (ids[count] == 0)
                    {
                        if (cmdparams[i-1][e][0] != NULL)
                        {
                            dup2(pipes[i-1][0], 0);
                            close(pipes[i-1][0]);
                            close(pipes[i-1][1]);
                        }
                        if (cmdparams[i+1][e][0] != NULL)
                        {
                            close(pipes[i][0]);
                            dup2(pipes[i][1], 1);
                            close(pipes[i][1]);
                        }

                        //printf("%s\n", cmdparams[i][e][0]);
                        execvp(cmdparams[i][e][0], cmdparams[i][e]);
                        printf("%s ", cmdparams[i][e][0]);
                        //perror("error executing child process");
                        exit(1);
                    }
                    else
                    {
                        printf("process id = %d started.\n", ids[count]);
                        if (cmdparams[i-1][e][0] != NULL)
                        {
                            close(pipes[i-1][0]);
                            close(pipes[i-1][1]);
                        }
                        if (cmdparams[i+1][e][0] != NULL)
                        {
                            pipes[i-1][0] = pipes[i][0];
                            pipes[i-1][1] = pipes[i][0];
                        }

                        dup2(pipes[i][1], 0);
                    }
                    count++;
                }
                e++;
                //printf("here\n");
            }

            i++;
            e = 0;
        }
     printf("here.\n");
    }

    printf("exit.\n");
    return 0;
}
//---------------------------------------------------------------------------

/*
    for (int i = 0; i < count; i++)
    {
        int childExitStatus;
        waitpid(ids[i], &childExitStatus, 0);
        printf("process id = %d ended with status = %d.\n", ids[i], childExitStatus);
    }
*/


Это сообщение отредактировал(а) Ak47black - 2.10.2010, 21:05
PM MAIL   Вверх
Ak47black
Дата 3.10.2010, 15:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2205
Регистрация: 2.12.2005

Репутация: нет
Всего: 0



Никаких нету идей по этому поводу?  smile 
PM MAIL   Вверх
xvr
Дата 4.10.2010, 13:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 20
Всего: 223



У меня есть идея, что вы не отделили мух от котлет  smile 

Нормальный *nix shell умеет запускать команды в 2х режимах. Если в конце командной строки присутствует знак '&', то команда запускается в background'е. При этом stdin для нее направляется от /dev/null (реально там чуток не так, но в первом приближении можете считать именно так). Сама команда запускается в fork из шела, шел при этом продолжает вводить другие команды и исполнять (и отлавливать EOF на своем stdin).

Если же знака '&' нет, то команда запускается в forground'е. Шел на время ее выполнения блокируется (точнее отключается от своих потоков ввода и вывода) и ждет завершение запущенной команды.

PM MAIL   Вверх
Ak47black
Дата 4.10.2010, 22:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2205
Регистрация: 2.12.2005

Репутация: нет
Всего: 0



Знаете, Вы мне открыли глаза на это дело. Спасибо Вам огромное за ответ.
Завтра попробую всё это на свежую голову

Это сообщение отредактировал(а) Ak47black - 4.10.2010, 22:31
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С/С++: Программирование под Unix/Linux"
xvr
  • Проставьте несколько ключевых слов темы, чтобы её можно было легче найти.
  • Не забывайте пользоваться кнопкой "Код".
  • Вопросы мобильной разработки тут
  • Телепатов на форуме нет! Задавайте чёткий, конкретный и полный вопрос. Указывайте полностью ошибки компилятора и компоновщика.
  • Новое сообщение должно иметь прямое отношение к разделу форума. Флуд, флейм, оффтопик запрещены.
  • Категорически запрещается обсуждение вареза, "кряков", взлома программ и т.д.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, xvr.

 
 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Программирование под Unix/Linux | Следующая тема »


 




[ Время генерации скрипта: 0.0638 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.