Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <stdlib.h>
- #include <sys/types.h>
- #include <sys/wait.h>
- #include <unistd.h>
- #include <string.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <signal.h>
- const int number_of_symbols = 5; // на сколько элементов выделится память (символов) при заполнении строки (read_line) (не делать меньше 3)
- const int other_number_of_symbols = 5; // на сколько элементов (символов) выделится память в функции strtok
- const int number_of_strings = 5; // на сколько строк выделится память в функции parcer
- /*
- @function freedom() - очищает память, занятую массивом строк
- @param char **base - массив строк, заканчивающийся NULL-ссылкой
- */
- void freedom (char **base)
- {
- int pos=0;
- while (base[pos])
- {
- free(base[pos]);
- pos++;
- }
- free(base);
- }
- /*
- @function sighndlr() - печать предупреждения
- Обрабатывает сигнал SIGUSR1, который посылает сыновний процесс (в случае ошибки execc), у которого закрыт стандартный вывод, отцу - процессу, формирующему конвейер
- */
- void sighndlr ()
- {
- printf("Не удалось запустить программу\n");
- }
- /*
- @function char *readline() - читает одну строку из заданного ввода
- @param int fd - дескриптор заданного ввода
- @param int *check - в этом параметре вернём 1, если в строке обнаружен EOF, иначе 0
- @return возвращает прочитанную строку
- */
- char *read_line(int file_descriptor, int *check)
- {
- int position=0, size;
- char *str, *temp, symbol, read_items;
- size=number_of_symbols;
- str=malloc(sizeof(char)*size);
- *check=0;
- if (!str)
- {
- printf("memory allocation error\n");
- exit(1);
- }
- while (1)
- {
- read_items=read(file_descriptor,&symbol,sizeof(char));
- if ((read_items==0)||(symbol=='\n'))
- {
- str[position]='\0';
- if (read_items==0)
- {
- *check=1;
- }
- return str;
- }
- else
- {
- str[position]=symbol;
- position++;
- }
- if (position==size)
- {
- size=size+number_of_symbols;
- temp=str;
- str=realloc(str,size*sizeof(char));
- if (!str)
- {
- free(temp);
- printf("memory allocation error\n");
- exit(1);
- }
- }
- }
- }
- /*
- @function char *mystrtok() - вычленяет лексему из строки
- @param char *line - строка, из которой вычленяется лексема
- @param int *check - в этом параметре вернём 1, если данная лексема - последняя перед концом строки, 2 - если произошла ошибка выделения памяти, иначе 0
- @param int *num - в этом параметре возвращаем позицию последнего символа, который записан в вычлененную лексему
- @return возвращает в виде полноценной строки первую лексему, которую возможно вычленить
- */
- char *mystrtok (char *line, int *check, int *num)
- {
- int size, pos=0, hpos=0, pos1, hpos1;
- // pos - позиция в основной строке
- // hpos - (вспомогательная) позиция в формируемой строке
- // pos1, hpos1 - нужны для обработки кавычек
- char *str, *temp;
- size=other_number_of_symbols;
- str=malloc(sizeof(char)*size);
- if (!str)
- {
- printf("memory allocation error\n");
- *check=2;
- free(str);
- return NULL;
- }
- while (1)
- {
- // Обработка кавычек
- if (line[pos]=='"')
- {
- pos1=pos+1;
- hpos1=hpos;
- while (1)
- {
- if (line[pos1]=='"')
- {
- hpos=hpos1;
- pos=pos1+1;
- break;
- }
- if ((line[pos1]==EOF)||(line[pos1]=='\0'))
- {
- break; // не найдено парной кавычки -> кавычка должна считаться как обычный символ
- }
- str[hpos1]=line[pos1];
- hpos1++;
- pos1++;
- if (hpos1==size)
- {
- temp=str;
- size=size+other_number_of_symbols;
- str=realloc(str,size*sizeof(char));
- if (!str)
- {
- free(temp);
- printf("memory allocation error\n");
- *check=2;
- return NULL;
- }
- }
- }
- }
- // Обработка иных случаев
- if (line[pos]==' ')
- {
- if (hpos==0)
- {
- pos++;
- }
- else
- {
- str[hpos]='\0';
- *check=0;
- *num=pos; // чтобы в следующий раз отправить в эту функцию другую строку
- return str;
- }
- }
- else
- {
- if (line[pos]=='\0')
- {
- if (hpos==0)
- {
- *check=1;
- free(str);
- return NULL;
- }
- else
- {
- str[hpos]='\0';
- *check=1;
- return str;
- }
- }
- else // обнаружен элемент, который можно записать в строку
- {
- // Обрабатываем спецсимволы
- if ((line[pos]=='|')||(line[pos]=='&')||(line[pos]=='>')||(line[pos]=='<')||(line[pos]==';')||(line[pos]==')')||(line[pos]=='('))
- {
- if (hpos>0) //до этого уже сформирована строка
- {
- str[hpos]='\0';
- *check=0;
- *num=pos;
- return str;
- }
- else // строка еще не сформирована (hpos==0)
- {
- // |
- if (line[pos]=='|')
- {
- if (line[pos+1]=='|')
- {
- str[0]='|';
- str[1]='|';
- str[2]='\0';
- *check=0;
- *num=pos+2;
- return str;
- }
- else
- {
- str[0]='|';
- str[1]='\0';
- *check=0;
- *num=pos+1;
- return str;
- }
- }
- // &
- if (line[pos]=='&')
- {
- if (line[pos+1]=='&')
- {
- str[0]='&';
- str[1]='&';
- str[2]='\0';
- *check=0;
- *num=pos+2;
- return str;
- }
- else
- {
- str[0]='&';
- str[1]='\0';
- *check=0;
- *num=pos+1;
- return str;
- }
- }
- // >
- if (line[pos]=='>')
- {
- if (line[pos+1]=='>')
- {
- str[0]='>';
- str[1]='>';
- str[2]='\0';
- *check=0;
- *num=pos+2;
- return str;
- }
- else
- {
- str[0]='>';
- str[1]='\0';
- *check=0;
- *num=pos+1;
- return str;
- }
- }
- // <
- if (line[pos]=='<')
- {
- str[0]='<';
- str[1]='\0';
- *check=0;
- *num=pos+1;
- return str;
- }
- // ;
- if (line[pos]==';')
- {
- str[0]=';';
- str[1]='\0';
- *check=0;
- *num=pos+1;
- return str;
- }
- // )
- if (line[pos]==')')
- {
- str[0]=')';
- str[1]='\0';
- *check=0;
- *num=pos+1;
- return str;
- }
- // (
- if (line[pos]=='(')
- {
- str[0]='(';
- str[1]='\0';
- *check=0;
- *num=pos+1;
- return str;
- }
- }
- }
- //Если встречен обычный символ
- str[hpos]=line[pos];
- hpos++;
- pos++;
- if (hpos==size)
- {
- temp=str;
- size=size+other_number_of_symbols;
- str=realloc(str,size*sizeof(char));
- if (!str)
- {
- free(temp);
- printf("memory allocation error\n");
- *check=2;
- return NULL;
- }
- }
- }
- }
- }
- }
- /*
- @function char **divide_to_lexemes() - разбивает строку на лексемы
- @param char *line - строка, из которой вычленяются лексемы
- @return возвращает массив строк (оканчивающийся NULL-ссылкой), сформированный из вычлененных лексем
- */
- char **divide_to_lexemes (char *line)
- {
- int check, pos=0, size=0, strpos=0, hstrpos=0;
- // strpos - сдвиг строки (все, что до этого сдвига уже поделено не лексемы)
- // hstrpos - на что увеличится strpos после вычленения очередной лексемы
- char **base, **temp;
- size=number_of_strings;
- base=malloc(sizeof(char *)*size);
- if (!base)
- {
- printf("memory allocation error\n");
- free(line);
- exit(1);
- }
- while(1)
- {
- base[pos]=mystrtok(line+strpos, &check, &hstrpos);
- if (check==2)
- {
- base[pos]=NULL;
- freedom(base);
- exit(1);
- }
- if (check==1)
- {
- if (!base[pos]) // вернулась NULL - парсинг строки завершен
- {
- return base; //может быть даже такое, что первый элемент этого массива - NULL
- }
- else // вернулась не пустая строка, но обнаружен конец основной строки
- {
- pos++;
- if (pos==size)
- {
- size=size+1;
- temp=base;
- base=realloc(base,size*sizeof(char *));
- if (!base)
- {
- free(temp[pos-1]); // т.к. на новый pos места уже нет
- temp[pos-1]=NULL;
- freedom(base);
- exit(1);
- }
- }
- base[pos]=NULL;
- return base;
- }
- }
- if (check==0)
- {
- strpos+=hstrpos;
- pos++;
- if (pos==size)
- {
- size=size+number_of_strings;
- temp=base;
- base=realloc(base,size*sizeof(char *));
- if (!base)
- {
- free(temp[pos-1]); // т.к. на новый pos места уже нет
- temp[pos-1]=NULL;
- freedom(base);
- exit(1);
- }
- }
- }
- }
- }
- /*
- @function int cd() - разбивает строку на лексемы
- @param char *str - строка-аргумент команды cd
- @return возвращает 0, в случае успешой смены директории, иначе -1
- */
- int cd (char *str) // проверка на корректность количества аргументов команды cd производится раньше
- {
- int res;
- if (str==NULL) //значит пользователю надо перейти в домашний каталог
- {
- res=chdir(getenv("HOME"));
- if (res==-1)
- {
- printf ("В указанный каталог перейти не удалось\n");
- }
- return res;
- }
- else
- {
- res=chdir(str);
- if (res==-1)
- {
- printf ("В указанный каталог перейти не удалось\n");
- }
- return res;
- }
- }
- /*
- @function int funcion_call() - вызов нового процесса
- @param char **base - массив строк, первым элементом которого является имя исполняемого файла (полный путь до него) и аргументы командной строки
- @param int fd[2] - fd[1] дескриптор смены стандартного вывода
- @param int flag - flag==1 говорит о том, что подан последний процесс из конвейера
- @param int *key - через этот параметр передаем pid запущенного процесса
- @return возвращает -1 в случае неудачного fork, -2 в случае неудачного exec, -3 в случае пустой команды, иначе - 0
- */
- int function_call (char **base, int file_descriptor[2], int flag, int *key)
- {
- int fork_res, exec_res; // проверка различных возвратов
- if (base[0]==NULL)
- {
- dup2(file_descriptor[0],0);
- close(file_descriptor[0]);
- close(file_descriptor[1]);
- return -3;
- }
- fork_res=fork();
- if (fork_res==-1)
- {
- printf("Не удалось породить процесс\n");
- *key=-1;
- return (-1);
- }
- if (fork_res>0)
- {
- dup2(file_descriptor[0],0);
- close(file_descriptor[0]);
- close(file_descriptor[1]);
- *key=fork_res;
- }
- else
- {
- if (flag!=1)
- {
- dup2(file_descriptor[1],1);
- }
- close(file_descriptor[1]);
- close(file_descriptor[0]);
- exec_res=execvp(base[0],base);
- if (exec_res==-1)
- {
- //printf("Не удалось запустить программу - %s\n",base[0]);
- kill(getppid(),SIGUSR1);
- return -2;
- }
- }
- return 0;
- }
- /*
- @function all_str_output() - вывод хранящихся в base строк
- @param char **base - массив строк, заканчивающийся NULL-ссылкой
- */
- void all_str_output (char **base)
- {
- int pos=0;
- while ((base[pos]))
- {
- printf("%s\n",base[pos]);
- pos++;
- }
- }
- /*
- @function int pipeline() - функция создания конвейера
- @param char **base - массив строк, из которого вычленяются подмассивы, содержащие имена отдельных процессов
- @param int bcheck - bcheck==1 говорит о том, что конвейер запускается в фоновом режиме (не нужно восстанавливать реакцию на SIGINT)
- @param int *transit - неименованный канал, ведущий к logic и использующийся для передачи возвращённого значения запущенного процесса
- @return возвращает -2 в случае каких-либо ошибок (а также возвращении в теле сыновнего процесса), либо 0 в случае корректной работы
- */
- int pipeline (char** base, int bcheck, int *transit)
- {
- int len=0, i=0, j=0, fd[2], fork_res, pipe_res, call_res, writeintransit=1, key;
- char **lastinstr, *str;
- if ((base[0]!=NULL)&&(strcmp(base[0],"cd")==0))
- {
- if ((base[1]!=NULL)&&(base[2]!=NULL)) //ошибки не случится, т.к. при false в первом условии проверки второго не осуществиться
- {
- printf("cd: Некорректное число аргументов\n");
- writeintransit=1;
- write(transit[1], &writeintransit, sizeof(int));
- }
- else
- {
- writeintransit=cd(base[1]);
- write(transit[1], &writeintransit, sizeof(int));
- }
- return 0;
- }
- fork_res=fork();
- if (fork_res==-1)
- {
- printf("Породить процесс не удалось\n");
- writeintransit=1;
- write(transit[1], &writeintransit, sizeof(int));
- return -1;
- }
- if (fork_res==0)
- {
- if (bcheck!=1)
- {
- signal(SIGINT,SIG_DFL);
- }
- lastinstr=base;
- while (base[i])
- {
- if (strcmp(base[i],"|")==0)
- {
- len++;
- }
- i++;
- }
- j=0;
- i=0;
- while (i<len)
- {
- while (strcmp(base[j],"|")!=0)
- {
- j++;
- }
- i++;
- j++;
- pipe_res=pipe(fd);
- if (pipe_res==-1)
- {
- printf("Не удалось установить связь между процессами конвейера\n");
- writeintransit=1; // т.к. конвейер построился некорректно
- write(transit[1], &writeintransit, sizeof(int));
- return -2;
- // тут еще надо подумать
- }
- str=base[j-1];
- base[j-1]=NULL;
- call_res=function_call(lastinstr, fd, 0, &key);
- base[j-1]=str;
- lastinstr=base+j;
- if (call_res==-2) // возврат в теле сыновнего процесса
- {
- return -2;
- }
- if (call_res==-1)
- {
- while(wait(NULL)!=-1);
- writeintransit=1; // т.к. конвейер построился некорректно
- write(transit[1], &writeintransit, sizeof(int));
- return -2;
- }
- // call_res = 0 - всё хорошо
- }
- // на момент выхода из цикла не вызвана последняя программа из конвейера
- pipe_res=pipe(fd);
- if (pipe_res==-1)
- {
- printf("Не удалось установить связь между процессами конвейера\n");
- writeintransit=1; // т.к. конвейер построился некорректно
- write(transit[1], &writeintransit, sizeof(int));
- return -2;
- }
- call_res=function_call(lastinstr, fd, 1, &key);
- if (call_res==-3) // последняя команда - пустая
- {
- writeintransit=1;
- write(transit[1], &writeintransit, sizeof(int));
- while(wait(NULL)!=-1);
- return -2;
- }
- if (call_res==-2) // возврат в теле сыновнего процесса
- {
- return -2;
- }
- waitpid(key, &writeintransit, 0);
- write(transit[1], &writeintransit, sizeof(int));
- while(wait(NULL)!=-1);
- return -2;
- }
- // тут может оказаться только процесс-родитель
- wait(NULL);
- return 0;
- }
- /*
- @function int redirection() - функция обработки перенаправлений
- @param char **base - массив строк, из которого вычленяется информация о перенаправлениях
- @param int bcheck - просто передаём дальше в pipeline()
- @param int *transit - передаём дальше в pipeline()
- @return возвращает число, которое вернула pipeline()
- Согласно нашему синтаксису требуется, чтобы перенаправления стояли последними 2/4 строками массива
- */
- int redirection (char **base, int bcheck, int *transit)
- {
- int len=0,fdrd,fdwr,hfd1,hfd2,checkrd=0,checkwr=0,res=0;
- // fdrd - дескриптор на запись
- // fdwr - дескриптор на чтение
- // checkwr==1 - имеется перенаправление вывода
- // checkrd==1 - имеется перенаправление ввода
- // в hfd1, hfd2 заносим стандартные потоки вывода/ввода
- char *str;
- while (base[len]) // кол-во переданных слов
- {
- len++;
- }
- hfd1=dup(1);
- hfd2=dup(0);
- if ((len>=4)&&(strcmp(base[len-2],">>")==0)&&(strcmp(base[len-4],">")==0)&&(strcmp(base[len-3],base[len-1])==0))
- {
- fdwr=open(base[len-1], O_CREAT | O_TRUNC | O_WRONLY | O_EXCL, 0666);
- if (fdwr==-1)
- {
- fdwr=open(base[len-1], O_TRUNC | O_WRONLY); // возможно, файл уже существует
- if (fdwr==-1)
- {
- printf("Перенаправление вывода организовать не удалось\n");
- goto jmp;
- }
- }
- checkwr=1;
- dup2(fdwr,1);
- str=base[len-4];
- base[len-4]=NULL;
- res=pipeline(base,bcheck,transit);
- base[len-4]=str;
- goto jmp;
- }
- if ((len>=4)&&(strcmp(base[len-2],">>")==0)&&(strcmp(base[len-4],"<")==0)&&(strcmp(base[len-3],base[len-1])==0))
- {
- printf("Недопустимая конструкция (входной и выходной файлы совпадают)\n");
- goto jmp;
- }
- if ((len>=4)&&(strcmp(base[len-2],">")==0)&&(strcmp(base[len-4],"<")==0)&&(strcmp(base[len-3],base[len-1])==0))
- {
- printf("Недопустимая конструкция (входной и выходной файлы совпадают)\n");
- goto jmp;
- }
- if ((len>=4)&&(strcmp(base[len-2],"<")==0)&&(strcmp(base[len-4],">")==0)&&(strcmp(base[len-3],base[len-1])==0))
- {
- printf("Недопустимая конструкция (входной и выходной файлы совпадают)\n");
- goto jmp;
- }
- if ((len>=4)&&(strcmp(base[len-2],"<")==0)&&(strcmp(base[len-4],">>")==0)&&(strcmp(base[len-3],base[len-1])==0))
- {
- printf("Недопустимая конструкция (входной и выходной файлы совпадают)\n");
- goto jmp;
- }
- if (len>=2) // потому что ситуация подачи на ввод, например >> text - корректна
- {
- if (strcmp(base[len-2],">")==0)
- {
- fdwr=open(base[len-1], O_CREAT | O_TRUNC | O_WRONLY | O_EXCL, 0666);
- if (fdwr==-1)
- {
- fdwr=open(base[len-1], O_TRUNC | O_WRONLY); // возможно, файл уже существует
- if (fdwr==-1)
- {
- printf("Перенаправление вывода организовать не удалось\n");
- goto jmp;
- }
- }
- checkwr=1;
- dup2(fdwr,1);
- }
- if (strcmp(base[len-2],">>")==0)
- {
- fdwr=open(base[len-1], O_CREAT | O_APPEND | O_WRONLY | O_EXCL, 0666);
- if (fdwr==-1)
- {
- fdwr=open(base[len-1], O_APPEND| O_WRONLY);
- if (fdwr==-1)
- {
- printf("Перенаправление вывода организовать не удалось\n");
- goto jmp;
- }
- }
- checkwr=1;
- dup2(fdwr,1);
- }
- if (strcmp(base[len-2],"<")==0)
- {
- fdrd=open(base[len-1], O_RDONLY);
- if (fdrd==-1)
- {
- printf("Перенаправление ввода организовать не удалось\n");
- goto jmp;
- }
- checkrd=1;
- dup2(fdrd,0);
- }
- if (len>=4)
- {
- if ((checkrd==1)||(checkwr==1))
- {
- if ((checkrd==1)&&(strcmp(base[len-4],">")==0))
- {
- fdwr=open(base[len-3], O_CREAT | O_TRUNC | O_WRONLY | O_EXCL, 0666);
- if (fdwr==-1)
- {
- fdwr=open(base[len-3], O_TRUNC | O_WRONLY);
- if (fdwr==-1)
- {
- printf("Перенаправление вывода организовать не удалось\n");
- goto jmp;
- }
- }
- checkwr=1;
- dup2(fdwr,1);
- }
- if ((checkrd==1)&&(strcmp(base[len-4],">>")==0))
- {
- fdwr=open(base[len-3], O_CREAT | O_APPEND | O_WRONLY | O_EXCL, 0666);
- if (fdwr==-1)
- {
- fdwr=open(base[len-3], O_APPEND| O_WRONLY);
- if (fdwr==-1)
- {
- printf("Перенаправление вывода организовать не удалось\n");
- goto jmp;
- }
- }
- checkwr=1;
- dup2(fdwr,1);
- }
- if ((checkwr==1)&&(strcmp(base[len-4],"<")==0))
- {
- fdrd=open(base[len-3], O_RDONLY);
- if (fdrd==-1)
- {
- printf("Перенаправление ввода организовать не удалось\n");
- goto jmp;
- }
- checkrd=1;
- dup2(fdrd,0);
- }
- if ((checkwr==1)&&(checkrd==1))
- {
- str=base[len-4];
- base[len-4]=NULL;
- res=pipeline(base,bcheck,transit);
- base[len-4]=str;
- }
- else
- {
- str=base[len-2];
- base[len-2]=NULL;
- res=pipeline(base,bcheck,transit);
- base[len-2]=str;
- }
- }
- else
- {
- res=pipeline(base,bcheck,transit);
- }
- }
- else // меньше 4 слов в команде
- {
- if ((checkrd==1)||(checkwr==1)) // только одно из перенаправлений имело место
- {
- str=base[len-2];
- base[len-2]=NULL;
- res=pipeline(base,bcheck,transit);
- base[len-2]=str;
- }
- else // перенаправлений не было
- {
- res=pipeline(base,bcheck,transit);
- }
- }
- }
- else // меньше 2 слов в команде
- {
- res=pipeline(base,bcheck,transit);
- }
- jmp:
- if (checkwr==1)
- {
- dup2(hfd1,1);;
- close(fdwr);
- }
- if (checkrd==1)
- {
- dup2(hfd2,0);
- close(fdrd);
- }
- close(hfd1);
- close(hfd2);
- return res;
- }
- /*
- @function int logic() - функция обработка логики (&&, ||)
- @param char **base - массив строк, из которого вычленяется информация о логике
- @param int bcheck - передаем дальше в redirection()
- @return возвращает -2 в случае каких-либо ошибок, либо 0 в случае корректной работы
- */
- int logic(char **base, int bcheck)
- {
- int lastexit=0; // тут хранится код возврата последнего выполнившегося процесса (и cd)
- int transit[2]; // проведенный до pipeline канал
- int i=0, redirection_res;
- char str1[3]="||", str2[3]="&&", **lastcom, *temp;
- char *lastlogic; //в комбинации с lastexit всегда должна дать выполниться первой команде
- lastlogic=str2;
- while (base[i]!=NULL)
- {
- if ((strcmp(base[i],str1)==0)||(strcmp(base[i],str2)==0))
- {
- if (i==0)
- {
- printf("Некорректный синтаксис\n");
- return 0;
- }
- if ((i>0)&&(strcmp(base[i-1],str1)==0))
- {
- printf("Некорректный синтаксис\n");
- return 0;
- }
- if ((i>0)&&(strcmp(base[i-1],str2)==0))
- {
- printf("Некорректный синтаксис\n");
- return 0;
- }
- }
- i++;
- }
- if ((i>0)&&((strcmp(base[i-1],"&&")==0)||(strcmp(base[i-1],"||")==0))) // последняя лексема - &&, либо ||
- {
- printf("Некорректный синтаксис\n");
- return 0;
- }
- i=0;
- if (pipe(transit)==-1)
- {
- printf("Не удается получить результат процесса\n");
- return -2;
- }
- lastcom=base;
- while (base[i]!=NULL)
- {
- if (strcmp(base[i],str1)==0)
- {
- if (((lastexit==0)&&(strcmp(lastlogic,str2)==0))||((lastexit!=0)&&(strcmp(lastlogic,str1)==0)))
- {
- temp=base[i]; // очень важно делать именно так (иначе портится память)
- base[i]=NULL;
- redirection_res=redirection(lastcom,bcheck,transit);
- base[i]=temp;
- if (redirection_res!=0) // возврат в случае ошибки fork , либо в теле сыновнего процесса
- {
- return -2;
- }
- read(transit[0],&lastexit,sizeof(int)); // читаем, что сюда записалось в pipeline
- }
- lastcom=base+i+1;
- lastlogic=str1;
- }
- if (strcmp(base[i],str2)==0)
- {
- if (((lastexit==0)&&(strcmp(lastlogic,str2)==0))||((lastexit!=0)&&(strcmp(lastlogic,str1)==0)))
- {
- temp=base[i];
- base[i]=NULL;
- redirection_res=redirection(lastcom,bcheck,transit);
- base[i]=temp;
- if (redirection_res!=0) // возврат в случае ошибки fork , либо в теле сыновнего процесса
- {
- close(transit[0]);
- close(transit[1]);
- return -2;
- }
- read(transit[0],&lastexit,sizeof(int)); // читаем, что сюда записалось в pipeline
- }
- lastcom=base+i+1;
- lastlogic=str2;
- }
- i++;
- }
- // на данный момент не обработана последняя команда
- if (((lastexit==0)&&(strcmp(lastlogic,str2)==0))||((lastexit!=0)&&(strcmp(lastlogic,str1)==0)))
- {
- redirection_res=redirection(lastcom,bcheck,transit);
- if (redirection_res!=0) // возврат в случае ошибки fork , либо в теле сыновнего процесса
- {
- close(transit[0]);
- close(transit[1]);
- return -2;
- }
- }
- close(transit[0]);
- close(transit[1]);
- return 0;
- }
- /*
- @function int backgroud() - функция обработки фонового режима (&) и ;
- @param char **base - массив строк, из которого вычленяется информация о последовательноти запуска процессов и фоновости режима
- @return возвращает -2 в случае каких-либо ошибок (а также возвращении в теле сыновнего процесса), либо 0 в случае корректной работы
- */
- int background (char **base)
- {
- char **lastcom, *temp;
- int i=0, res, file_descriptor[2]; // res - осуществляет проверку различных возвратов, по file_descriptor сообщим сыновнему процессу pid отца, чтобы он мог подождать завершения отца
- lastcom=base;
- // проверка на корректность расстановки ; (она не может быть первым символом и стоять рядом с другой ;)
- if ((base[i]!=NULL)&&(strcmp(base[i],";")==0))
- {
- printf("Некорректный синтаксис\n");
- return 0;
- }
- while (base[i]!=NULL)
- {
- if (strcmp(base[i],";")==0)
- {
- if ((i>0)&&(strcmp(base[i-1],";")==0))
- {
- printf("Некорректный синтаксис\n");
- return 0;
- }
- }
- i++;
- }
- i=0;
- jmp:
- while ((base[i]!=NULL)&&(strcmp(base[i],"&")!=0)&&(strcmp(base[i],";")!=0)) // сравнения должны быть именно в таком порядке, иначе в случае strcmp(NULL,...) произойдет страшное
- {
- i++;
- }
- if ((base[i]!=NULL)&&(strcmp(base[i],"&")==0))
- {
- res=fork();
- if (res==-1)
- {
- printf("Не удалось породить процесс\n");
- return -2;
- }
- if (res==0)
- {
- pipe(file_descriptor);
- res=fork();
- if (res==-1)
- {
- printf("Не удалось породить процесс\n");
- return -2;
- }
- if (res==0)
- {
- read(file_descriptor[0],&res,sizeof(int));
- close(file_descriptor[0]);
- close(file_descriptor[1]);
- while(getppid()==res)
- {
- }
- temp=base[i];
- base[i]=NULL;
- res=open("/dev/null", O_WRONLY);
- dup2(res,0);
- logic(lastcom,1);
- close(res);
- base[i]=temp;
- return -2;
- }
- // сюда может попасть только процесс-отец
- res=getpid();
- write(file_descriptor[1],&res,sizeof(int));
- close(file_descriptor[0]);
- close(file_descriptor[1]);
- return -2;
- }
- else
- {
- wait(NULL); // программа основного shell
- }
- }
- if ((base[i]!=NULL)&&(strcmp(base[i],";")==0))
- {
- temp=base[i];
- base[i]=NULL;
- res=logic(lastcom,0);
- base[i]=temp;
- if (res!=0)
- {
- return (-2); // возврат в теле одного из сыновей основого shell, либо в случае ошибки fork в pipeline
- }
- }
- if (base[i]!=NULL)
- {
- i++;
- lastcom=base+i;
- goto jmp;
- }
- //на данный момент не выполнился последний нефоновый процесс (ситуацию "proc &" рассматриваем как proc и пустой процесс)
- return (logic(lastcom,0));
- }
- int main (int argc, char **argv)
- {
- signal(SIGINT, SIG_IGN);
- signal(SIGUSR1, sighndlr);
- int check_end, check=0, input_descriptor;
- char *str, **base;
- if (argc==1)
- {
- input_descriptor=dup(0);
- }
- else
- {
- if (argc==2)
- {
- input_descriptor=open(argv[1], O_RDONLY);
- check=1;
- if (input_descriptor==-1)
- {
- printf("Нет доступа к файлу\n");
- return 0;
- }
- }
- else
- {
- printf("Некорректное число аргументов командной строки\n");
- return 0;
- }
- }
- do {
- printf("MyShell:\n");
- str=read_line(input_descriptor,&check_end);
- base=divide_to_lexemes(str);
- //printf("В массив строк занесены следующие строки\n");
- //all_str_output(base);
- if (background(base)==-2)
- {
- freedom(base);
- free(str);
- return (-2); // возврат либо в теле, некорректно сработавшего шелл (не сработал fork()), либо в теле сыновнего процесса, в котором не сработал exec,
- // либо в теле каких-то промежуточных процессов-копий основного шелл
- }
- freedom(base);
- free(str);
- } while (check_end==0);
- if (check==1)
- {
- close(input_descriptor);
- }
- return 0;
- }
Add Comment
Please, Sign In to add comment