Advertisement
romko11l

Untitled

Nov 30th, 2019
121
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 25.13 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <sys/types.h>
  4. #include <sys/wait.h>
  5. #include <unistd.h>
  6. #include <string.h>
  7. #include <sys/stat.h>
  8. #include <fcntl.h>
  9. #include <signal.h>
  10.  
  11.  
  12. const int n = 5; // на сколько элементов выделится память (символов) при заполнении строки (read_line) (не делать меньше 3)
  13. const int m = 5; // на сколько элементов (символов) выделится память в функции strtok
  14. const int t = 5; // на сколько строк выделится память в функции parcer
  15.  
  16. void freedom (char **base)
  17. {
  18.     int pos=0;
  19.     while (base[pos])
  20.     {
  21.         free(base[pos]);
  22.         pos++;
  23.     }
  24.     free(base);
  25. }
  26.  
  27. void Sighndlr ()
  28. {
  29.     printf("Не удалось запустить программу\n");
  30. }
  31.  
  32. //чтение одной строки из заданного ввода
  33. char *read_line(int fd, int *check) // в check-е вернется 1, если в строке обнаружен EOF
  34. {
  35.     int pos=0, size;
  36.     char *str, *temp, c, k; //к c переименовать
  37.     size=n;
  38.     str=malloc(sizeof(char)*size);
  39.     *check=0;
  40.    
  41.     if (!str)
  42.     {
  43.         printf("memory allocation error\n");
  44.         exit(1);
  45.     }
  46.    
  47.     while (1)
  48.     {
  49.         k=read(fd,&c,sizeof(char));
  50.         if ((k==0)||(c=='\n'))
  51.         {
  52.             str[pos]='\0';
  53.             if (k==0)
  54.             {
  55.                 *check=1;
  56.             }
  57.             return str;
  58.         }
  59.         else
  60.         {
  61.             str[pos]=c;
  62.             pos++;
  63.         }
  64.    
  65.         if (pos==size)
  66.         {
  67.             size=size+n;
  68.             temp=str;
  69.             str=realloc(str,size*sizeof(char));
  70.             if (!str)
  71.             {
  72.                 free(temp);
  73.                 printf("memory allocation error\n");
  74.                 exit(1);
  75.             }
  76.         }
  77.     }
  78.    
  79. }
  80.  
  81. //вычленение лексем из строки (выводит по лексеме в виде полноценной строки)
  82. char *mystrtok (char *line, int *check, int *num) //вернет 1 в случае нахождения конца строки
  83. {
  84.     int size, pos=0, hpos=0, pos1, hpos1;
  85.     char *str, *temp;
  86.     size=m;
  87.     str=malloc(sizeof(char)*size);
  88.     if (!str)
  89.     {
  90.         printf("memory allocation error\n");
  91.         *check=2;
  92.         free(str);
  93.         return NULL;
  94.     }
  95.    
  96.     while (1)
  97.     {
  98.         // Обработка кавычек
  99.         if (line[pos]=='"') //константы //енам
  100.         {
  101.             pos1=pos+1;
  102.             hpos1=hpos;
  103.             while (1)
  104.             {
  105.                 if (line[pos1]=='"')
  106.                 {
  107.                     hpos=hpos1;
  108.                     pos=pos1+1;
  109.                     break;
  110.                 }
  111.                 if ((line[pos1]==EOF)||(line[pos1]=='\0'))
  112.                 {
  113.                     break; // не найдено парной кавычки -> кавычка должна считаться как обычный символ
  114.                 }
  115.                 str[hpos1]=line[pos1];
  116.                 hpos1++;
  117.                 pos1++;
  118.                 if (hpos1==size)
  119.                 {
  120.                     temp=str;
  121.                     size=size+m;
  122.                     str=realloc(str,size*sizeof(char));
  123.                     if (!str)
  124.                     {
  125.                         free(temp);
  126.                         printf("memory allocation error\n");
  127.                         *check=2;
  128.                         return NULL;
  129.                     }
  130.                 }
  131.             }
  132.         }
  133.         // Обработка иных случаев
  134.         if (line[pos]==' ')
  135.         {
  136.             if (hpos==0)
  137.             {
  138.                 pos++;
  139.             }
  140.             else
  141.             {
  142.                 str[hpos]='\0';
  143.                 *check=0;
  144.                 *num=pos; // чтобы в следующий раз отправить в эту функцию другую строку
  145.                 return str;
  146.                
  147.             }
  148.         }
  149.         else
  150.         {
  151.             if (line[pos]=='\0')
  152.             {
  153.                 if (hpos==0)
  154.                 {
  155.                     *check=1;
  156.                     free(str);
  157.                     return NULL;
  158.                 }
  159.                 else
  160.                 {
  161.                     str[hpos]='\0';
  162.                     *check=1;
  163.                     return str;
  164.                 }
  165.             }
  166.             else // обнаружен элемент, который можно записать в строку
  167.             {
  168.                 // Обрабатываем спецсимволы
  169.                 if ((line[pos]=='|')||(line[pos]=='&')||(line[pos]=='>')||(line[pos]=='<')||(line[pos]==';')||(line[pos]==')')||(line[pos]=='('))
  170.                 {
  171.                     if (hpos>0) //до этого уже сформирована строка
  172.                     {
  173.                         str[hpos]='\0';
  174.                         *check=0;
  175.                         *num=pos;
  176.                         return str;
  177.                     }
  178.                     else // строка еще не сформирована (hpos==0)
  179.                     {
  180.                         // |
  181.                         if (line[pos]=='|')
  182.                         {
  183.                             if (line[pos+1]=='|')
  184.                             {
  185.                                 str[0]='|';
  186.                                 str[1]='|';
  187.                                 str[2]='\0';
  188.                                 *check=0;
  189.                                 *num=pos+2;
  190.                                 return str;
  191.                             }
  192.                             else
  193.                             {
  194.                                 str[0]='|';
  195.                                 str[1]='\0';
  196.                                 *check=0;
  197.                                 *num=pos+1;
  198.                                 return str;
  199.                             }
  200.                         }
  201.                         // &
  202.                         if (line[pos]=='&')
  203.                         {
  204.                             if (line[pos+1]=='&')
  205.                             {
  206.                                 str[0]='&';
  207.                                 str[1]='&';
  208.                                 str[2]='\0';
  209.                                 *check=0;
  210.                                 *num=pos+2;
  211.                                 return str;
  212.                             }
  213.                             else
  214.                             {
  215.                                 str[0]='&';
  216.                                 str[1]='\0';
  217.                                 *check=0;
  218.                                 *num=pos+1;
  219.                                 return str;
  220.                             }
  221.                         }
  222.                         // >
  223.                         if (line[pos]=='>')
  224.                         {
  225.                             if (line[pos+1]=='>')
  226.                             {
  227.                                 str[0]='>';
  228.                                 str[1]='>';
  229.                                 str[2]='\0';
  230.                                 *check=0;
  231.                                 *num=pos+2;
  232.                                 return str;
  233.                             }
  234.                             else
  235.                             {
  236.                                 str[0]='>';
  237.                                 str[1]='\0';
  238.                                 *check=0;
  239.                                 *num=pos+1;
  240.                                 return str;
  241.                             }
  242.                         }
  243.                         // <
  244.                         if (line[pos]=='<')
  245.                         {
  246.                             str[0]='<';
  247.                             str[1]='\0';
  248.                             *check=0;
  249.                             *num=pos+1;
  250.                             return str;
  251.                         }
  252.                         // ;
  253.                         if (line[pos]==';')
  254.                         {
  255.                             str[0]=';';
  256.                             str[1]='\0';
  257.                             *check=0;
  258.                             *num=pos+1;
  259.                             return str;
  260.                         }
  261.                         // )
  262.                         if (line[pos]==')')
  263.                         {
  264.                             str[0]=')';
  265.                             str[1]='\0';
  266.                             *check=0;
  267.                             *num=pos+1;
  268.                             return str;
  269.                         }
  270.                         // (
  271.                         if (line[pos]=='(')
  272.                         {
  273.                             str[0]='(';
  274.                             str[1]='\0';
  275.                             *check=0;
  276.                             *num=pos+1;
  277.                             return str;
  278.                         }
  279.                     }
  280.                 }
  281.                 //Если встречен обычный символ
  282.                 str[hpos]=line[pos];
  283.                 hpos++;
  284.                 pos++;
  285.                 if (hpos==size)
  286.                 {
  287.                     temp=str;
  288.                     size=size+m;
  289.                     str=realloc(str,size*sizeof(char));
  290.                     if (!str)
  291.                     {
  292.                         free(temp);
  293.                         printf("memory allocation error\n");
  294.                         *check=2;
  295.                         return NULL;
  296.                     }
  297.                 }
  298.             }
  299.         }
  300.        
  301.     }
  302. }
  303.  
  304. // разбитие строки на лексемы
  305. char **parcer (char *line) // последний элемент массива всегда будет иметь значение NULL
  306. {
  307.     int check, pos=0, size=0, strpos=0, hstrpos=0;
  308.     char **base, **temp;
  309.    
  310.     size=t;
  311.     base=malloc(sizeof(char *)*size);
  312.     if (!base)
  313.     {
  314.         printf("memory allocation error\n");
  315.         free(line);
  316.         exit(1);
  317.     }
  318.    
  319.     while(1)
  320.     {
  321.         base[pos]=mystrtok(line+strpos, &check, &hstrpos);
  322.         if (check==2)
  323.         {
  324.             base[pos]=NULL;
  325.             freedom(base);
  326.             exit(1);
  327.         }
  328.         if (check==1)
  329.         {
  330.             if (!base[pos]) // вернулась NULL - парсинг строки завершен
  331.             {
  332.                 return base; //может быть даже такое, что первый элемент этого массива - NULL
  333.             }
  334.             else // вернулась не пустая строка, но обнаружен конец основной строки
  335.             {
  336.                 pos++;
  337.                 if (pos==size)
  338.                 {
  339.                     size=size+1;
  340.                     temp=base;
  341.                     base=realloc(base,size*sizeof(char *));
  342.                     if (!base)
  343.                     {
  344.                         free(temp[pos-1]); // т.к. на новый pos места уже нет
  345.                         temp[pos-1]=NULL;
  346.                         freedom(base);
  347.                         exit(1);
  348.                     }
  349.                 }
  350.                 base[pos]=NULL;
  351.                 return base;
  352.             }
  353.         }
  354.         if (check==0)
  355.         {
  356.             strpos+=hstrpos;
  357.             pos++;
  358.             if (pos==size)
  359.             {
  360.                 size=size+t;
  361.                 temp=base;
  362.                 base=realloc(base,size*sizeof(char *));
  363.                 if (!base)
  364.                 {
  365.                     free(temp[pos-1]); // т.к. на новый pos места уже нет
  366.                     temp[pos-1]=NULL;
  367.                     freedom(base);
  368.                     exit(1);
  369.                 }
  370.             }
  371.         }
  372.     }
  373. }
  374.  
  375. // функция смены текущей директории
  376. int cd (char *str) // проверка на корректность количества аргументов команды cd производится раньше
  377. {
  378.     int k;
  379.     if (str==NULL) //значит пользователю надо перейти в домашний каталог
  380.     {
  381.         k=chdir(getenv("HOME"));
  382.         if (k==-1)
  383.         {
  384.             printf ("В указанный каталог перейти не удалось\n");
  385.         }
  386.         return k;
  387.     }
  388.     else
  389.     {
  390.         k=chdir(str);
  391.         if (k==-1)
  392.         {
  393.             printf ("В указанный каталог перейти не удалось\n");
  394.         }
  395.         return k;
  396.     }
  397. }
  398.  
  399. //используется в конвейере, осуществляя непосредственно создание нового процесса и замену тела
  400. int function_call (char **base, int fd[2], int flag, int *key) // вернет -1 в случае неудачного fork, -2  в случае неудачного exec, -3 в случае пустой команды
  401. {   // flag==1 говорит о том, что подан последний процесс из конвейера
  402.     // base представляет из себя массив строк, заканчивающийся NULL - ссылкой
  403.     // в key возвращаем pid сыновнего процесса
  404.     int a;
  405.     if (base[0]==NULL)
  406.     {
  407.         dup2(fd[0],0);
  408.         close(fd[0]);
  409.         close(fd[1]);
  410.         return -3;
  411.     }
  412.     a=fork();
  413.     if (a==-1)
  414.     {
  415.         printf("Не удалось породить процесс\n");
  416.         *key=-1;
  417.         return (-1);
  418.     }
  419.     if (a>0)
  420.     {
  421.         dup2(fd[0],0);
  422.         close(fd[0]);
  423.         close(fd[1]);
  424.         *key=a;
  425.     }
  426.     else
  427.     {
  428.         if (flag!=1)
  429.         {
  430.             dup2(fd[1],1);
  431.         }
  432.         close(fd[1]);
  433.         close(fd[0]);
  434.         a=execvp(base[0],base);
  435.         if (a==-1)
  436.         {
  437.             //printf("Не удалось запустить программу - %s\n",base[0]);
  438.             kill(getppid(),SIGUSR1);
  439.             return -2;
  440.         }
  441.     }
  442.     return 0;
  443. }
  444.  
  445. void all_str_output (char **base)
  446. {
  447.     int pos=0;
  448.     while ((base[pos]))
  449.     {
  450.         printf("%s\n",base[pos]);
  451.         pos++;
  452.     }
  453. }
  454.  
  455. //конвейер
  456. int pipeline (char** base, int bcheck, int *transit) // если bcheck==1 - то вызываемый процесс фоновый (не нужно восстанавливать реакцию на SIGINT)
  457. {   // transit - неименованный канал, ведущий к logic и использующийся для передачи возвращённого значения
  458.     int len=0, i=0, j=0, fd[2], k, writeintransit=1, key;
  459.     char **lastinstr, *str;
  460.     if ((base[0]!=NULL)&&(strcmp(base[0],"cd")==0))
  461.     {
  462.         if ((base[1]!=NULL)&&(base[2]!=NULL)) //ошибки не случится, т.к. при false в первом условии проверки второго не осуществиться
  463.         {
  464.             printf("cd: Некорректное число аргументов\n");
  465.             writeintransit=1;
  466.             write(transit[1], &writeintransit, sizeof(int));
  467.         }
  468.         else
  469.         {
  470.             writeintransit=cd(base[1]);
  471.             write(transit[1], &writeintransit, sizeof(int));
  472.         }
  473.         return 0;
  474.     }
  475.     k=fork();
  476.     if (k==-1)
  477.     {
  478.         printf("Породить процесс не удалось\n");
  479.         writeintransit=1;
  480.         write(transit[1], &writeintransit, sizeof(int));
  481.         return -1;
  482.     }
  483.     if (k==0)
  484.     {
  485.         if (bcheck!=1)
  486.         {
  487.             signal(SIGINT,SIG_DFL);
  488.         }
  489.         lastinstr=base;
  490.         while (base[i])
  491.         {
  492.             if (strcmp(base[i],"|")==0)
  493.             {
  494.                 len++;
  495.             }
  496.             i++;
  497.         }
  498.         j=0;
  499.         i=0;
  500.         while (i<len)
  501.         {
  502.             while (strcmp(base[j],"|")!=0)
  503.             {
  504.                 j++;
  505.             }
  506.             i++;
  507.             j++;
  508.             k=pipe(fd);
  509.             if (k==-1)
  510.             {
  511.                 printf("Не удалось установить связь между процессами конвейера\n");
  512.                 writeintransit=1; // т.к. конвейер построился некорректно
  513.                 write(transit[1], &writeintransit, sizeof(int));
  514.                 return -2;
  515.                 // тут еще надо подумать
  516.             }
  517.             str=base[j-1];
  518.             base[j-1]=NULL;
  519.             k=function_call(lastinstr, fd, 0, &key);
  520.             base[j-1]=str;
  521.             lastinstr=base+j;
  522.             if (k==-2) // возврат в теле сыновнего процесса
  523.             {
  524.                 return -2;
  525.             }
  526.             if (k==-1)
  527.             {
  528.                 while(wait(NULL)!=-1);
  529.                 writeintransit=1; // т.к. конвейер построился некорректно
  530.                 write(transit[1], &writeintransit, sizeof(int));
  531.                 return -2;
  532.             }
  533.             // k = 0 - всё хорошо
  534.         }
  535.         // на момент выхода из цикла не вызвана последняя программа из конвейера
  536.         k=pipe(fd);
  537.         if (k==-1)
  538.         {
  539.             printf("Не удалось установить связь между процессами конвейера\n");
  540.             writeintransit=1; // т.к. конвейер построился некорректно
  541.             write(transit[1], &writeintransit, sizeof(int));
  542.             return -2;
  543.             // тут еще надо подумать
  544.         }
  545.         k=function_call(lastinstr, fd, 1, &key);
  546.         if (k==-3) // последняя команда - пустая
  547.         {
  548.             writeintransit=1;
  549.             write(transit[1], &writeintransit, sizeof(int));
  550.             while(wait(NULL)!=-1);
  551.             return -2;
  552.         }
  553.         if (k==-2) // возврат в теле сыновнего процесса
  554.         {
  555.             return -2;
  556.         }
  557.         waitpid(key, &writeintransit, 0);
  558.         write(transit[1], &writeintransit, sizeof(int));
  559.         while(wait(NULL)!=-1);
  560.         return -2;
  561.     }
  562.     // тут может оказаться только процесс-родитель
  563.     wait(NULL);
  564.     return 0;
  565. }
  566.  
  567. // обработка перенаправлений
  568. int redirection (char **base, int bcheck, int *transit) // требуем, чтобы перенаправления были последними
  569. {   // если bcheck==1 - то вызываемый процесс фоновый (не нужно восстанавливать реакцию на SIGINT)
  570.     int len=0,fdrd,fdwr,hfd1,hfd2,checkrd=0,checkwr=0,res=0;
  571.     char *str;
  572.     while (base[len]) // кол-во переданных слов
  573.     {
  574.         len++;
  575.     }
  576.     hfd1=dup(1);
  577.     hfd2=dup(0);
  578.     if ((len>=4)&&(strcmp(base[len-2],">>")==0)&&(strcmp(base[len-4],">")==0)&&(strcmp(base[len-3],base[len-1])==0))
  579.     {
  580.         fdwr=open(base[len-1], O_CREAT | O_TRUNC | O_WRONLY | O_EXCL, 0666);
  581.         if (fdwr==-1)
  582.         {
  583.             fdwr=open(base[len-1], O_TRUNC | O_WRONLY); // возможно, файл уже существует
  584.             if (fdwr==-1)
  585.             {
  586.                 printf("Перенаправление вывода организовать не удалось\n");
  587.                 goto jmp;
  588.             }
  589.         }
  590.         checkwr=1;
  591.         dup2(fdwr,1);
  592.         str=base[len-4];
  593.         base[len-4]=NULL;
  594.         res=pipeline(base,bcheck,transit);
  595.         base[len-4]=str;
  596.         goto jmp;
  597.     }
  598.     if ((len>=4)&&(strcmp(base[len-2],">>")==0)&&(strcmp(base[len-4],"<")==0)&&(strcmp(base[len-3],base[len-1])==0))
  599.     {
  600.         printf("Недопустимая конструкция (входной и выходной файлы совпадают)\n");
  601.         goto jmp;
  602.     }
  603.     if ((len>=4)&&(strcmp(base[len-2],">")==0)&&(strcmp(base[len-4],"<")==0)&&(strcmp(base[len-3],base[len-1])==0))
  604.     {
  605.         printf("Недопустимая конструкция (входной и выходной файлы совпадают)\n");
  606.         goto jmp;
  607.     }
  608.     if ((len>=4)&&(strcmp(base[len-2],"<")==0)&&(strcmp(base[len-4],">")==0)&&(strcmp(base[len-3],base[len-1])==0))
  609.     {
  610.         printf("Недопустимая конструкция (входной и выходной файлы совпадают)\n");
  611.         goto jmp;
  612.     }
  613.     if ((len>=4)&&(strcmp(base[len-2],"<")==0)&&(strcmp(base[len-4],">>")==0)&&(strcmp(base[len-3],base[len-1])==0))
  614.     {
  615.         printf("Недопустимая конструкция (входной и выходной файлы совпадают)\n");
  616.         goto jmp;
  617.     }
  618.     if (len>=2) // потому что ситуация подачи на ввод, например >> text - корректна
  619.     {
  620.         if (strcmp(base[len-2],">")==0)
  621.         {
  622.             fdwr=open(base[len-1], O_CREAT | O_TRUNC | O_WRONLY | O_EXCL, 0666);
  623.             if (fdwr==-1)
  624.             {
  625.                 fdwr=open(base[len-1], O_TRUNC | O_WRONLY); // возможно, файл уже существует
  626.                 if (fdwr==-1)
  627.                 {
  628.                     printf("Перенаправление вывода организовать не удалось\n");
  629.                     goto jmp;
  630.                 }
  631.             }
  632.             checkwr=1;
  633.             dup2(fdwr,1);
  634.         }
  635.         if (strcmp(base[len-2],">>")==0)
  636.         {
  637.             fdwr=open(base[len-1], O_CREAT | O_APPEND | O_WRONLY | O_EXCL, 0666);
  638.             if (fdwr==-1)
  639.             {
  640.                 fdwr=open(base[len-1], O_APPEND| O_WRONLY);
  641.                 if (fdwr==-1)
  642.                 {
  643.                     printf("Перенаправление вывода организовать не удалось\n");
  644.                     goto jmp;
  645.                 }
  646.             }
  647.             checkwr=1;
  648.             dup2(fdwr,1);
  649.         }
  650.         if (strcmp(base[len-2],"<")==0)
  651.         {
  652.             fdrd=open(base[len-1], O_RDONLY);
  653.             if (fdrd==-1)
  654.             {
  655.                 printf("Перенаправление ввода организовать не удалось\n");
  656.                 goto jmp;
  657.             }
  658.             checkrd=1;
  659.             dup2(fdrd,0);
  660.         }
  661.         if (len>=4)
  662.         {
  663.             if ((checkrd==1)||(checkwr==1))
  664.             {
  665.                 if ((checkrd==1)&&(strcmp(base[len-4],">")==0))
  666.                 {
  667.                     fdwr=open(base[len-3], O_CREAT | O_TRUNC | O_WRONLY | O_EXCL, 0666);
  668.                     if (fdwr==-1)
  669.                     {
  670.                         fdwr=open(base[len-3], O_TRUNC | O_WRONLY);
  671.                         if (fdwr==-1)
  672.                         {
  673.                             printf("Перенаправление вывода организовать не удалось\n");
  674.                             goto jmp;
  675.                         }
  676.                     }
  677.                     checkwr=1;
  678.                     dup2(fdwr,1);
  679.                 }
  680.                 if ((checkrd==1)&&(strcmp(base[len-4],">>")==0))
  681.                 {
  682.                     fdwr=open(base[len-3], O_CREAT | O_APPEND | O_WRONLY | O_EXCL, 0666);
  683.                     if (fdwr==-1)
  684.                     {
  685.                         fdwr=open(base[len-3], O_APPEND| O_WRONLY);
  686.                         if (fdwr==-1)
  687.                         {
  688.                             printf("Перенаправление вывода организовать не удалось\n");
  689.                             goto jmp;
  690.                         }
  691.                     }
  692.                     checkwr=1;
  693.                     dup2(fdwr,1);
  694.                 }
  695.                 if ((checkwr==1)&&(strcmp(base[len-4],"<")==0))
  696.                 {
  697.                     fdrd=open(base[len-3], O_RDONLY);
  698.                     if (fdrd==-1)
  699.                     {
  700.                         printf("Перенаправление ввода организовать не удалось\n");
  701.                         goto jmp;
  702.                     }
  703.                     checkrd=1;
  704.                     dup2(fdrd,0);
  705.                 }
  706.                 if ((checkwr==1)&&(checkrd==1))
  707.                 {
  708.                     str=base[len-4];
  709.                     base[len-4]=NULL;
  710.                     res=pipeline(base,bcheck,transit);
  711.                     base[len-4]=str;
  712.                 }
  713.                 else
  714.                 {
  715.                     str=base[len-2];
  716.                     base[len-2]=NULL;
  717.                     res=pipeline(base,bcheck,transit);
  718.                     base[len-2]=str;
  719.                 }
  720.             }
  721.             else
  722.             {
  723.                 res=pipeline(base,bcheck,transit);
  724.             }
  725.         }
  726.         else // меньше 4 слов в команде
  727.         {
  728.             if ((checkrd==1)||(checkwr==1)) // только одно из перенаправлений имело место
  729.             {
  730.                 str=base[len-2];
  731.                 base[len-2]=NULL;
  732.                 res=pipeline(base,bcheck,transit);
  733.                 base[len-2]=str;
  734.             }
  735.             else // перенаправлений не было
  736.             {
  737.                 res=pipeline(base,bcheck,transit);
  738.             }
  739.         }
  740.     }
  741.     else // меньше 2 слов в команде
  742.     {
  743.         res=pipeline(base,bcheck,transit);
  744.     }
  745.     jmp:
  746.     if (checkwr==1)
  747.     {
  748.         dup2(hfd1,1);;
  749.         close(fdwr);
  750.     }
  751.     if (checkrd==1)
  752.     {
  753.         dup2(hfd2,0);
  754.         close(fdrd);
  755.     }
  756.     close(hfd1);
  757.     close(hfd2);
  758.     return res;
  759. }
  760.  
  761. // обработчик логики && и ||
  762. int logic(char **base, int bcheck)
  763. {
  764.     int lastexit=0; // тут хранится код возврата последнего выполнившегося процесса (и cd)
  765.     int transit[2]; // проведенный до pipeline канал
  766.     int i=0,a;
  767.     char str1[3]="||", str2[3]="&&", **lastcom, *temp;
  768.     char *lastlogic; //в комбинации с lastexit всегда должна дать выполниться первой команде
  769.     lastlogic=str2;
  770.     while (base[i]!=NULL)
  771.     {
  772.         if ((strcmp(base[i],str1)==0)||(strcmp(base[i],str2)==0))
  773.         {
  774.             if  (i==0)
  775.             {
  776.                 printf("Некорректный синтаксис\n");
  777.                 return 0;
  778.             }
  779.             if ((i>0)&&(strcmp(base[i-1],str1)==0))
  780.             {
  781.                 printf("Некорректный синтаксис\n");
  782.                 return 0;
  783.             }
  784.             if ((i>0)&&(strcmp(base[i-1],str2)==0))
  785.             {
  786.                 printf("Некорректный синтаксис\n");
  787.                 return 0;
  788.             }
  789.         }
  790.         i++;
  791.     }
  792.     if ((i>0)&&((strcmp(base[i-1],"&&")==0)||(strcmp(base[i-1],"||")==0))) // последняя лексема - &&, либо ||
  793.     {
  794.         printf("Некорректный синтаксис\n");
  795.         return 0;
  796.     }
  797.     i=0;
  798.     pipe(transit);
  799.     lastcom=base;
  800.     while (base[i]!=NULL)
  801.     {
  802.         if (strcmp(base[i],str1)==0)
  803.         {
  804.             if (((lastexit==0)&&(strcmp(lastlogic,str2)==0))||((lastexit!=0)&&(strcmp(lastlogic,str1)==0)))
  805.             {
  806.                 temp=base[i]; // очень важно делать именно так (иначе портится память)
  807.                 base[i]=NULL;
  808.                 a=redirection(lastcom,bcheck,transit);
  809.                 base[i]=temp;
  810.                 if (a!=0) // возврат в случае ошибки fork , либо в теле сыновнего процесса
  811.                 {
  812.                     return -2;
  813.                 }
  814.                 read(transit[0],&lastexit,sizeof(int)); // читаем, что сюда записалось в pipeline
  815.             }
  816.             lastcom=base+i+1;
  817.             lastlogic=str1;
  818.         }
  819.         if (strcmp(base[i],str2)==0)
  820.         {
  821.             if (((lastexit==0)&&(strcmp(lastlogic,str2)==0))||((lastexit!=0)&&(strcmp(lastlogic,str1)==0)))
  822.             {
  823.                 temp=base[i];
  824.                 base[i]=NULL;
  825.                 a=redirection(lastcom,bcheck,transit);
  826.                 base[i]=temp;
  827.                 if (a!=0) // возврат в случае ошибки fork , либо в теле сыновнего процесса
  828.                 {
  829.                     close(transit[0]);
  830.                     close(transit[1]);
  831.                     return -2;
  832.                 }
  833.                 read(transit[0],&lastexit,sizeof(int)); // читаем, что сюда записалось в pipeline
  834.             }
  835.             lastcom=base+i+1;
  836.             lastlogic=str2;
  837.         }
  838.         i++;
  839.     }
  840.     // на данный момент не обработана последняя команда
  841.     if (((lastexit==0)&&(strcmp(lastlogic,str2)==0))||((lastexit!=0)&&(strcmp(lastlogic,str1)==0)))
  842.     {
  843.         a=redirection(lastcom,bcheck,transit);
  844.         if (a!=0) // возврат в случае ошибки fork , либо в теле сыновнего процесса
  845.         {
  846.             close(transit[0]);
  847.             close(transit[1]);
  848.             return -2;
  849.         }
  850.     }
  851.     close(transit[0]);
  852.     close(transit[1]);
  853.     return 0;
  854. }
  855.  
  856.  
  857. // обработчик фонового режима (и ;)
  858. int background (char **base)
  859. {
  860.     char **lastcom, *temp;
  861.     int i=0, a, fd[2];
  862.     lastcom=base;
  863.     // проверка на корректность расстановки ; (она не может быть первым символом и стоять рядом с другой ;)
  864.     if ((base[i]!=NULL)&&(strcmp(base[i],";")==0))
  865.     {
  866.         printf("Некорректный синтаксис\n");
  867.         return 0;
  868.     }
  869.     while (base[i]!=NULL)
  870.     {
  871.         if (strcmp(base[i],";")==0)
  872.         {
  873.             if ((i>0)&&(strcmp(base[i-1],";")))
  874.             {
  875.                 printf("Некорректный синтаксис\n");
  876.                 return 0;
  877.             }
  878.         }
  879.         i++;
  880.     }
  881.     i=0;
  882.     jmp://булевые переменные  (???)
  883.     while ((base[i]!=NULL)&&(strcmp(base[i],"&")!=0)&&(strcmp(base[i],";")!=0)) // сравнения должны быть именно в таком порядке, иначе в случае strcmp(NULL,...) произойдет страшное
  884.     {
  885.         i++;
  886.     }
  887.     if ((base[i]!=NULL)&&(strcmp(base[i],"&")==0))
  888.     {
  889.         a=fork();
  890.         if (a==-1)
  891.         {
  892.             printf("Не удалось породить процесс\n");
  893.             return -2;
  894.         }
  895.         if (a==0)
  896.         {
  897.             pipe(fd);
  898.             a=fork();
  899.             if (a==-1)
  900.             {
  901.                 printf("Не удалось породить процесс\n");
  902.                 return -2;
  903.             }
  904.             if (a==0)
  905.             {
  906.                 read(fd[0],&a,sizeof(int));
  907.                 close(fd[0]);
  908.                 close(fd[1]);
  909.                 while(getppid()==a)
  910.                 {
  911.                 }
  912.                 temp=base[i];
  913.                 base[i]=NULL;
  914.                 a=open("/dev/null", O_WRONLY);
  915.                 dup2(a,0);
  916.                 logic(lastcom,1);
  917.                 close(a);
  918.                 base[i]=temp;
  919.                 return -2;
  920.             }
  921.             // сюда может попасть только процесс-отец
  922.             a=getpid();
  923.             write(fd[1],&a,sizeof(int));
  924.             close(fd[0]);
  925.             close(fd[1]);
  926.             return -2;
  927.         }
  928.         else
  929.         {
  930.             wait(NULL); // программа основного shell
  931.         }
  932.     }
  933.     if ((base[i]!=NULL)&&(strcmp(base[i],";")==0))
  934.     {
  935.         temp=base[i];
  936.         base[i]=NULL;
  937.         a=logic(lastcom,0);
  938.         base[i]=temp;
  939.         if (a!=0)
  940.         {
  941.             return (-2); // возврат в теле одного из сыновей основого shell, либо в случае ошибки fork в pipeline
  942.         }
  943.     }
  944.     if (base[i]!=NULL)
  945.     {
  946.         i++;
  947.         lastcom=base+i;
  948.         goto jmp;
  949.     }
  950.     //на данный момент не выполнился последний нефоновый процесс (ситуацию "proc &" рассматриваем как proc и пустой процесс)
  951.     return (logic(lastcom,0));
  952. }
  953.  
  954.  
  955. int main (int argc, char **argv)
  956. {
  957.     signal(SIGINT, SIG_IGN);
  958.     signal(SIGUSR1, Sighndlr);
  959.     int a, check=0, fd;
  960.     char *s, **base;
  961.     if (argc==1)
  962.     {
  963.         fd=dup(0);
  964.     }
  965.     else
  966.     {
  967.         if (argc==2)
  968.         {
  969.             fd=open(argv[1], O_RDONLY); //переименовать
  970.             check=1;
  971.             if (fd==-1)
  972.             {
  973.                 printf("Нет доступа к файлу\n");
  974.                 return 0;
  975.             }
  976.         }
  977.         else
  978.         {
  979.             printf("Некорректное число аргументов командной строки\n");
  980.             return 0;
  981.         }
  982.     }
  983.    
  984.     do {
  985.         s=read_line(fd,&a);
  986.         base=parcer(s);
  987.         //printf("В массив строк занесены следующие строки\n");
  988.         //all_str_output(base);
  989.         if (background(base)==-2)
  990.         {
  991.             freedom(base);
  992.             free(s);
  993.             return (-2);
  994.         }
  995.         freedom(base);
  996.         free(s);
  997.     } while (a==0);
  998.     if (check==1)
  999.     {
  1000.         close(fd);
  1001.     }
  1002.     return 0;
  1003. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement