/** * Parse and execute a command. */ int parse_command( command_t *c, int level, command_t *father) { int returnare; if (c->op == OP_NONE) { /* execute a simple command */ if(c->scmd != NULL && c->cmd1 == NULL && c->cmd2 == NULL) return parse_simple( c->scmd, level, c); } switch (c->op) { case OP_SEQUENTIAL: /* execute the commands one after the other */ returnare = parse_command( c->cmd1, level++, c); returnare = parse_command( c->cmd2, level++, c); return returnare; break; case OP_PARALLEL: /* execute the commands simultaneously */ do_in_parallel( c->cmd1, c->cmd2, level++, c); break; case OP_CONDITIONAL_NZERO: /* execute the second command only if the first one * returns non zero */ returnare = parse_command( c->cmd1, level++,c); if(returnare != 0) returnare = parse_command( c->cmd2, level++, c); return returnare; break; case OP_CONDITIONAL_ZERO: /* execute the second command only if the first one * returns zero */ returnare = parse_command(c->cmd1, level++, c); if(returnare == 0) returnare = parse_command( c->cmd2, level++, c); return returnare; break; case OP_PIPE: /* redirect the output of the first command to the * input of the second */ return do_on_pipe( c->cmd1, c->cmd2, level++, c); break; default: assert(false); } return 0; /* replace with actual exit code of command */ }
/** * Parse and execute a command. */ int parse_command(command_t *c, int level, command_t *father, void *h) { /* TODO sanity checks */ if (c->op == OP_NONE) { /* TODO execute a simple command */ /* TODO replace with actual exit code of command */ return parse_simple(c->scmd, level, father, (HANDLE*)h); } switch (c->op) { case OP_SEQUENTIAL: /* TODO execute the commands one after the other */ parse_command(c->cmd1, level+1, c, (HANDLE*)h); return parse_command(c->cmd2, level+1, c, (HANDLE*)h); break; case OP_PARALLEL: /* TODO execute the commands simultaneously */ if(do_in_parallel(c->cmd1, c->cmd2, level, father)){ return 0; } return -1; break; case OP_CONDITIONAL_NZERO: /* TODO execute the second command only if the first one * returns non zero */ if(parse_command(c->cmd1, level+1, c, (HANDLE*)h)){ return parse_command(c->cmd2, level+1, c, (HANDLE*)h); } break; case OP_CONDITIONAL_ZERO: /* TODO execute the second command only if the first one * returns zero */ if(parse_command(c->cmd1, level+1, c, (HANDLE*)h) == FALSE){ return parse_command(c->cmd2, level+1, c, (HANDLE*)h); } break; case OP_PIPE:{ /* TODO redirect the output of the first command to the * input of the second */ struct simple_command_t *cmds[100]; unsigned int x = 0; if (do_on_pipe(c, level, father, cmds, &x)){ return 0; } else{ return -1; } break; } default: return SHELL_EXIT; } return 0; /* TODO replace with actual exit code of command */ }
/** * Process two commands in parallel, by creating two children. */ static bool do_in_parallel(command_t *cmd1, command_t *cmd2, int level, command_t *father) { /* TODO execute cmd1 and cmd2 simultaneously */ BOOL ret_1, ret_2; char* cmd; SECURITY_ATTRIBUTES sa_1; STARTUPINFO siStartupInfo_1; PROCESS_INFORMATION piProcessInfo_1; HANDLE hOutFile_1 = INVALID_HANDLE_VALUE; HANDLE hInFile_1 = INVALID_HANDLE_VALUE; HANDLE hErrFile_1 = INVALID_HANDLE_VALUE; SECURITY_ATTRIBUTES sa_2; STARTUPINFO siStartupInfo_2; PROCESS_INFORMATION piProcessInfo_2; HANDLE hOutFile_2 = INVALID_HANDLE_VALUE; HANDLE hInFile_2 = INVALID_HANDLE_VALUE; HANDLE hErrFile_2 = INVALID_HANDLE_VALUE; BOOL changed = FALSE; char buffer[100]; int x; ZeroMemory(&sa_1, sizeof(SECURITY_ATTRIBUTES)); sa_1.nLength = sizeof(SECURITY_ATTRIBUTES); sa_1.bInheritHandle = TRUE; ZeroMemory(&siStartupInfo_1, sizeof(siStartupInfo_1)); ZeroMemory(&piProcessInfo_1, sizeof(piProcessInfo_1)); siStartupInfo_1.cb = sizeof(siStartupInfo_1); ZeroMemory(&sa_2, sizeof(SECURITY_ATTRIBUTES)); sa_2.nLength = sizeof(SECURITY_ATTRIBUTES); sa_2.bInheritHandle = TRUE; ZeroMemory(&siStartupInfo_2, sizeof(siStartupInfo_2)); ZeroMemory(&piProcessInfo_2, sizeof(piProcessInfo_2)); siStartupInfo_2.cb = sizeof(siStartupInfo_2); if(cmd2->up != NULL){ if(cmd2->up->op != OP_PARALLEL){ return parse_command(cmd2->up, level, father, (void*)(0)) == 0; } } if(cmd1->scmd){ redirrect_command(cmd1->scmd, &siStartupInfo_1, &hInFile_1, &hOutFile_1, &hErrFile_1); cmd = get_argv(cmd1->scmd); ret_1 = CreateProcess(NULL, (LPSTR)cmd, (LPSECURITY_ATTRIBUTES)&sa_1, NULL, TRUE, NORMAL_PRIORITY_CLASS, NULL, NULL, &siStartupInfo_1, &piProcessInfo_1); free(cmd); } if(cmd2->scmd){ redirrect_command(cmd2->scmd, &siStartupInfo_2, &hInFile_2, &hOutFile_2, &hErrFile_2); cmd = get_argv(cmd2->scmd); ret_2 = CreateProcess(NULL, (LPSTR)cmd, (LPSECURITY_ATTRIBUTES)&sa_2, NULL, TRUE, NORMAL_PRIORITY_CLASS, NULL, NULL, &siStartupInfo_2, &piProcessInfo_2); free(cmd); } if(cmd1->scmd){ if(ret_1 == FALSE){ sprintf(buffer, "%s: No such file or directory\n", cmd); WriteFile(hErrFile_1, buffer, strlen(buffer), &x, NULL); } else{ WaitForSingleObject(piProcessInfo_1.hProcess, INFINITE); GetExitCodeProcess(piProcessInfo_1.hProcess, &ret_1); CloseHandle(piProcessInfo_1.hProcess); CloseHandle(piProcessInfo_1.hThread); } close_handles(hInFile_1, hOutFile_1, hErrFile_1); } if(cmd2->scmd){ if(ret_2 == FALSE){ sprintf(buffer, "%s: No such file or directory\n", cmd); WriteFile(hErrFile_2, buffer, strlen(buffer), &x, NULL); } else{ WaitForSingleObject(piProcessInfo_2.hProcess, INFINITE); GetExitCodeProcess(piProcessInfo_2.hProcess, &ret_2); CloseHandle(piProcessInfo_2.hProcess); CloseHandle(piProcessInfo_2.hThread); } close_handles(hInFile_2, hOutFile_2, hErrFile_2); } if(cmd1->scmd && cmd2->scmd){ return (ret_2 == 0 && ret_1 == 0); } if(!cmd1->scmd){ do_in_parallel(cmd1->cmd1, cmd1->cmd2, level, cmd1); } if(!cmd2->scmd){ do_in_parallel(cmd2->cmd1, cmd2->cmd2, level, cmd2); } return (ret_1 && ret_2); /* TODO replace with actual exit status */ }