Помогите советом как доделать shell

Тема в разделе "WASM.UNIX", создана пользователем nbyte, 2 окт 2010.

  1. nbyte

    nbyte New Member

    Публикаций:
    0
    Регистрация:
    27 май 2007
    Сообщения:
    161
    Здравствуйте.
    Вот такой у меня код вышел шелла
    Код (Text):
    1. //---------------------------------------------------------------------------
    2.  
    3. #pragma hdrstop
    4.  
    5. #include <fcntl.h>
    6. #include <string.h>
    7. #include <stdlib.h>
    8. #include <errno.h>
    9. #include <stdio.h>
    10. #include <netinet/in.h>
    11. #include <resolv.h>
    12. #include <sys/socket.h>
    13. #include <arpa/inet.h>
    14. #include <unistd.h>
    15. #include <sys/types.h>
    16. #include <sys/wait.h>
    17. #include <iostream>
    18. using namespace std;
    19.  
    20.  
    21. void parseA(char* input);
    22. void parseB(char* input);
    23. void parseC(char* input);
    24. void parseD(char* input);
    25.  
    26.  
    27.  
    28.  
    29.  
    30.  
    31.  
    32. char* cmdparams[20][20][20] = {NULL};
    33. int block = 0;
    34. int cmd = 0;
    35. int param = 0;
    36.  
    37. void parseA(char* input)
    38. {
    39.     while (input[0] != 0)
    40.     {
    41.         cmd = 0;
    42.         const char* delim = strchr(input, '|');
    43.         if (delim)
    44.         {
    45.             int len = delim-input;
    46.             char* subcmd = (char*)malloc(len);
    47.             strncpy(subcmd, input, len);
    48.             subcmd[len] = '\0';
    49.  
    50.             parseB(subcmd);
    51.             block++;
    52.             strcpy(input, delim+1);
    53.         }
    54.         else
    55.         {
    56.             parseB(input);
    57.             return;
    58.         }
    59.     }
    60. }
    61.  
    62. void parseB(char* input)
    63. {
    64.     while (input[0] != 0)
    65.     {
    66.         param = 0;
    67.         char* delim = strchr(input, '&');
    68.         if (delim)
    69.         {
    70.             int len = delim-input;
    71.             char* subcmd = (char*)malloc(len);
    72.             strncpy(subcmd, input, len);
    73.             subcmd[len] = '\0';
    74.             parseC(subcmd);
    75.             cmd++;
    76.             strcpy(input, delim+1);
    77.         }
    78.         else
    79.         {
    80.             parseC(input);
    81.             return;
    82.         }
    83.     }
    84. }
    85.  
    86. void parseC(char* input)
    87. {
    88.    while (input[0] == ' ') strcpy(input, input+1);
    89.    while (input[strlen(input)-1] == ' ') input[strlen(input)-1] = '\0';
    90.  
    91.    while (input[0] != 0)
    92.    {
    93.         char* delim = strchr(input, ' ');
    94.         if (delim)
    95.         {
    96.             int len = delim-input;
    97.             char* subcmd = (char*)malloc(len);
    98.             strncpy(subcmd, input, len);
    99.             subcmd[len] = '\0';
    100.             parseD(subcmd);
    101.             param++;
    102.             strcpy(input, delim+1);
    103.         }
    104.         else
    105.         {
    106.             parseD(input);
    107.             return;
    108.         }
    109.    }
    110.    
    111. }
    112.  
    113. void parseD(char* input)
    114. {
    115.     cmdparams[block][cmd][param] = input;
    116. }
    117. //---------------------------------------------------------------------------
    118.  
    119.  
    120.  
    121.  
    122. //---------------------------------------------------------------------------
    123.  
    124.  
    125.  
    126. int main(int argc, char* argv[])
    127. {
    128.     //char input[] = "ls -l | cut -c 1-20 | cut -c 1-1 \0";
    129.  
    130.     char input[] = "sleep 1 & sleep 5 \0";
    131.     //getline(cin, input);
    132.     parseA(input);
    133.     if (input[0] == 0) {perror("no params"); exit(1);}
    134.  
    135.     int i = 0;
    136.     int e = 0;
    137.     int ids[20];
    138.     int pipes[20][2];
    139.     int count = 0;
    140.     for (int i = 0; i < block; i++)
    141.         pipe(pipes[i]);
    142.  
    143.     while (cmdparams[i][e][0] != NULL)
    144.     {
    145.         while (cmdparams[i][e][0] != NULL)
    146.         {
    147.             if (pipe(pipes[i]) == -1)    {perror("error creating pipe"); exit(1);}
    148.             if (cmdparams[i][e][0] != NULL)
    149.             {
    150.                 if ((ids[count] = fork()) == -1)   {perror("error creating child process"); exit(1);}
    151.                 if (ids[count] == 0)
    152.                 {
    153.                     if (cmdparams[i-1][e][0] != NULL)
    154.                     {
    155.                         dup2(pipes[i-1][0], 0);
    156.                         close(pipes[i-1][0]);
    157.                         close(pipes[i-1][1]);
    158.                     }
    159.                     if (cmdparams[i+1][e][0] != NULL)
    160.                     {
    161.                         close(pipes[i][0]);
    162.                         dup2(pipes[i][1], 1);
    163.                         close(pipes[i][1]);
    164.                     }
    165.  
    166.                     //printf("%s\n", cmdparams[i][e][0]);
    167.                     execvp(cmdparams[i][e][0], cmdparams[i][e]);
    168.                     printf("%s ", cmdparams[i][e][0]);
    169.                     //perror("error executing child process");
    170.                     exit(1);
    171.                 }
    172.                 else
    173.                 {
    174.                     printf("process id = %d started.\n", ids[count]);
    175.                     if (cmdparams[i-1][e][0] != NULL)
    176.                     {
    177.                         close(pipes[i-1][0]);
    178.                         close(pipes[i-1][1]);
    179.                     }
    180.                     if (cmdparams[i+1][e][0] != NULL)
    181.                     {
    182.                          pipes[i-1][0] = pipes[i][0];
    183.                          pipes[i-1][1] = pipes[i][0];
    184.                     }
    185.  
    186.                     dup2(pipes[i][1], 0);
    187.                 }
    188.                 count++;
    189.             }
    190.             e++;
    191.             //printf("here\n");
    192.         }
    193.  
    194.         i++;
    195.         e = 0;
    196.     }
    197.  
    198.     /*int checkid;
    199.     if ((checkid = fork()) == -1)   {perror("error creating child process"); exit(1);}
    200.     if (checkid == 0)
    201.     {
    202.         while(1)
    203.         {
    204.             //std::cin.getline(input, 99);
    205.             printf("%s\n", input);
    206.         }
    207.     }*/
    208.  
    209.     for (int i = 0; i < count; i++)
    210.     {
    211.         int childExitStatus;
    212.         waitpid(ids[i], &childExitStatus, 0);
    213.         printf("process id = %d ended with status = %d.\n", ids[i], childExitStatus);
    214.     }
    215.  
    216.  
    217.  
    218.  
    219.     printf("all exited.\n");
    220.  
    221.  
    222.     //getchar();
    223.     return 0;
    224. }
    225. //---------------------------------------------------------------------------
    Он полностью рабочий, но мне осталось ещё реализовать следующие вещи:
    Завершение работы получив EOF (включая Ctrl+D от клавиатуры)
    Завершение работы если пользователь вводит слово/команду exit с клавиатуры
    Команду jobs которая показывала-бы все рабочие процессы (запущенные в этом шелле)
    Команду fg которая возвращает на последний запущенный процесс
    Для меня очень туманна сама суть реализации всего этого.
    Подскажите(подтолкните) пожалуйста как это можно реализовать?
     
  2. nbyte

    nbyte New Member

    Публикаций:
    0
    Регистрация:
    27 май 2007
    Сообщения:
    161
    На функции с именем начитаемся с parse не обращайте внимания (они очень грамозкие но работают).
     
  3. nbyte

    nbyte New Member

    Публикаций:
    0
    Регистрация:
    27 май 2007
    Сообщения:
    161
    У меня тут главный процесс, после того как запустит все процессы переходит в ожидание их завершения и после завершения выходит
    Код (Text):
    1.     for (int i = 0; i < count; i++)
    2.     {
    3.         int childExitStatus;
    4.         waitpid(ids[i], &childExitStatus, 0);
    5.         printf("process id = %d ended with status = %d.\n", ids[i], childExitStatus);
    6.     }
     
  4. nbyte

    nbyte New Member

    Публикаций:
    0
    Регистрация:
    27 май 2007
    Сообщения:
    161
    Незнаю как например реализовать отлавливание EOF/Ctrl+D
    Как мне следует это дело отлавливать?
     
  5. nbyte

    nbyte New Member

    Публикаций:
    0
    Регистрация:
    27 май 2007
    Сообщения:
    161
    Вообщем буду рад если кто-то хоть что-то подскажет
     
  6. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    в лабы мб?
     
  7. nbyte

    nbyte New Member

    Публикаций:
    0
    Регистрация:
    27 май 2007
    Сообщения:
    161
    В смысле? :)
     
  8. nbyte

    nbyte New Member

    Публикаций:
    0
    Регистрация:
    27 май 2007
    Сообщения:
    161
    Можно-ли как-то понять что запущенный процесс ничего не возвращает? (например sleep )
     
  9. nbyte

    nbyte New Member

    Публикаций:
    0
    Регистрация:
    27 май 2007
    Сообщения:
    161
    Как узнать что запущенный процесс ничего не возвращает в stdout?
     
  10. Mika0x65

    Mika0x65 New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2005
    Сообщения:
    1.384
    Не возвращает, в смысле, не пишет? Можно перенеправить его stdout к себе в файл и проверять, не написал ли чего. Но зачем это вообще надо?
     
  11. nbyte

    nbyte New Member

    Публикаций:
    0
    Регистрация:
    27 май 2007
    Сообщения:
    161
    У меня вот такой код
    Код (Text):
    1. //---------------------------------------------------------------------------
    2. #pragma hdrstop
    3. #include <fcntl.h>
    4. #include <string.h>
    5. #include <stdlib.h>
    6. #include <errno.h>
    7. #include <stdio.h>
    8. #include <netinet/in.h>
    9. #include <resolv.h>
    10. #include <sys/socket.h>
    11. #include <arpa/inet.h>
    12. #include <unistd.h>
    13. #include <sys/types.h>
    14. #include <sys/wait.h>
    15. #include <iostream>
    16. using namespace std;
    17. void parseA(char* input);
    18. void parseB(char* input);
    19. void parseC(char* input);
    20. void parseD(char* input);
    21. char* cmdparams[20][20][20] = {NULL};
    22. int block = 0;
    23. int cmd = 0;
    24. int param = 0;
    25. void parseA(char* input)
    26. {
    27.     while (input[0] != 0)
    28.     {
    29.         cmd = 0;
    30.         const char* delim = strchr(input, '|');
    31.         if (delim)
    32.         {
    33.             int len = delim-input;
    34.             char* subcmd = (char*)malloc(len);
    35.             strncpy(subcmd, input, len);
    36.             subcmd[len] = '\0';
    37.             parseB(subcmd);
    38.             block++;
    39.             strcpy(input, delim+1);
    40.         }
    41.         else
    42.         {
    43.             parseB(input);
    44.             return;
    45.         }
    46.     }
    47. }
    48. void parseB(char* input)
    49. {
    50.     while (input[0] != 0)
    51.     {
    52.         param = 0;
    53.         char* delim = strchr(input, '&');
    54.         if (delim)
    55.         {
    56.             int len = delim-input;
    57.             char* subcmd = (char*)malloc(len);
    58.             strncpy(subcmd, input, len);
    59.             subcmd[len] = '\0';
    60.             parseC(subcmd);
    61.             cmd++;
    62.             strcpy(input, delim+1);
    63.         }
    64.         else
    65.         {
    66.             parseC(input);
    67.             return;
    68.         }
    69.     }
    70. }
    71. void parseC(char* input)
    72. {
    73.    while (input[0] == ' ') strcpy(input, input+1);
    74.    while (input[strlen(input)-1] == ' ') input[strlen(input)-1] = '\0';
    75.    while (input[0] != 0)
    76.    {
    77.         char* delim = strchr(input, ' ');
    78.         if (delim)
    79.         {
    80.             int len = delim-input;
    81.             char* subcmd = (char*)malloc(len);
    82.             strncpy(subcmd, input, len);
    83.             subcmd[len] = '\0';
    84.             parseD(subcmd);
    85.             param++;
    86.             strcpy(input, delim+1);
    87.         }
    88.         else
    89.         {
    90.             parseD(input);
    91.             return;
    92.         }
    93.    }
    94.    
    95. }
    96. void parseD(char* input)
    97. {
    98.     cmdparams[block][cmd][param] = input;
    99. }
    100. //---------------------------------------------------------------------------
    101. //---------------------------------------------------------------------------
    102. int main(int argc, char* argv[])
    103. {
    104.     //char input[] = "ls -l | cut -c 1-20 | cut -c 1-1 \0";
    105.     while (1)
    106.     {    
    107.         printf("start.\n");
    108.         char input[255];
    109.      memset(input, 0, 255);
    110.         std::cin.getline(input, 255);
    111.         printf("got.\n");
    112.         if (input[0] == 0) {return 0;}
    113.         parseA(input);
    114.         printf("%s\n", input);
    115.         int i = 0;
    116.         int e = 0;
    117.         int ids[20];
    118.         int pipes[20][2];
    119.         int count = 0;
    120.         for (int i = 0; i < block; i++)
    121.             pipe(pipes[i]);
    122.         while (cmdparams[i][e][0] != NULL)
    123.         {
    124.             while (cmdparams[i][e][0] != NULL)
    125.             {
    126.                 if (pipe(pipes[i]) == -1)    {perror("error creating pipe"); exit(1);}
    127.                 if (cmdparams[i][e][0] != NULL)
    128.                 {
    129.                     if ((ids[count] = fork()) == -1)   {perror("error creating child process"); exit(1);}
    130.                     if (ids[count] == 0)
    131.                     {
    132.                         if (cmdparams[i-1][e][0] != NULL)
    133.                         {
    134.                             dup2(pipes[i-1][0], 0);
    135.                             close(pipes[i-1][0]);
    136.                             close(pipes[i-1][1]);
    137.                         }
    138.                         if (cmdparams[i+1][e][0] != NULL)
    139.                         {
    140.                             close(pipes[i][0]);
    141.                             dup2(pipes[i][1], 1);
    142.                             close(pipes[i][1]);
    143.                         }
    144.                         //printf("%s\n", cmdparams[i][e][0]);
    145.                         execvp(cmdparams[i][e][0], cmdparams[i][e]);
    146.                         printf("%s ", cmdparams[i][e][0]);
    147.                         //perror("error executing child process");
    148.                         exit(1);
    149.                     }
    150.                     else
    151.                     {
    152.                         printf("process id = %d started.\n", ids[count]);
    153.                         if (cmdparams[i-1][e][0] != NULL)
    154.                         {
    155.                             close(pipes[i-1][0]);
    156.                             close(pipes[i-1][1]);
    157.                         }
    158.                         if (cmdparams[i+1][e][0] != NULL)
    159.                         {
    160.                             pipes[i-1][0] = pipes[i][0];
    161.                             pipes[i-1][1] = pipes[i][0];
    162.                         }
    163.                         dup2(pipes[i][1], 0);
    164.                     }
    165.                     count++;
    166.                 }
    167.                 e++;
    168.                 //printf("here\n");
    169.             }
    170.             i++;
    171.             e = 0;
    172.         }
    173.      printf("here.\n");
    174.     }
    175.     printf("exit.\n");
    176.     return 0;
    177. }
    178. //---------------------------------------------------------------------------
    179. /*
    180.     for (int i = 0; i < count; i++)
    181.     {
    182.         int childExitStatus;
    183.         waitpid(ids[i], &childExitStatus, 0);
    184.         printf("process id = %d ended with status = %d.\n", ids[i], childExitStatus);
    185.     }
    186. */
    Проблема в том что getline (134 строка) по второму циклу проскальзывает (ничего не спрашивая пользователя выполняется например если ввести "sleep 2")
    И я подозреваю что это из-за того что я делаю
    dup2(pipes[1], 0); на 191 строке.
    Тоесть sleep 2 ничего не возврашает, и это "сливается" в getline
     
  12. Mika0x65

    Mika0x65 New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2005
    Сообщения:
    1.384
    Если честно, просматривать всю простынь кода у меня сейчас ни сил, ни времени. Но в целом суть довольно проста: запускаем процесс, если он фоновый, то просто ждем от него сигнал SIGCHILD, чтобы сделать wait, когда помрет. Если не фоновый, то сразу делаем wait и ждем завершения. Обработка каналов -- это отдельная песня вообще.