Advertisement
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 n = 5; // на сколько элементов выделится память (символов) при заполнении строки (read_line) (не делать меньше 3)
- const int m = 5; // на сколько элементов (символов) выделится память в функции strtok
- const int t = 5; // на сколько строк выделится память в функции parcer
- void freedom (char **base)
- {
- int pos=0;
- while (base[pos])
- {
- free(base[pos]);
- pos++;
- }
- free(base);
- }
- void Sighndlr ()
- {
- printf("Не удалось запустить программу\n");
- }
- char *read_line(int fd, int *check) // в check-е вернется 1, если в строке обнаружен EOF; num_quotes - число кавычек
- {
- int pos=0, size;
- char *str, *temp, c, k;
- size=n;
- str=malloc(sizeof(char)*size);
- *check=0;
- if (!str)
- {
- printf("memory allocation error\n");
- exit(1);
- }
- while (1)
- {
- k=read(fd,&c,sizeof(char));
- if ((k==0)||(c=='\n'))
- {
- str[pos]='\0';
- if (k==0)
- {
- *check=1;
- }
- return str;
- }
- else
- {
- str[pos]=c;
- pos++;
- }
- if (pos==size)
- {
- size=size+n;
- temp=str;
- str=realloc(str,size*sizeof(char));
- if (!str)
- {
- free(temp);
- printf("memory allocation error\n");
- exit(1);
- }
- }
- }
- }
- char *mystrtok (char *line, int *check, int *num) //вернет 1 в случае нахождения конца строки
- {
- int size, pos=0, hpos=0, pos1, hpos1;
- char *str, *temp;
- size=m;
- 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+m;
- 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+m;
- str=realloc(str,size*sizeof(char));
- if (!str)
- {
- free(temp);
- printf("memory allocation error\n");
- *check=2;
- return NULL;
- }
- }
- }
- }
- }
- }
- char **parcer (char *line) // последний элемент массива всегда будет иметь значение NULL
- {
- int check, pos=0, size=0, strpos=0, hstrpos=0;
- char **base, **temp;
- size=t;
- 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+t;
- temp=base;
- base=realloc(base,size*sizeof(char *));
- if (!base)
- {
- free(temp[pos-1]); // т.к. на новый pos места уже нет
- temp[pos-1]=NULL;
- freedom(base);
- exit(1);
- }
- }
- }
- }
- }
- int cd (char *str) // проверка на корректность количества аргументов команды cd производится раньше
- {
- int k;
- if (str==NULL) //значит пользователю надо перейти в домашний каталог
- {
- k=chdir(getenv("HOME"));
- if (k==-1)
- {
- printf ("В указанный каталог перейти не удалось\n");
- }
- return k;
- }
- else
- {
- k=chdir(str);
- if (k==-1)
- {
- printf ("В указанный каталог перейти не удалось\n");
- }
- return k;
- }
- }
- int function_call (char **base, int fd[2], int flag) // вернет -1 в случае неудачного fork, -2 в случае неудачного exec
- { // flag=1 говорит о том, что подан последний процесс из конвейера
- // base представляет из себя массив строк, заканчивающийся NULL - ссылкой
- int a;
- if (base[0]==NULL)
- {
- dup2(fd[0],0);
- close(fd[0]);
- close(fd[1]);
- return -2;
- }
- a=fork();
- if (a==-1)
- {
- printf("Не удалось породить процесс\n");
- return (-1);
- }
- if (a>0)
- {
- dup2(fd[0],0);
- close(fd[0]);
- close(fd[1]);
- }
- else
- {
- if (flag!=1)
- {
- dup2(fd[1],1);
- }
- close(fd[1]);
- close(fd[0]);
- a=execvp(base[0],base);
- if (a==-1)
- {
- //printf("Не удалось запустить программу - %s\n",base[0]);
- kill(getppid(),SIGUSR1);
- return -2;
- }
- }
- return 0;
- }
- void all_str_output (char **base)
- {
- int pos=0;
- while ((base[pos]))
- {
- printf("%s\n",base[pos]);
- pos++;
- }
- }
- int pipeline (char** base)
- {
- int len=0, i=0, j=0, fd[2], k;
- char **lastinstr, *str;
- signal(SIGINT,SIG_DFL);
- if ((base[0]!=NULL)&&(strcmp(base[0],"cd")==0))
- {
- if ((base[1]!=NULL)&&(base[2]!=NULL)) //ошибки не случится, т.к. при false в первом условии проверки второго не осуществиться
- {
- printf("cd: Некорректное число аргументов\n");
- }
- else
- {
- cd(base[1]);
- }
- return 0;
- }
- k=fork();
- if (k==-1)
- {
- printf("Породить процесс не удалось\n");
- return -1;
- }
- if (k==0)
- {
- 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++;
- k=pipe(fd);
- if (k==-1)
- {
- printf("Не удалось установить связь между процессами конвейера\n");
- return -2;
- // тут еще надо подумать
- }
- str=base[j-1];
- base[j-1]=NULL;
- k=function_call(lastinstr, fd, 0);
- base[j-1]=str;
- lastinstr=base+j;
- if (k==-2) // возврат в теле сыновнего процесса
- {
- return -2;
- }
- if (k==-1)
- {
- while(wait(NULL)!=-1);
- return -2;
- }
- // k = 0 - всё хорошо
- }
- // на момент выхода из цикла не вызвана последняя программа из конвейера
- k=pipe(fd);
- if (k==-1)
- {
- printf("Не удалось установить связь между процессами конвейера\n");
- return -2;
- // тут еще надо подумать
- }
- k=function_call(lastinstr, fd, 1);
- while(wait(NULL)!=-1);
- return -2;
- }
- wait(NULL);
- return 0;
- }
- // требуем, чтобы перенаправления были последними
- int redirection (char **base)
- {
- int len=0,fdrd,fdwr,hfd1,hfd2,checkrd=0,checkwr=0,res=0;
- 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);
- 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);
- base[len-4]=str;
- }
- else
- {
- str=base[len-2];
- base[len-2]=NULL;
- res=pipeline(base);
- base[len-2]=str;
- }
- }
- else
- {
- res=pipeline(base);
- }
- }
- else // меньше 4 слов в команде
- {
- if ((checkrd==1)||(checkwr==1)) // только одно из перенаправлений имело место
- {
- str=base[len-2];
- base[len-2]=NULL;
- res=pipeline(base);
- base[len-2]=str;
- }
- else // перенаправлений не было
- {
- res=pipeline(base);
- }
- }
- }
- else // меньше 2 слов в команде
- {
- res=pipeline(base);
- }
- jmp:
- if (checkwr==1)
- {
- dup2(hfd1,1);;
- close(fdwr);
- }
- if (checkrd==1)
- {
- dup2(hfd2,0);
- close(fdrd);
- }
- close(hfd1);
- close(hfd2);
- return res;
- }
- /*
- // пока что отказываемся от использования этой функции
- int parsing_sequence_of_commands (char **base) // в этой функции потом надо будет реализовывать фоновый режим
- {
- int i=0,lastarg=-1;
- char str[2], *hstr;
- str[0]=';';
- str[1]='\0';
- while (base[i]!=NULL)
- {
- if (strcmp(base[i],str)==0)
- {
- hstr=base[i];
- base[i]=NULL;
- if (function_call(base+lastarg+1)==-2)
- {
- base[i]=hstr;
- return -1; // возврат при неккоректном exec-е
- } // здесь нужен будет вызов функции, которая продолжит дальнейший разбор
- base[i]=hstr;
- lastarg=i;
- }
- i++;
- }
- if ((lastarg+1)!=i)
- {
- if (function_call(base+lastarg+1)==-2)
- {
- return -1;
- }
- }
- // иначе - пустая команда
- return 0;
- } */
- int main (int argc, char **argv)
- {
- signal(SIGINT, SIG_IGN);
- signal(SIGUSR1, Sighndlr);
- int a, check=0, fd;
- char *s, **base;
- if (argc==1)
- {
- fd=dup(0);
- }
- else
- {
- if (argc==2)
- {
- fd=open(argv[1], O_RDONLY);
- check=1;
- if (fd==-1)
- {
- printf("Нет доступа к файлу\n");
- return 0;
- }
- }
- else
- {
- printf("Некорректное число аргументов командной строки\n");
- return 0;
- }
- }
- do {
- s=read_line(fd,&a);
- //printf("%d\n",a);
- //printf("\n");
- //printf("%s\n",s);
- base=parcer(s);
- //printf("В массив строк занесены следующие строки\n");
- //all_str_output(base);
- if (redirection(base)==-2)
- { // возврат в сыновний процесс при некорректном exec-е
- freedom(base);
- free(s);
- return 0;
- }
- freedom(base);
- free(s);
- } while (a==0);
- if (check==1)
- {
- close(fd);
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement