     1	#include <stdio.h>
     2	#include "definitions.h"
     3	#include "utilities.h"
     4	#define MAXLINE 4096
     5	void handleUserCommand()
     6	{
     7	 //       if( chk_pipe()==1)
     8	   //     {
     9	
    10	        if (checkBuiltInCommands() == 0) {
    11			//printf("%d",commandArgc);
    12	
    13	                launchJob(commandArgv, "STANDARD", 0, FOREGROUND);
    14	                              //puts(commandArgv[1]);
    15	        }
    16	}
    17	
    18	 //int check_pipe()
    19	 //{
    20	 void pipelining(int flag)
    21	 {
    22	    char    line[MAXLINE];
    23	    FILE    *fpin, *fpout;
    24	    char arg1[50],arg2[50];
    25	    int i;
    26	   if(flag==2)
    27	   {
    28		    strcat(arg1,commandArgv[0]);
    29		    strcpy(arg2,commandArgv[2]);
    30	   }
    31	    else
    32	   {
    33		   for(i=0;i<flag-1;i++)
    34		   {
    35			   strcat(arg1,commandArgv[i]);
    36			   strcat(arg1," ");
    37		   }
    38		   strcpy(arg2,commandArgv[commandArgc-1]);
    39	   }
    40	   puts(commandArgv[0]);
    41	   puts(arg1);
    42	   puts(arg2);
    43	
    44	    if ((fpin = popen(arg1, "r")) == NULL)
    45	        printf("can't open %s", arg1);
    46	
    47	    if ((fpout = popen(arg2, "w")) == NULL)
    48	        printf("popen error");
    49	
    50	
    51	    while (fgets(line, MAXLINE, fpin) != NULL) {
    52	        if (fputs(line, fpout) == EOF)
    53	            printf("fputs error to pipe");
    54	    }
    55	    if (ferror(fpin))
    56	        printf("fgets error");
    57	    if (pclose(fpout) == -1)
    58	        printf("pclose error\n");
    59	
    60	
    61	    //return 1;
    62	}
    63	
    64	
    65	int checkBuiltInCommands()
    66	{
    67	        if (strcmp("exit", commandArgv[0]) == 0) {
    68	                exit(EXIT_SUCCESS);
    69	        }
    70	        if (strcmp("cd", commandArgv[0]) == 0) {
    71	
    72	                changeDirectory();
    73	                return 1;
    74	        }
    75	       /* if (strcmp("in", commandArgv[0]) == 0) {
    76	                launchJob(commandArgv + 2, *(commandArgv + 1), STDIN, FOREGROUND);
    77	                return 1;
    78	        }
    79	        if (strcmp("out", commandArgv[0]) == 0) {
    80	                launchJob(commandArgv + 2, *(commandArgv + 1), STDOUT, FOREGROUND);
    81	                return 1;
    82	        }*/
    83	        if (strcmp("bg", commandArgv[0]) == 0) {
    84	                if (commandArgv[1] == NULL)
    85	                        return 0;
    86	                if (strcmp("in", commandArgv[1]) == 0)
    87	                        launchJob(commandArgv + 3, *(commandArgv + 2), STDIN, BACKGROUND);
    88	                else if (strcmp("out", commandArgv[1]) == 0)
    89	                        launchJob(commandArgv + 3, *(commandArgv + 2), STDOUT, BACKGROUND);
    90	                else
    91	                        launchJob(commandArgv + 1, "STANDARD", 0, BACKGROUND);
    92	                return 1;
    93	        }
    94	        if (strcmp("fg", commandArgv[0]) == 0) {
    95	                if (commandArgv[1] == NULL)
    96	                        return 0;
    97	                int jobId = (int) atoi(commandArgv[1]);
    98	                t_job* job = getJob(jobId, BY_JOB_ID);
    99	                if (job == NULL)
   100	                        return 0;
   101	                if (job->status == SUSPENDED || job->status == WAITING_INPUT)
   102	                        putJobForeground(job, TRUE);
   103	                else                                                                                                // status = BACKGROUND
   104	                        putJobForeground(job, FALSE);
   105	                return 1;
   106	        }
   107	        if (strcmp("jobs", commandArgv[0]) == 0) {
   108	                printJobs();
   109	                return 1;
   110	        }
   111	        if (strcmp("kill", commandArgv[0]) == 0)
   112	        {
   113	                if (commandArgv[1] == NULL)
   114	                        return 0;
   115	                killJob(atoi(commandArgv[1]));
   116	                return 1;
   117	        }
   118	        //int i;
   119	        ////for( i=0;i<=commandArgc;i++)
   120	        //{
   121	        //char *str;
   122	        //strcpy(str,commandArgv);
   123	        if( commandArgc == 3 )
   124	        {
   125			if(strcmp("|", commandArgv[1]) == 0  )
   126	            {
   127	            pipelining(2);
   128	            return 1;
   129	            }
   130	            //return 1;
   131	        }
   132		if( commandArgc > 3 )
   133	{
   134			if(strcmp("|", commandArgv[commandArgc-2]) == 0 )
   135			{
   136				//puts("works");
   137				//printf("%d",commandArgc);
   138				pipelining(commandArgc-1);
   139				return 1;
   140			}
   141		}
   142	        //break;
   143	        //}
   144	
   145	
   146	
   147	        return 0;
   148	}
   149	
   150	void executeCommand(char *command[], char *file, int newDescriptor,
   151	                    int executionMode)
   152	{
   153	        int commandDescriptor;
   154	        if (newDescriptor == STDIN) {
   155	                commandDescriptor = open(file, O_RDONLY, 0600);
   156	                dup2(commandDescriptor, STDIN_FILENO);
   157	                close(commandDescriptor);
   158	        }
   159	        if (newDescriptor == STDOUT) {
   160	                commandDescriptor = open(file, O_CREAT | O_TRUNC | O_WRONLY, 0600);
   161	                dup2(commandDescriptor, STDOUT_FILENO);
   162	                close(commandDescriptor);
   163	        }
   164	        if (execvp(*command, command) == -1)
   165	                perror("MSH");
   166	}
   167	
   168	void launchJob(char *command[], char *file, int newDescriptor,
   169	               int executionMode)
   170	{
   171	        pid_t pid;
   172	        pid = fork();
   173	        switch (pid) {
   174	        case -1:
   175	                perror("MSH");
   176	                exit(EXIT_FAILURE);
   177	                break;
   178	        case 0:
   179	                signal(SIGINT, SIG_DFL);
   180	                signal(SIGQUIT, SIG_DFL);
   181	                signal(SIGTSTP, SIG_DFL);
   182	                signal(SIGCHLD, &signalHandler_child);
   183	                signal(SIGTTIN, SIG_DFL);
   184	                usleep(20000);
   185	                setpgrp();
   186	                if (executionMode == FOREGROUND)
   187	                        tcsetpgrp(MSH_TERMINAL, getpid());
   188	                if (executionMode == BACKGROUND)
   189	                        printf("[%d] %d\n", ++numActiveJobs, (int) getpid());
   190	
   191	                executeCommand(command, file, newDescriptor, executionMode);
   192	
   193	                exit(EXIT_SUCCESS);
   194	                break;
   195	        default:
   196	                setpgid(pid, pid);
   197	
   198	                jobsList = insertJob(pid, pid, *(command), file, (int) executionMode);
   199	
   200	                t_job* job = getJob(pid, BY_PROCESS_ID);
   201	
   202	                if (executionMode == FOREGROUND) {
   203	                        putJobForeground(job, FALSE);
   204	                }
   205	                if (executionMode == BACKGROUND)
   206	                        putJobBackground(job, FALSE);
   207	                break;
   208	        }
   209	}
   210	
   211	void putJobForeground(t_job* job, int continueJob)
   212	{
   213	        job->status = FOREGROUND;
   214	        tcsetpgrp(MSH_TERMINAL, job->pgid);
   215	        if (continueJob) {
   216	                if (kill(-job->pgid, SIGCONT) < 0)
   217	                        perror("kill (SIGCONT)");
   218	        }
   219	
   220	        waitJob(job);
   221	        tcsetpgrp(MSH_TERMINAL, MSH_PGID);
   222	}
   223	
   224	void putJobBackground(t_job* job, int continueJob)
   225	{
   226	        if (job == NULL)
   227	                return;
   228	
   229	        if (continueJob && job->status != WAITING_INPUT)
   230	                job->status = WAITING_INPUT;
   231	        if (continueJob)
   232	                if (kill(-job->pgid, SIGCONT) < 0)
   233	                        perror("kill (SIGCONT)");
   234	
   235	        tcsetpgrp(MSH_TERMINAL, MSH_PGID);
   236	}
   237	
   238	void waitJob(t_job* job)
   239	{
   240	        int terminationStatus;
   241	        while (waitpid(job->pid, &terminationStatus, WNOHANG) == 0) {
   242	                if (job->status == SUSPENDED)
   243	                        return;
   244	        }
   245	        jobsList = delJob(job);
   246	}
   247	
   248	void killJob(int jobId)
   249	{
   250	        t_job *job = getJob(jobId, BY_JOB_ID);
   251	        kill(job->pid, SIGKILL);
   252	}
   253	
   254	void changeDirectory()
   255	{
   256	        if (commandArgv[1] == NULL) {
   257	                chdir(getenv("HOME"));
   258	        } else {
   259	                if (chdir(commandArgv[1]) == -1) {
   260	                        printf(" %s: no such directory\n", commandArgv[1]);
   261	                }
   262	        }
   263	}
   264	
   265	
   266	void init()
   267	{
   268	        MSH_PID = getpid();
   269	        MSH_TERMINAL = STDIN_FILENO;
   270	        MSH_IS_INTERACTIVE = isatty(MSH_TERMINAL);
   271	
   272	        if (MSH_IS_INTERACTIVE) {
   273	                while (tcgetpgrp(MSH_TERMINAL) != (MSH_PGID = getpgrp()))
   274	                        kill(MSH_PID, SIGTTIN);
   275	
   276	                signal(SIGQUIT, SIG_IGN);
   277	                signal(SIGTTOU, SIG_IGN);
   278	                signal(SIGTTIN, SIG_IGN);
   279	                signal(SIGTSTP, SIG_IGN);
   280	                signal(SIGINT, SIG_IGN);
   281	                signal(SIGCHLD, &signalHandler_child);
   282	
   283	                setpgid(MSH_PID, MSH_PID);
   284	                MSH_PGID = getpgrp();
   285	                if (MSH_PID != MSH_PGID) {
   286	                        printf("Error, the shell is not process group leader");
   287	                        exit(EXIT_FAILURE);
   288	                }
   289	                if (tcsetpgrp(MSH_TERMINAL, MSH_PGID) == -1)
   290	                        tcgetattr(MSH_TERMINAL, &MSH_TMODES);
   291	
   292	                currentDirectory = (char*) calloc(1024, sizeof(char));
   293	        } else {
   294	                printf("Could not make MSH interactive. Exiting..\n");
   295	                exit(EXIT_FAILURE);
   296	        }
   297	}
   298	
   299	int main(int argc, char **argv, char **envp)
   300	{
   301	        init();
   302	        welcomeScreen();
   303	        shellPrompt();
   304	        while (TRUE) {
   305	                userInput = getchar();
   306	                switch (userInput) {
   307	                case '\n':
   308	                        shellPrompt();
   309	                        break;
   310	                default:
   311	                        getTextLine();
   312	                        handleUserCommand();
   313	                        shellPrompt();
   314	                        break;
   315	                }
   316	        }
   317	        printf("\n");
   318	        return 0;
   319	}
   320	
   321	void signalHandler_child(int p)
   322	{
   323	        pid_t pid;
   324	        int terminationStatus;
   325	        pid = waitpid(WAIT_ANY, &terminationStatus, WUNTRACED | WNOHANG);
   326	        if (pid > 0) {
   327	                t_job* job = getJob(pid, BY_PROCESS_ID);
   328	                if (job == NULL)
   329	                        return;
   330	                if (WIFEXITED(terminationStatus)) {
   331	                        if (job->status == BACKGROUND) {
   332	                                printf("\n[%d]+  Done\t   %s\n", job->id, job->name);
   333	                                jobsList = delJob(job);
   334	                        }
   335	                } else if (WIFSIGNALED(terminationStatus)) {
   336	                        printf("\n[%d]+  KILLED\t   %s\n", job->id, job->name);
   337	                        jobsList = delJob(job);
   338	                } else if (WIFSTOPPED(terminationStatus)) {
   339	                        if (job->status == BACKGROUND) {
   340	                                tcsetpgrp(MSH_TERMINAL, MSH_PGID);
   341	                                changeJobStatus(pid, WAITING_INPUT);
   342	                                printf("\n[%d]+   suspended [wants input]\t   %s\n",
   343	                                       numActiveJobs, job->name);
   344	                        } else {
   345	                                tcsetpgrp(MSH_TERMINAL, job->pgid);
   346	                                changeJobStatus(pid, SUSPENDED);
   347	                                printf("\n[%d]+   stopped\t   %s\n", numActiveJobs, job->name);
   348	                        }
   349	                        return;
   350	                } else {
   351	                        if (job->status == BACKGROUND) {
   352	                                jobsList = delJob(job);
   353	                        }
   354	                }
   355	                tcsetpgrp(MSH_TERMINAL, MSH_PGID);
   356	        }
   357	}
