#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>

int counter=0;

//------------------------------ konveer ------------------------------

void konveer(char* p/*processes*/,char* s/*writenin' file*/,char* r/*reinput_output_divergence' file*/,int r_flag,int w_flag,int a_flag) {
 int i=0,j=0,beginin=1,fd1[2],fd2[2],pdd,n,m;
 char* p1,*p2,*h1,*h2;
 int pid_det,x;
 FILE *f1,*f2;

  p1=(char*) malloc (sizeof(char)*(101));
  p2=(char*) malloc (sizeof(char)*(101));
  while (p[i]!='\0')  {
   while ((p[i]!=' ') && (p[i]!='\0')) {
    p1[j]=p[i];
    i++;
    j++;
   }
   p1[j]='\0';
   if (p[i-1]=='\n') {
    p1[j-1]='\0';
   }
   j=0;

   if (beginin==1) {
    if (r_flag==1) {
    /*input pipe HERE r ==< p1 ==>*/
       pipe(fd1);
       pid_det=fork();
       if (!pid_det) {
        close(0);
        f1=fopen(r, "r");
	close(fd1[0]);
	dup2(fd1[1],1);
        close(fd1[1]);
        //fprintf(stderr,"hint \n");
	execlp(p1,p1,NULL);
        //fprintf(stderr,"child error \n");
        exit(1);
       }
       waitpid(pid_det, &x , 0);
       close(fd1[1]);
     //printf(" (%s)=====(%s) \n",r,p1);
     }
    else {
     //printf("first process usin default input \n");
     //FIRST process w/o input inicialization

     pipe(fd1);
      pid_det=fork();
       if (!pid_det) {
       close(fd1[0]);
       dup2(fd1[1],1);
       close(fd1[1]);
       execlp(p1,p1,NULL);
       //fprintf(stderr,"child error 'first w/o para' \n");
       exit(1);
      }
     waitpid(pid_det , &x , 0);
     sleep(1);
     close(fd1[1]);
   }
   }
   else {
     //printf("(%s)=====(%s) \n",p2,p1);
     if (p[i]!='\0') {
    /* pipe p2 ==< p1 ==> !!*/
     pipe(fd1);
     pid_det=fork();
     if (!pid_det) {
      close(fd1[0]);
      //close(fd2[1]);
      dup2(fd2[0],0);
      dup2(fd1[1],1);
      close(fd1[1]);
      close(fd2[0]);
      execlp(p1,p1,NULL);
      //fprintf(stderr,"child error \n");
      exit(1);
     }
     waitpid(pid_det , &x ,0 ); 
     sleep(1);
    // dup2(n,fd1[1]);
     close(fd2[0]);
     close(fd1[1]);
    }
    if (p[i]=='\0') {
     //printf("LAST is p1 \n");
     if (w_flag == 1) {
      //printf("(%s)=====(%s) \n",p1,s);

      pid_det=fork();
      if (!pid_det) {
       close(1);
       f2=fopen(s, "w");
       dup2(fd2[0],0);
       close(fd2[0]);
       execlp(p1,p1,NULL);
       //fprintf(stderr,"child error \n");
       exit(1);
      }
      waitpid(pid_det , &x ,0 );
      close(fd2[0]);
      break;
     }
     if (a_flag == 1) {
      //printf("(%s)=====(%s) \n",p1,s);
      pid_det=fork();
      if (!pid_det) {
       close(1);
       f2=fopen(s, "a");
       dup2(fd2[0],0);
       close(fd2[0]);
       execlp(p1,p1,NULL);
       //fprintf(stderr,"child error\n");
       exit(1);
      }
      waitpid(pid_det, &x ,0 );
      close(fd2[0]);
      break;
     }
     //printf("LAST process usin default output \n");
     pid_det=fork();
     if (!pid_det) {
      dup2(fd2[0],0);
      close(fd2[0]);
	//close(fd2[1]);	
      //fprintf(stderr,"LALALA \n");
      execlp(p1,p1,NULL);
      //fprintf(stderr,"%s \n ^^^^^^^^^^^^^",p1);
	perror(p1);
      //fprintf(stderr,"child error !!!\n");
      exit(1);
     }
    //p1 - LAST
     waitpid(pid_det,&x,0);
     close(fd2[0]);
     break;
    }
   }

    i=i+3 ;

    while ((p[i]!=' ') && (p[i]!='\0')) {
     p2[j]=p[i];
     i++;
     j++;
    }
    p2[j]='\0';
    if (p[i-1]=='\n') {
     p2[j-1]='\0';
    }
    j=0;
    //printf("(%s)=====(%s) \n",p1,p2);
    /* pipe p1 ==< p2 ==> !!*/
   if (p[i]!='\0') {
    pipe(fd2);
    pid_det=fork();
    if (!pid_det) {
     close(fd2[0]);
     dup2(fd1[0],0);
     dup2(fd2[1],1);
     close(fd1[0]);
     close(fd2[1]);
     execlp(p2,p2,NULL);
     //fprintf(stderr,"child error \n");
     exit(1);
    }
    waitpid(pid_det,&x,0);
    close(fd1[0]);
    close(fd2[1]);
   }

     if (p[i]=='\0') {
     //printf("LAST is p2 \n");
     if (w_flag == 1) {
      //printf("(%s)=====(%s) \n",p2,s);
      pid_det=fork();
      if (!pid_det) {
       close(1);
       f2=fopen(s, "w");
       dup2(fd1[0],0);
       close(fd1[0]);
       execlp(p2,p2,NULL);
      }
      waitpid(pid_det,&x,0);
      close(fd1[0]);
      break;
     }
     if (a_flag == 1) {
      //printf("(%s)=====(%s) \n",p2,s);
      pid_det=fork();
      if (!pid_det) {
       close(1);
       f2=fopen(s, "a");
       dup2(fd1[0],0);
       close(fd1[0]);
       execlp(p2,p2,NULL);
       //fprintf(stderr,"child error \n");
       exit(1);
      }
      waitpid(pid_det,&x,0);
      close(fd1[0]);
      break;
     }
     //printf("LAST process usin default output \n");
     //p2 - LAST
    pid_det=fork();
    if (!pid_det) {
     dup2(fd1[0],0);
     close(fd1[0]);
     execlp(p2,p2,NULL);
     //fprintf(stderr,"child error \n");
     exit(1);
    }
    waitpid(pid_det,&x,0);
    close(fd1[0]);
    break;
    }
   i=i+3;
   beginin++;


  }
  free(p1);
  free(p2);
}

//------------------------------ input_output_divergence ------------------------------

int input_output_divergence(char* p/*processes*/,char* s/*writenin' file*/,char* r/*reinput_output_divergence' file*/,int r_flag,int w_flag,int a_flag) {
 int i=0,pid_det,x;
 char* p1;
 FILE* f1,*f2;
 p1=(char*) malloc (sizeof(char)*(101));
 while (p[i]!='\0') {
  p1[i]=p[i];
  i++;
 }
 if (p1[i-1]=='\n') {
  p1[i-1]='\0';
 }
 pid_det=fork();
 if (!pid_det) {
  if (r_flag==1) {
        close(0);
        f1=fopen(r, "r");
  }
  if (w_flag == 1) {
       close(1);
       f2=fopen(s, "w");
  }
  if (a_flag == 1) {
       close(1);
       f2=fopen(s, "a");
  }
	execlp(p1,p1,NULL);
        //fprintf(stderr,"child error \n");
        exit(1);
 }
 waitpid(pid_det, &x , 0);
 free(p1);
}

int string_corr(char* TT) {
 int i=0,check=0,pos=0,j=0,smallflag=0,store=0;
 int r_flag=0,w_flag=0,a_flag=0;
 char *p,*r,*s;
 int lastflag=0;
  counter=0;
  p=(char*) malloc (sizeof(char)*(101));
  r=(char*) malloc (sizeof(char)*(101));
  s=(char*) malloc (sizeof(char)*(101));
  strcpy(p,TT);
  while (p[i] != '\0') {
   pos=0,j=0,smallflag=0,store=0;
   while (( p[i] != ' ') && (p[i] != '\0')) {
    i++;
   }
   if (p[i] == '\0') {
    counter++;
    //printf("%d proc w/o para on last position \n",counter);
    break;
   }

   if (check == 1) {
    //printf("useless3 \n");
    return -1;
   }
   i++;
   counter++;

   if (p[i] == '<') {
    r_flag=1;
    smallflag++;
    pos=i;
    store=i;
    if (counter != 1) {
     //printf("useless1 \n");
     return -1;
    }
    i++;
    if (p[i] == ' ') {
     smallflag++;
     i++;
    }
    while ((p[i] != ' ') && (p[i] !='\0')) {
    i++;
    }
    if (p[i] == '\0') {
     //printf("useless4 \n");
     lastflag=1;
    }
   j=i;
   pos=j-pos;
   //printf(" %d %d %c \n",j,pos,p[j]);
   while (p[j-pos] != '\0') {
   // printf("%c !\n",p[j-pos]);
    if ((j-i) < pos){
     r[j-i]=p[j-pos];
    }
    p[j-pos-1]=p[j];
    j++;
   }
   p[j-pos-1]='\0';
   r[pos]='\0';
   j=0;
   while ((pos-smallflag) != 0) {
    r[j]=r[j+smallflag];
    j++;
    pos--;
   }
   r[j]='\0';
   //printf("%s \n",r);
   i=store;
   printf("Read command executed with %s! \n",r);
   //printf("%d %c ## \n",i,p[i]);
   smallflag=0;
   if (r[j-1]=='\n') {
    r[j-1]='\0';
   }
   }
   if (lastflag) break;

   if (p[i] == '>') {
    smallflag++;
    if (check == 1) {
     //printf("useless5 \n");
     return -1;
    }
    pos=i;
    if (counter == 1) {
     lastflag=1;
     //printf("useless2 \n");
     //return -1;
    }
    i++;
    if (p[i] == '>') {
     smallflag++;
     i++;
     a_flag=1;
    }
    else {
     w_flag=1;
    }
    if (p[i] ==' ') {
     smallflag++;
     i++;
    }
    while ((p[i] != ' ') && (p[i] !='\0')) {
    i++;
    }
   check=1;
   j=i;
   pos=j-pos;
   while (p[j-pos] != '\0') {
    //printf("!");//%c !\n",p[j-pos]);
    /*if ((j-i) < pos){
     r[j-i]=p[j-pos];
    }*/
    s[j-i]=p[j-pos];
    p[j-pos]=p[j];
    j++;
   }
   //printf(" %d %d %d \n",j,pos,i);
   p[i-pos-1]='\0';
   s[j-i]='\0';
   //printf("%s& \n",p);
   j=0;
   while ((pos-smallflag) != 0) {
    s[j]=s[j+smallflag];
    j++;
    pos--;
   }
   s[j]='\0';
   if (s[j-1]=='\n') {
    s[j-1]='\0';
   }
   if (p[i] == '\0') {
    if (a_flag) {printf("Append command executed to file %s! \n",s);}
    else {printf("Write command executed to file %s! \n",s);}
    //printf("tyta \n");
    break;
   }
  }

   if (p[i] == '|') {
    //printf("'|' detected ^_^ \n");
    i++;
    if ((p[i] == '\0') || (p[i] != ' ')) {
     printf(" Syntax error \n");
     return -1;
    }
    i++;
    continue;
   }

   printf(" Syntax error  \n");
   return -1;

  }
 if (counter < 2) {
  //printf("workin with proc %s 'r' %s 'w' %s \n",p,r,s);
  input_output_divergence(p,s,r,r_flag,w_flag,a_flag);
  free(p);
  free(r);
  free(s);
  return 0;
 }
 //printf ("processes string :: %s \n",p);
 konveer(p,s,r,r_flag,w_flag,a_flag);
 free(p);
 free(r);
 free(s);
 return 0;
}

//--------------------- main ------------------------------------------

int main(int argc, char*argv[]) {
 FILE *f;
 char* eofcheck,*s;
 int corr=1,i=0;
 char c,cc;

  s=(char*) malloc (sizeof(char)*(101));
  printf("\n-------------------------Shell-------------------------\n");
  do {
  printf("List of commands: \n\t 'b' symbol to begin the command process \n\t 'q' symbol to quit \n\n\n");
  //printf("u can change command file '%s' atm \n >_",argv[1]);
  c=getchar();
  cc=getchar();
  while (cc!='\n') {
   cc=getchar();
  }
  if (c=='b') {
   if (argv[1] == NULL) {
    printf("Command file error '%s' \n");
    return;
   }
   f=fopen(argv[1] , "r");
   if (f == NULL) {
    printf("File read error '%s' \n");
    return;
   }
   eofcheck=fgets(s,100,f);
   while ( eofcheck != NULL) {
    corr=string_corr(s);
    if (corr) {
     printf("Syntax error '%s' \n" , i+1 , argv[1]);
     break;
     //return;
    }
    printf("\n Processing of %d string has been finished \n\n\n",i+1);
    eofcheck=fgets(s,100,f);
    i++;
   }
   i=0;
   continue;
  }
 if (c=='q') {break;}
 printf("Command error \n");
 } while (1);
 fclose(f);
 free(s);
 return;
}
 
