/* This takes a pipeline and either execs it or runs the built-in command */ void runPipeline(pipeline thePipeline) { if(executeCommand(thePipeline) == 0) { pid_t childPid; job_item* theJob; int i; /* must check every argv */ int j; for(j = 0; j < thePipeline->length; ++j) { for(i = 1; i < thePipeline->stage[j].argc; ++i) { if(strcmp(thePipeline->stage[j].argv[i], "&") == 0) { /* exec in the background */ if(i < thePipeline->stage[j].argc - 1) { fprintf(stderr, "Junk after '&'.\n"); return; } if(thePipeline->length > 1) { fprintf(stderr, "Pipelines cannot be backgrounded.\n"); return; } if((childPid = fork()) < 0) { perror("fork"); return; } else if(childPid == 0) { /* exec it in the background, ignoring the last argv[] */ thePipeline->stage->argv[thePipeline->stage->argc - 1] = (char*)0; execvp(thePipeline->stage->argv[0], thePipeline->stage->argv); perror(thePipeline->stage->argv[0]); exit(-1); } /* add the new job to the background */ theJob = (job_item*)malloc(sizeof(job_item)); if(theJob == NULL) { perror("malloc"); return; } theJob->command = newstr(thePipeline->cline); theJob->job_status = BACKGROUND; theJob->pid = childPid; addJobToList(theJob); backgroundJob(theJob); return; } } } /* exec the whole pipeline in the foreground */ execStages(thePipeline); } }
int main(int argc, char *argv[], char *env[]) { //flag para laço principal int flag = 1; //comando lido de stdin char cmd[255]; //comando lido command app; initCommand(&app); //struct para manipulação de signals struct sigaction signals; struct jobs *j; struct job *jb; signals.sa_handler = &signalHandler; sigfillset(&signals.sa_mask); signals.sa_flags = 0; sigaction(SIGCHLD, &signals, NULL); sigaction(SIGTSTP, &signals, NULL); sigaction(SIGINT, &signals, NULL); sigaction(SIGTERM, &signals, NULL); //laço principal do { //inicialização do cmd strcpy(cmd, ""); //força a impressão do buffer de saída fflush(stdout); //impressão inicial do terminal printf("AB2> "); //limpeza do stdin __fpurge(stdin); //leitura do comando scanf("%[^\n]", cmd); //comando embutido "quit" ou "exit" if ((!strcmp(cmd, "quit")) || (!strcmp(cmd, "exit"))) { flag = 0; //comando embutido "pwd" } else if (!strcmp(cmd, "pwd")) { printf("%s\n", getcwd(NULL, 0)); //comando embutido "jobs" } else if (!strcmp(cmd, "jobs")) { //remove os 'jobs' terminados da lista cleanJobs(&jobs); if (jobs) { printf("Lista de 'jobs':\n"); j = jobs; while (j) { printf("\t[%d]", j->job.pid); printf("\t%s", (j->job.state == JOB_STOPPED ? "Parado" : (j->job.state == JOB_TERMINATED ? "Terminado" : (j->job.state == JOB_EXEC_FG ? "Executando" : "Executando em plano de fundo")))); printf("\t(%s)\n", j->job.application.input); j = j->next; } } else { printf("Nenhum 'job' na lista\n"); } //comando embutido "job" } else if (!strcmp(cmd, "job")) { printf("job_pid: %d\n", job_pid); //comando embutido "help" } else if (!strcmp(cmd, "help")) { printf("AB2 SHELL HELP\n\n"); printf("Comandos embutidos:\n"); printf(" help: exibe esta lista\n"); printf(" about: exibe o 'about' do shell\n"); printf(" pwd: mostra o diretório corrente\n"); printf(" cd: troca o diretório corrente\n"); printf(" quit: termina o shell\n"); printf(" jobs: lista todos os jobs em background\n"); printf(" bg <PID>: reinicia um job, passando sua execução para background\n"); printf(" fg <PID>: reinicia um job, passando sua execução para foreground\n"); //comando embutido "about" } else if (!strcmp(cmd, "about")) { printf("AB2 SHELL ABOUT\n\n"); printf("Shell criada por:\n"); printf(" André Vinícius Azevedo Aguilar NUSP: 5890160\n"); printf(" Eduardo de Freitas Alberice NUSP: 5890006\n"); printf(" Flávio Heleno Batista NUSP: 5890027\n"); //comandos embutidos com parâmetros ou comandos externos, não vazios } else if (strcmp(cmd, "")) { parseCommand(cmd, &app, env); //comando embutido "cd" if (!strcmp(app.argv[0], "cd")) { if (app.argc) { if (chdir(app.argv[1])) { printf("cd: %s: Diretório não encontrado\n", app.argv[1]); } } //comando embutido "bg" } else if (!strcmp(app.argv[0], "bg")) { if (app.argc == 2) { backgroundJob(atoi(app.argv[1]), &jobs); } else { if (!job_pid) { cleanJobs(&jobs); jb = lastJob(jobs); if (jb) { job_pid = jb->pid; } } if (job_pid) { backgroundJob(job_pid, &jobs); job_pid = 0; } else { printf("Nenhum 'job' ativo\n"); } } //comando embutido "fg" } else if (!strcmp(app.argv[0], "fg")) { if (app.argc == 2) { job_pid = atoi(app.argv[1]); foregroundJob(job_pid, &jobs); } else { if (!job_pid) { cleanJobs(&jobs); jb = lastJob(jobs); if (jb) { job_pid = jb->pid; } } if (job_pid) { foregroundJob(job_pid, &jobs); } else { printf("Nenhum 'job' ativo\n"); } } //comando embutido "kill" } else if (!strcmp(app.argv[0], "kill")) { if (app.argc == 2) { job_pid = atoi(app.argv[1]); terminateJob(job_pid, &jobs); printf("\n[%d]\tterminado\t%s\n", job_pid, ""); job_pid = 0; } else { if (!job_pid) { cleanJobs(&jobs); jb = lastJob(jobs); if (jb) { job_pid = jb->pid; } } if (job_pid) { terminateJob(job_pid, &jobs); printf("\n[%d]\tterminado\t%s\n", job_pid, ""); job_pid = 0; } else { printf("Nenhum 'job' ativo\n"); } } //comandos externos } else { //força a impressão do buffer de saída fflush(stdout); //cria o novo job job_pid = 0; job_pid = createJob(app, &jobs); if (stateJob(job_pid, jobs) == JOB_TERMINATED) { if (resultJob(job_pid, jobs) == JOB_FAILED) { printf("%s: comando não encontrado\n", app.argv[0]); } job_pid = 0; } } freeCommand(&app); } cleanJobs(&jobs); } while (flag); if (jobs) { killJobs(&jobs); cleanJobs(&jobs); } return 0; }