Advertisement
romko11l

Untitled

Nov 16th, 2019
127
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 15.47 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.  
  10.  
  11. const int n = 5; // на сколько элементов выделится память (символов) при заполнении строки (read_line) (не делать меньше 3)
  12. const int m = 5; // на сколько элементов (символов) выделится память в функции strtok
  13. const int t = 5; // на сколько строк выделится память в функции parcer
  14.  
  15. void freedom (char **base)
  16. {
  17.     int pos=0;
  18.     while (base[pos])
  19.     {
  20.         free(base[pos]);
  21.         pos++;
  22.     }
  23.     free(base);
  24. }
  25.  
  26. char *read_line(FILE *f, int *check) // в check-е вернется 1, если в строке обнаружен EOF; num_quotes - число кавычек
  27. {
  28.     int c, pos=0, size;
  29.     char *str, *temp;
  30.     size=n;
  31.     str=malloc(sizeof(char)*size);
  32.     *check=0;
  33.    
  34.     if (!str)
  35.     {
  36.         printf("memory allocation error\n");
  37.         exit(1);
  38.     }
  39.    
  40.     while (1)
  41.     {
  42.         c=fgetc(f);
  43.         if ((c==EOF)||(c=='\n'))
  44.         {
  45.             str[pos]='\0';
  46.             if (c==EOF)
  47.             {
  48.                 *check=1;
  49.             }
  50.             return str;
  51.         }
  52.         else
  53.         {
  54.             str[pos]=c;
  55.             pos++;
  56.         }
  57.    
  58.         if (pos==size)
  59.         {
  60.             size=size+n;
  61.             temp=str;
  62.             str=realloc(str,size*sizeof(char));
  63.             if (!str)
  64.             {
  65.                 free(temp);
  66.                 printf("memory allocation error\n");
  67.                 exit(1);
  68.             }
  69.         }
  70.     }
  71.    
  72. }
  73.  
  74. char *mystrtok (char *line, int *check, int *num) //вернет 1 в случае нахождения конца строки
  75. {
  76.     int size, pos=0, hpos=0, pos1, hpos1;
  77.     char *str, *temp;
  78.     size=m;
  79.     str=malloc(sizeof(char)*size);
  80.     if (!str)
  81.     {
  82.         printf("memory allocation error\n");
  83.         *check=2;
  84.         free(str);
  85.         return NULL;
  86.     }
  87.    
  88.     while (1)
  89.     {
  90.         // Обработка кавычек
  91.         if (line[pos]=='"')
  92.         {
  93.             pos1=pos+1;
  94.             hpos1=hpos;
  95.             while (1)
  96.             {
  97.                 if (line[pos1]=='"')
  98.                 {
  99.                     hpos=hpos1;
  100.                     pos=pos1+1;
  101.                     break;
  102.                 }
  103.                 if ((line[pos1]==EOF)||(line[pos1]=='\0'))
  104.                 {
  105.                     break; // не найдено парной кавычки -> кавычка должна считаться как обычный символ
  106.                 }
  107.                 str[hpos1]=line[pos1];
  108.                 hpos1++;
  109.                 pos1++;
  110.                 if (hpos1==size)
  111.                 {
  112.                     temp=str;
  113.                     size=size+m;
  114.                     str=realloc(str,size*sizeof(char));
  115.                     if (!str)
  116.                     {
  117.                         free(temp);
  118.                         printf("memory allocation error\n");
  119.                         *check=2;
  120.                         return NULL;
  121.                     }
  122.                 }
  123.             }
  124.         }
  125.         // Обработка иных случаев
  126.         if (line[pos]==' ')
  127.         {
  128.             if (hpos==0)
  129.             {
  130.                 pos++;
  131.             }
  132.             else
  133.             {
  134.                 str[hpos]='\0';
  135.                 *check=0;
  136.                 *num=pos; // чтобы в следующий раз отправить в эту функцию другую строку
  137.                 return str;
  138.                
  139.             }
  140.         }
  141.         else
  142.         {
  143.             if (line[pos]=='\0')
  144.             {
  145.                 if (hpos==0)
  146.                 {
  147.                     *check=1;
  148.                     free(str);
  149.                     return NULL;
  150.                 }
  151.                 else
  152.                 {
  153.                     str[hpos]='\0';
  154.                     *check=1;
  155.                     return str;
  156.                 }
  157.             }
  158.             else // обнаружен элемент, который можно записать в строку
  159.             {
  160.                 // Обрабатываем спецсимволы
  161.                 if ((line[pos]=='|')||(line[pos]=='&')||(line[pos]=='>')||(line[pos]=='<')||(line[pos]==';')||(line[pos]==')')||(line[pos]=='('))
  162.                 {
  163.                     if (hpos>0) //до этого уже сформирована строка
  164.                     {
  165.                         str[hpos]='\0';
  166.                         *check=0;
  167.                         *num=pos;
  168.                         return str;
  169.                     }
  170.                     else // строка еще не сформирована (hpos==0)
  171.                     {
  172.                         // |
  173.                         if (line[pos]=='|')
  174.                         {
  175.                             if (line[pos+1]=='|')
  176.                             {
  177.                                 str[0]='|';
  178.                                 str[1]='|';
  179.                                 str[2]='\0';
  180.                                 *check=0;
  181.                                 *num=pos+2;
  182.                                 return str;
  183.                             }
  184.                             else
  185.                             {
  186.                                 str[0]='|';
  187.                                 str[1]='\0';
  188.                                 *check=0;
  189.                                 *num=pos+1;
  190.                                 return str;
  191.                             }
  192.                         }
  193.                         // &
  194.                         if (line[pos]=='&')
  195.                         {
  196.                             if (line[pos+1]=='&')
  197.                             {
  198.                                 str[0]='&';
  199.                                 str[1]='&';
  200.                                 str[2]='\0';
  201.                                 *check=0;
  202.                                 *num=pos+2;
  203.                                 return str;
  204.                             }
  205.                             else
  206.                             {
  207.                                 str[0]='&';
  208.                                 str[1]='\0';
  209.                                 *check=0;
  210.                                 *num=pos+1;
  211.                                 return str;
  212.                             }
  213.                         }
  214.                         // >
  215.                         if (line[pos]=='>')
  216.                         {
  217.                             if (line[pos+1]=='>')
  218.                             {
  219.                                 str[0]='>';
  220.                                 str[1]='>';
  221.                                 str[2]='\0';
  222.                                 *check=0;
  223.                                 *num=pos+2;
  224.                                 return str;
  225.                             }
  226.                             else
  227.                             {
  228.                                 str[0]='>';
  229.                                 str[1]='\0';
  230.                                 *check=0;
  231.                                 *num=pos+1;
  232.                                 return str;
  233.                             }
  234.                         }
  235.                         // <
  236.                         if (line[pos]=='<')
  237.                         {
  238.                             str[0]='<';
  239.                             str[1]='\0';
  240.                             *check=0;
  241.                             *num=pos+1;
  242.                             return str;
  243.                         }
  244.                         // ;
  245.                         if (line[pos]==';')
  246.                         {
  247.                             str[0]=';';
  248.                             str[1]='\0';
  249.                             *check=0;
  250.                             *num=pos+1;
  251.                             return str;
  252.                         }
  253.                         // )
  254.                         if (line[pos]==')')
  255.                         {
  256.                             str[0]=')';
  257.                             str[1]='\0';
  258.                             *check=0;
  259.                             *num=pos+1;
  260.                             return str;
  261.                         }
  262.                         // (
  263.                         if (line[pos]=='(')
  264.                         {
  265.                             str[0]='(';
  266.                             str[1]='\0';
  267.                             *check=0;
  268.                             *num=pos+1;
  269.                             return str;
  270.                         }
  271.                     }
  272.                 }
  273.                 //Если встречен обычный символ
  274.                 str[hpos]=line[pos];
  275.                 hpos++;
  276.                 pos++;
  277.                 if (hpos==size)
  278.                 {
  279.                     temp=str;
  280.                     size=size+m;
  281.                     str=realloc(str,size*sizeof(char));
  282.                     if (!str)
  283.                     {
  284.                         free(temp);
  285.                         printf("memory allocation error\n");
  286.                         *check=2;
  287.                         return NULL;
  288.                     }
  289.                 }
  290.             }
  291.         }
  292.        
  293.     }
  294. }
  295.  
  296. char **parcer (char *line) // последний элемент массива всегда будет иметь значение NULL
  297. {
  298.     int check, pos=0, size=0, strpos=0, hstrpos=0;
  299.     char **base, **temp;
  300.    
  301.     size=t;
  302.     base=malloc(sizeof(char *)*size);
  303.     if (!base)
  304.     {
  305.         printf("memory allocation error\n");
  306.         free(line);
  307.         exit(1);
  308.     }
  309.    
  310.     while(1)
  311.     {
  312.         base[pos]=mystrtok(line+strpos, &check, &hstrpos);
  313.         if (check==2)
  314.         {
  315.             base[pos]=NULL;
  316.             freedom(base);
  317.             exit(1);
  318.         }
  319.         if (check==1)
  320.         {
  321.             if (!base[pos]) // вернулась NULL - парсинг строки завершен
  322.             {
  323.                 return base; //может быть даже такое, что первый элемент этого массива - NULL
  324.             }
  325.             else // вернулась не пустая строка, но обнаружен конец основной строки
  326.             {
  327.                 pos++;
  328.                 if (pos==size)
  329.                 {
  330.                     size=size+1;
  331.                     temp=base;
  332.                     base=realloc(base,size*sizeof(char *));
  333.                     if (!base)
  334.                     {
  335.                         free(temp[pos-1]); // т.к. на новый pos места уже нет
  336.                         temp[pos-1]=NULL;
  337.                         freedom(base);
  338.                         exit(1);
  339.                     }
  340.                 }
  341.                 base[pos]=NULL;
  342.                 return base;
  343.             }
  344.         }
  345.         if (check==0)
  346.         {
  347.             strpos+=hstrpos;
  348.             pos++;
  349.             if (pos==size)
  350.             {
  351.                 size=size+t;
  352.                 temp=base;
  353.                 base=realloc(base,size*sizeof(char *));
  354.                 if (!base)
  355.                 {
  356.                     free(temp[pos-1]); // т.к. на новый pos места уже нет
  357.                     temp[pos-1]=NULL;
  358.                     freedom(base);
  359.                     exit(1);
  360.                 }
  361.             }
  362.         }
  363.     }
  364. }
  365.  
  366. int cd (char *str) // проверка на корректность количества аргументов команды cd производится раньше
  367. {
  368.     int k;
  369.     if (str==NULL) //значит пользователю надо перейти в домашний каталог
  370.     {
  371.         k=chdir(getenv("HOME"));
  372.         if (k==-1)
  373.         {
  374.             printf ("В указанный каталог перейти не удалось\n");
  375.         }
  376.         return k;
  377.     }
  378.     else
  379.     {
  380.         k=chdir(str);
  381.         if (k==-1)
  382.         {
  383.             printf ("В указанный каталог перейти не удалось\n");
  384.         }
  385.         return k;
  386.     }
  387. }
  388.  
  389. // -1,0 - возврат в теле процесса-отца; -2 - возврат в теле сыновнего процесса
  390. int function_call (char **base) // вернет -1 в случае неудачного fork, -2  в случае неудачного exec
  391. {
  392.     // base представляет из себя массив строк, заканчивающийся NULL - ссылкой
  393.     int a,status;
  394.     char str[3]="cd";
  395.     if (base[0]==NULL)
  396.     {
  397.         return 0;
  398.     }
  399.     if (strcmp(str,base[0])==0)
  400.     {
  401.         if ((base[1]!=NULL)&&(base[2]!=NULL)) //ошибки не случится, т.к. при false в первом условии проверки второго не осуществиться
  402.         {
  403.             printf("cd: Некорректное число аргументов\n");
  404.         }
  405.         else
  406.         {
  407.             cd(base[1]);
  408.         }
  409.         return 0;
  410.     }
  411.     a=fork();
  412.     if (a==-1)
  413.     {
  414.         printf("Не удалось породить процесс\n");
  415.         return (-1);
  416.     }
  417.     if (a>0)
  418.     {
  419.         wait(&status);
  420.     }
  421.     else
  422.     {
  423.         a=execvp(base[0],base);
  424.         if (a==-1)
  425.         {
  426.             printf("Не удалось запустить программу - %s\n",base[0]);
  427.             return -2;
  428.         }
  429.     }
  430.     return 0;
  431. }
  432.  
  433. void all_str_output (char **base)
  434. {
  435.     int pos=0;
  436.     while ((base[pos]))
  437.     {
  438.         printf("%s\n",base[pos]);
  439.         pos++;
  440.     }
  441. }
  442.  
  443. int pipeline (char **base)
  444. {
  445.     int len=0, i=0, fd[2], k,hlen=0;
  446.     char **lastinstr, *str;
  447.     lastinstr=base
  448.     while (base[i])
  449.     {
  450.         if (base[len]=='|')
  451.         {
  452.             len++;
  453.         }
  454.         i++;
  455.     }
  456.     i=0;
  457.     while (base[i])
  458.     {
  459.         if (base[i]=='|')
  460.         {
  461.             hlen++;
  462.             k=pipe(fd);
  463.             if (k==-1)
  464.             {
  465.                 printf("Не удалось установить связь между процессами\n");
  466.                 //тут еще надо подумать
  467.             }
  468.             else
  469.             {
  470.                 str=base[i];
  471.                 base[i]=NULL;
  472.                 //сначала делаем все настройки для сына, чтобы не делать этого в function_call
  473.                 if (hlen!=len)
  474.                 {
  475.                     dup2(fd[1],1);
  476.                 }
  477.                 k=function_call(lastinstr);
  478.                 if ((k==0)||(k==-1)) // возврат в теле отца
  479.                 {
  480.                    
  481.                 }
  482.             }
  483.            
  484.         }
  485.     }
  486. }
  487.  
  488. // требуем, чтобы перенаправления были последними
  489. int redirection (char **base)
  490. {
  491.     int len=0,fdrd,fdwr,hfd1,hfd2,checkrd=0,checkwr=0,res=0;
  492.     char *str;
  493.     while (base[len]) // кол-во переданных слов
  494.     {
  495.         len++;
  496.     }
  497.     hfd1=dup(1);
  498.     hfd2=dup(0);
  499.     if (len>=2) // потому что ситуация подачи на ввод, например >> text - корректна
  500.     {
  501.         if (strcmp(base[len-2],">")==0)
  502.         {
  503.             fdwr=open(base[len-1], O_CREAT | O_TRUNC | O_WRONLY | O_EXCL, 0666);
  504.             if (fdwr==-1)
  505.             {
  506.                 fdwr=open(base[len-1], O_TRUNC | O_WRONLY); // возможно, файл уже существует
  507.                 if (fdwr==-1)
  508.                 {
  509.                     printf("Перенаправление вывода организовать не удалось\n");
  510.                     goto jmp;
  511.                 }
  512.             }
  513.             checkwr=1;
  514.             dup2(fdwr,1);
  515.         }
  516.         if (strcmp(base[len-2],">>")==0)
  517.         {
  518.             fdwr=open(base[len-1], O_CREAT | O_APPEND | O_WRONLY | O_EXCL, 0666);
  519.             if (fdwr==-1)
  520.             {
  521.                 fdwr=open(base[len-1], O_APPEND| O_WRONLY);
  522.                 if (fdwr==-1)
  523.                 {
  524.                     printf("Перенаправление вывода организовать не удалось\n");
  525.                     goto jmp;
  526.                 }
  527.             }
  528.             checkwr=1;
  529.             dup2(fdwr,1);
  530.         }
  531.         if (strcmp(base[len-2],"<")==0)
  532.         {
  533.             fdrd=open(base[len-1], O_RDONLY);
  534.             if (fdrd==-1)
  535.             {
  536.                 printf("Перенаправление ввода организовать не удалось\n");
  537.                 goto jmp;
  538.             }
  539.             checkrd=1;
  540.             dup2(fdrd,0);
  541.         }
  542.         if (len>=4)
  543.         {
  544.             if ((checkrd==1)||(checkwr==1))
  545.             {
  546.                 if ((checkrd==1)&&(strcmp(base[len-4],">")==0))
  547.                 {
  548.                     fdwr=open(base[len-3], O_CREAT | O_TRUNC | O_WRONLY | O_EXCL, 0666);
  549.                     if (fdwr==-1)
  550.                     {
  551.                         fdwr=open(base[len-3], O_TRUNC | O_WRONLY);
  552.                         if (fdwr==-1)
  553.                         {
  554.                             printf("Перенаправление вывода организовать не удалось\n");
  555.                             goto jmp;
  556.                         }
  557.                     }
  558.                     checkwr=1;
  559.                     dup2(fdwr,1);
  560.                 }
  561.                 if ((checkrd==1)&&(strcmp(base[len-4],">>")==0))
  562.                 {
  563.                     fdwr=open(base[len-3], O_CREAT | O_APPEND | O_WRONLY | O_EXCL, 0666);
  564.                     if (fdwr==-1)
  565.                     {
  566.                         fdwr=open(base[len-3], O_APPEND| O_WRONLY);
  567.                         if (fdwr==-1)
  568.                         {
  569.                             printf("Перенаправление вывода организовать не удалось\n");
  570.                             goto jmp;
  571.                         }
  572.                     }
  573.                     checkwr=1;
  574.                     dup2(fdwr,1);
  575.                 }
  576.                 if ((checkwr==1)&&(strcmp(base[len-4],"<")==0))
  577.                 {
  578.                     fdrd=open(base[len-3], O_RDONLY);
  579.                     if (fdrd==-1)
  580.                     {
  581.                         printf("Перенаправление ввода организовать не удалось\n");
  582.                         goto jmp;
  583.                     }
  584.                     checkrd=1;
  585.                     dup2(fdrd,0);
  586.                 }
  587.                 if ((checkwr==1)&&(checkrd==1))
  588.                 {
  589.                     str=base[len-4];
  590.                     base[len-4]=NULL;
  591.                     res=function_call(base);
  592.                     base[len-4]=str;
  593.                 }
  594.                 else
  595.                 {
  596.                     str=base[len-2];
  597.                     base[len-2]=NULL;
  598.                     res=function_call(base);
  599.                     base[len-2]=str;
  600.                 }
  601.             }
  602.             else
  603.             {
  604.                 res=function_call(base);
  605.             }
  606.         }
  607.         else // меньше 4 слов в команде
  608.         {
  609.             if ((checkrd==1)||(checkwr==1)) // только одно из перенаправлений имело место
  610.             {
  611.                 str=base[len-2];
  612.                 base[len-2]=NULL;
  613.                 res=function_call(base);
  614.                 base[len-2]=str;
  615.             }
  616.             else // перенаправлений не было
  617.             {
  618.                 res=function_call(base);
  619.             }
  620.         }
  621.     }
  622.     else // меньше 2 слов в команде
  623.     {
  624.         res=function_call(base);
  625.     }
  626.     jmp:
  627.     if (checkwr==1)
  628.     {
  629.         dup2(hfd1,1);;
  630.         close(fdwr);
  631.     }
  632.     if (checkrd==1)
  633.     {
  634.         dup2(hfd2,0);
  635.         close(fdrd);
  636.     }
  637.     close(hfd1);
  638.     close(hfd2);
  639.     return res;
  640. }
  641.  
  642. /*
  643. // пока что отказываемся от использования этой функции
  644. int parsing_sequence_of_commands (char **base) // в этой функции потом надо будет реализовывать фоновый режим
  645. {
  646.     int i=0,lastarg=-1;
  647.     char str[2], *hstr;
  648.     str[0]=';';
  649.     str[1]='\0';
  650.     while (base[i]!=NULL)
  651.     {
  652.         if (strcmp(base[i],str)==0)
  653.         {
  654.             hstr=base[i];
  655.             base[i]=NULL;
  656.             if (function_call(base+lastarg+1)==-2)
  657.             {
  658.                 base[i]=hstr;
  659.                 return -1; // возврат при неккоректном exec-е
  660.             } // здесь нужен будет вызов функции, которая продолжит дальнейший разбор
  661.             base[i]=hstr;
  662.             lastarg=i;
  663.         }
  664.         i++;
  665.     }
  666.     if ((lastarg+1)!=i)
  667.     {
  668.         if (function_call(base+lastarg+1)==-2)
  669.         {
  670.             return -1;
  671.         }
  672.     }
  673.     // иначе - пустая команда
  674.     return 0;
  675. } */
  676.  
  677. int main (int argc, char **argv)
  678. {
  679.     int a, check=0;
  680.     char *s, **base;
  681.     FILE *f;
  682.     if (argc==1)
  683.     {
  684.         f=stdin;
  685.     }
  686.     else
  687.     {
  688.         if (argc==2)
  689.         {
  690.             f=fopen(argv[1], "r");
  691.             check=1;
  692.             if (f==NULL)
  693.             {
  694.                 printf("Нет доступа к файлу\n");
  695.                 return 0;
  696.             }
  697.         }
  698.         else
  699.         {
  700.             printf("Некорректное число аргументов командной строки\n");
  701.             return 0;
  702.         }
  703.     }
  704.     do {
  705.     s=read_line(f,&a);
  706.     //printf("%d\n",a);
  707.     //printf("\n");
  708.     //printf("%s\n",s);
  709.     base=parcer(s);
  710.     //printf("В массив строк занесены следующие строки\n");
  711.     //all_str_output(base);
  712.     if (redirection(base)==-2)
  713.     { // возврат в сыновний процесс при некорректном exec-е
  714.         freedom(base);
  715.         free(s);
  716.         return 0;
  717.     }
  718.     freedom(base);
  719.     free(s);
  720.     } while (a==0);
  721.     if (check==1)
  722.     {
  723.         fclose(f);
  724.     }
  725.     return 0;
  726. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement