bool Q::cancel(const string& uid) { JobOption job = find_job(uid); if (job.empty()) return false; delete_job(job.get().uid()); return true; }
int preempt(job_t* job) { int cmp_n, cmp = 0; int i, x = -1; for ( i=0; i < cores.cnt; i++ ) { cmp_n = sch_time(job, cores.jobs[i]); if ( cmp_n < cmp ) { cmp = cmp_n; x = i; }//if else if ( cmp_n == cmp ) { if ( x != -1 && cores.jobs[x]->arr_t < cores.jobs[i]->arr_t ) x = i; }//else if }//for // insert job into core list. if ( x >= 0 ) { delete_job(x,cores.jobs[x]->jid); insert_job(x,job); }//if return x; }//preempt
static PRJob * alloc_job(PRBool joinable, PRThreadPool *tp) { PRJob *jobp; jobp = PR_NEWZAP(PRJob); if (NULL == jobp) goto failed; if (joinable) { jobp->join_cv = PR_NewCondVar(tp->join_lock); jobp->join_wait = PR_TRUE; if (NULL == jobp->join_cv) goto failed; } else { jobp->join_cv = NULL; } #ifdef OPT_WINNT jobp->nt_notifier.jobp = jobp; #endif return jobp; failed: delete_job(jobp); PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return NULL; }
void fgCommand(int index) { int size = list_size(lista_trabajos); // Guardamos el tamaño de la lista if(empty_list(lista_trabajos)) { printf("La lista está vacía\n"); } else if(index > size || index <= 0) { printf("El argumento indicado está fuera del rango de la lista\n"); printf("La lista sólo contiene {%d} elementos\n", size); } else { // Extraemos el trabajo de la lista de trabajos job *trabajo = get_item_bypos(lista_trabajos, index); // Información sobre el proceso actual printf("Tarea: %d, pid: %d, comando: %s, estado anterior: %s. \n", index, trabajo->pgid, trabajo->command, state_strings[trabajo->state]); // Si la tarea está parada es que la hemos suspendido if(trabajo->state == STOPPED) { printf("Reanudando la tarea... \n"); killpg(trabajo->pgid, SIGCONT); // Enviamos al proceso la señal para reanudarlo } if(trabajo->state != FOREGROUND) { int status; int pgid; int info; pgid = trabajo->pgid; trabajo->state = FOREGROUND; printf("Tarea: %d, pid: %d, comando: %s, estado actual: %s. \n", index, trabajo->pgid, trabajo->command, state_strings[trabajo->state]); printf("Asignándole el terminal...\n"); set_terminal(pgid); // Esperamos que el proceso siga haciendo su ejecución en primer plano pid_t wpid = waitpid(pgid, &status, WUNTRACED); // Vemos su nuevo estado y damos el mensaje enum status st = analyze_status(status, &info); printf("Background pid: %d, command: %s, %s, info: %d \n", wpid, trabajo->command, status_strings[st], info); block_SIGCHLD(); if(st == SUSPENDED) { // Actualizamos su estado en la lista trabajo->state = STOPPED; // Si no, es que ha terminado y por tanto lo eliminamos de la lista } else { // Lo eliminamos de la lista delete_job(lista_trabajos, trabajo); } unblock_SIGCHLD(); // Le devolvemos al terminal al proceso principal set_terminal(getpid()); } } }
/** Manejador para la señal SIGCHLD **/ void manejador(int senal) { int i; // Recorremos la lista for(i = list_size(lista_trabajos); i >= 1; i--) { // Extraemos un trabajo job *aux = get_item_bypos(lista_trabajos, i); // Si no es de foreground, es decir BACKGROUND O STOPPED if(aux->state != FOREGROUND) { int status; // Vemos si ha cambiado su estado sin bloquearnos (Wait no bloqueante) // es totalmente necesario WNOHANG para no quedarnos bloqueados pid_t wpid = waitpid(aux->pgid, &status, WNOHANG | WUNTRACED); // Si es el caso if(wpid == aux->pgid) { int info; // Vemos su nuevo estado y damos el mensaje enum status st = analyze_status(status, &info); printf("Background pid: %d, command: %s, %s, info: %d \n", wpid, aux->command, status_strings[st], info); // Si se ha suspendido if(st == SUSPENDED) { // Actualizamos su estado en la lista aux->state = STOPPED; // Si no, se trata de un proceso terminado } else { if(aux->state == RESPAWNABLE) { // Restauramos las señales que reciben del terminal restore_terminal_signals(); aux->args[0] = "#"; // Volvemos a ejecutar el comando execvp(aux->command, aux->args); // Solo llegará aquí si no se ha producido el cambio de imagen printf("Error. No se ha podido hacer el respawn: %s\n", aux->command); exit(-1); } // Lo eliminamos de la lista delete_job(lista_trabajos, aux); } } } } }
void print_all_job(void) { int i; for (i = beg; i < end; i++) { if (!job[i]) continue; print_job(i); if (job[i]->state == JOB_DONE) delete_job(job[i]->pgid); } }
PR_JoinJob(PRJob *jobp) { if (!JOINABLE_JOB(jobp)) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return PR_FAILURE; } PR_Lock(jobp->tpool->join_lock); while(jobp->join_wait) PR_WaitCondVar(jobp->join_cv, PR_INTERVAL_NO_TIMEOUT); PR_Unlock(jobp->tpool->join_lock); delete_job(jobp); return PR_SUCCESS; }
const string Q::post(const string& queue_name, const string& uid, const string& data, const long run_at) { if (!this->active) return ""; if (!uid.empty()) { JobOption existing = find_job(uid); if (!existing.empty()) delete_job(uid); } Job job = Job(uid, data, JSPending, run_at); push_back(queue_name, job); q_log("posted [%s] on [%s] as [%s]", data.c_str(), queue_name.c_str(), job.uid().c_str()); return job.uid(); }
/** When the scheme is set to RR, called when the quantum timer has expired on a core. If any job should be scheduled to run on the core free'd up by the quantum expiration, return the job_number of the job that should be scheduled to run on core core_id. @param core_id the zero-based index of the core where the quantum has expired. @param time the current time of the simulator. @return job_number of the job that should be scheduled on core cord_id @return -1 if core should remain idle */ int scheduler_quantum_expired(int core_id, int time) { // Increment Time inc_time(time); // Process quantumn rollover delete_job(core_id,cores.jobs[core_id]->jid); // Schedule new job job_t* p = priqueue_poll(jobs); if ( p != NULL ) { insert_job(core_id,p); return p->jid; }//if return -1; }//scheduler_quantum_expired
static void* thr_fn(void *arg) { struct worker_t *w = (struct worker_t*)arg; struct job_t job; unsigned int sleep_time = 0, slept_time; time_t start, now; char now_str[128], ap_str[128]; struct tm now_tm, ap_tm; sigset_t mask; sigfillset(&mask); sigdelset(&mask, SIG_WORKER_INTERRUPT); sigdelset(&mask, SIG_WORKER_KILL); pthread_sigmask(SIG_BLOCK, &mask, NULL); while (!__sync_fetch_and_add(&w->exit_loop, 0)) { start = time(NULL); do { if (sleep_time == 0) sleep_time = w->interval; next_job(w, &job, &sleep_time); if (job.id > 0) w->wlog("next job[%d] start in %d seconds\n", job.id, sleep_time); sleep_time = sleep(sleep_time); if (sleep_time > 0) w->wlog("interrupt by signal, %d seconds left\n", sleep_time); } while (sleep_time > 0); now = time(NULL); slept_time = now - start; strftime(now_str, 128, "%T", localtime_r(&now, &now_tm)); if (job.id > 0) { strftime(ap_str, 128, "%T", localtime_r(&job.ap_time, &ap_tm)); w->wlog("[%s] do job[%d], appointment time[%s], slept %d seconds\n", now_str, job.id, ap_str, slept_time); delete_job(w, job.id); } else { w->wlog("[%s] slept %d seconds\n", now_str, slept_time); } } return NULL; }
/** Called when a job has completed execution. The core_id, job_number and time parameters are provided for convenience. You may be able to calculate the values with your own data structure. If any job should be scheduled to run on the core free'd up by the finished job, return the job_number of the job that should be scheduled to run on core core_id. @param core_id the zero-based index of the core where the job was located. @param job_number a globally unique identification number of the job. @param time the current time of the simulator. @return job_number of the job that should be scheduled to run on core core_id @return -1 if core should remain idle. */ int scheduler_job_finished(int core_id, int job_number, int time) { // Increment Time inc_time(time); // Process job termination job_t* p = delete_job(core_id,job_number); priqueue_remove(jobs,p); inc_wait(cur_t - p->arr_t - p->run_t); inc_turn(cur_t - p->arr_t); free_job(p); // Schedule new job p = priqueue_poll(jobs); if ( p != NULL ) { insert_job(core_id,p); return p->jid; }//if return -1; }//scheduler_job_finished
// handler for all of the signals (SIGCHLD, SIGINT, SIGTSTP) void child_signal_handler(int signum, siginfo_t* siginfo, void* extra){ if(signum == SIGCHLD){ int status, ch_pid; ch_pid = waitpid(-1, &status, WNOHANG | WUNTRACED | WCONTINUED); if(ch_pid > 0){ if(ch_pid == pipe_pid){ pipe_pid = 0; } //find which subjob(process) and which job this child process belongs to. job* this_job = find_job_pid(ch_pid, jlist); subjob* this_subjob = find_subjob(this_job, ch_pid); //handle each case of status change if(WIFEXITED(status)){ this_subjob->finished = 1; // if subjob exited normally if(job_finished(this_job)){ if(ch_pid == fg_pid){ fg_pid = 0; // if child process exited is a foreground job, reset if(tcsetpgrp(STDIN_FILENO, getpgid(0)) == -1){ perror("tcsetpgrp error 1"); } } else{ //if ch_pid was a background job message_q = add(message_q, "\n"); message_q = add(message_q, this_job->command); message_q = add(message_q, "Finished: "); } delete_job(this_job, jlist); } } else if(WIFSIGNALED(status)){ if(ch_pid == fg_pid){ fg_pid = 0; if(tcsetpgrp(STDIN_FILENO, getpgid(0)) == -1){ perror("tcsetpgrp error"); } } delete_job(this_job, jlist); //delete corresponding job } else if(WIFSTOPPED(status)){ if(ch_pid == fg_pid){ fg_pid = 0; if(tcsetpgrp(STDIN_FILENO, getpgid(ch_pid)) == -1){ perror("tcsetpgrp error 3"); } } this_subjob->stopped = 1; // set the stopped boolean to TRUE if(job_stopped(this_job)){ message_q = add(message_q, "\n"); // add stopped prompt to message q message_q = add(message_q, this_job->command); message_q = add(message_q, "Stopped: "); update_orders(jlist, this_job); // update ranking of most recent jobs } } else if(WIFCONTINUED(status)){//restart the stopped process this_subjob->stopped = 0; if(!job_stopped(this_job)){ update_orders(jlist, this_job); // update order of jobs in job_list } if(fg_pid){ if(tcsetpgrp(STDIN_FILENO, fg_pid) == -1){ perror("tcsetpgrp error 5"); } } else{ } } ch_pid = waitpid(-1, &status, WNOHANG | WUNTRACED | WCONTINUED); // wait } } if(signum == SIGINT){ //ctrl-C //if the signal is coming from the main shell, exit the shell. if(sh_pgid == getpgid(siginfo->si_pid)){ if(fg_pid){ killpg(getpgid(fg_pid), SIGINT); // kill fg process with SIGINT } } else{ killpg(0, SIGTERM); } } if(signum == SIGTSTP){ if(sh_pgid == getpgid(siginfo->si_pid)){ if(fg_pid){ killpg(getpgid(fg_pid), SIGTSTP); // kill fg process with SIGTSTP } } else{ killpg(0, SIGSTOP); } } }
PR_CancelJob(PRJob *jobp) { PRStatus rval = PR_FAILURE; PRThreadPool *tp; if (jobp->on_timerq) { /* * now, check again while holding the timerq lock */ tp = jobp->tpool; PR_Lock(tp->timerq.lock); if (jobp->on_timerq) { jobp->on_timerq = PR_FALSE; PR_REMOVE_AND_INIT_LINK(&jobp->links); tp->timerq.cnt--; PR_Unlock(tp->timerq.lock); if (!JOINABLE_JOB(jobp)) { delete_job(jobp); } else { JOIN_NOTIFY(jobp); } rval = PR_SUCCESS; } else PR_Unlock(tp->timerq.lock); } else if (jobp->on_ioq) { /* * now, check again while holding the ioq lock */ tp = jobp->tpool; PR_Lock(tp->ioq.lock); if (jobp->on_ioq) { jobp->cancel_cv = PR_NewCondVar(tp->ioq.lock); if (NULL == jobp->cancel_cv) { PR_Unlock(tp->ioq.lock); PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0); return PR_FAILURE; } /* * mark job 'cancelled' and notify io thread(s) * XXXX: * this assumes there is only one io thread; when there * are multiple threads, the io thread processing this job * must be notified. */ jobp->cancel_io = PR_TRUE; PR_Unlock(tp->ioq.lock); /* release, reacquire ioq lock */ notify_ioq(tp); PR_Lock(tp->ioq.lock); while (jobp->cancel_io) PR_WaitCondVar(jobp->cancel_cv, PR_INTERVAL_NO_TIMEOUT); PR_Unlock(tp->ioq.lock); PR_ASSERT(!jobp->on_ioq); if (!JOINABLE_JOB(jobp)) { delete_job(jobp); } else { JOIN_NOTIFY(jobp); } rval = PR_SUCCESS; } else PR_Unlock(tp->ioq.lock); } if (PR_FAILURE == rval) PR_SetError(PR_INVALID_STATE_ERROR, 0); return rval; }
/* queue a job, when a socket is readable or writeable */ static PRJob * queue_io_job(PRThreadPool *tpool, PRJobIoDesc *iod, PRJobFn fn, void * arg, PRBool joinable, io_op_type op) { PRJob *jobp; PRIntervalTime now; jobp = alloc_job(joinable, tpool); if (NULL == jobp) { return NULL; } /* * Add a new job to io_jobq * wakeup io worker thread */ jobp->job_func = fn; jobp->job_arg = arg; jobp->tpool = tpool; jobp->iod = iod; if (JOB_IO_READ == op) { jobp->io_op = JOB_IO_READ; jobp->io_poll_flags = PR_POLL_READ; } else if (JOB_IO_WRITE == op) { jobp->io_op = JOB_IO_WRITE; jobp->io_poll_flags = PR_POLL_WRITE; } else if (JOB_IO_ACCEPT == op) { jobp->io_op = JOB_IO_ACCEPT; jobp->io_poll_flags = PR_POLL_READ; } else if (JOB_IO_CONNECT == op) { jobp->io_op = JOB_IO_CONNECT; jobp->io_poll_flags = PR_POLL_WRITE|PR_POLL_EXCEPT; } else { delete_job(jobp); PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return NULL; } jobp->timeout = iod->timeout; if ((PR_INTERVAL_NO_TIMEOUT == iod->timeout) || (PR_INTERVAL_NO_WAIT == iod->timeout)) { jobp->absolute = iod->timeout; } else { now = PR_IntervalNow(); jobp->absolute = now + iod->timeout; } PR_Lock(tpool->ioq.lock); if (PR_CLIST_IS_EMPTY(&tpool->ioq.list) || (PR_INTERVAL_NO_TIMEOUT == iod->timeout)) { PR_APPEND_LINK(&jobp->links,&tpool->ioq.list); } else if (PR_INTERVAL_NO_WAIT == iod->timeout) { PR_INSERT_LINK(&jobp->links,&tpool->ioq.list); } else { PRCList *qp; PRJob *tmp_jobp; /* * insert into the timeout-sorted ioq */ for (qp = tpool->ioq.list.prev; qp != &tpool->ioq.list; qp = qp->prev) { tmp_jobp = JOB_LINKS_PTR(qp); if ((PRInt32)(jobp->absolute - tmp_jobp->absolute) >= 0) { break; } } PR_INSERT_AFTER(&jobp->links,qp); } jobp->on_ioq = PR_TRUE; tpool->ioq.cnt++; /* * notify io worker thread(s) */ PR_Unlock(tpool->ioq.lock); notify_ioq(tpool); return jobp; }
/* * worker thread function */ static void wstart(void *arg) { PRThreadPool *tp = (PRThreadPool *) arg; PRCList *head; /* * execute jobs until shutdown */ while (!tp->shutdown) { PRJob *jobp; #ifdef OPT_WINNT BOOL rv; DWORD unused, shutdown; LPOVERLAPPED olp; PR_Lock(tp->jobq.lock); tp->idle_threads++; PR_Unlock(tp->jobq.lock); rv = GetQueuedCompletionStatus(tp->jobq.nt_completion_port, &unused, &shutdown, &olp, INFINITE); PR_ASSERT(rv); if (shutdown) break; jobp = ((NT_notifier *) olp)->jobp; PR_Lock(tp->jobq.lock); tp->idle_threads--; tp->jobq.cnt--; PR_Unlock(tp->jobq.lock); #else PR_Lock(tp->jobq.lock); while (PR_CLIST_IS_EMPTY(&tp->jobq.list) && (!tp->shutdown)) { tp->idle_threads++; PR_WaitCondVar(tp->jobq.cv, PR_INTERVAL_NO_TIMEOUT); tp->idle_threads--; } if (tp->shutdown) { PR_Unlock(tp->jobq.lock); break; } head = PR_LIST_HEAD(&tp->jobq.list); /* * remove job from queue */ PR_REMOVE_AND_INIT_LINK(head); tp->jobq.cnt--; jobp = JOB_LINKS_PTR(head); PR_Unlock(tp->jobq.lock); #endif jobp->job_func(jobp->job_arg); if (!JOINABLE_JOB(jobp)) { delete_job(jobp); } else { JOIN_NOTIFY(jobp); } } PR_Lock(tp->jobq.lock); tp->current_threads--; PR_Unlock(tp->jobq.lock); }
PR_JoinThreadPool(PRThreadPool *tpool) { PRStatus rval = PR_SUCCESS; PRCList *head; PRStatus rval_status; PR_Lock(tpool->jobq.lock); while (!tpool->shutdown) PR_WaitCondVar(tpool->shutdown_cv, PR_INTERVAL_NO_TIMEOUT); /* * wakeup worker threads */ #ifdef OPT_WINNT /* * post shutdown notification for all threads */ { int i; for(i=0; i < tpool->current_threads; i++) { PostQueuedCompletionStatus(tpool->jobq.nt_completion_port, 0, TRUE, NULL); } } #else PR_NotifyAllCondVar(tpool->jobq.cv); #endif /* * wakeup io thread(s) */ notify_ioq(tpool); /* * wakeup timer thread(s) */ PR_Lock(tpool->timerq.lock); notify_timerq(tpool); PR_Unlock(tpool->timerq.lock); while (!PR_CLIST_IS_EMPTY(&tpool->jobq.wthreads)) { wthread *wthrp; head = PR_LIST_HEAD(&tpool->jobq.wthreads); PR_REMOVE_AND_INIT_LINK(head); PR_Unlock(tpool->jobq.lock); wthrp = WTHREAD_LINKS_PTR(head); rval_status = PR_JoinThread(wthrp->thread); PR_ASSERT(PR_SUCCESS == rval_status); PR_DELETE(wthrp); PR_Lock(tpool->jobq.lock); } PR_Unlock(tpool->jobq.lock); while (!PR_CLIST_IS_EMPTY(&tpool->ioq.wthreads)) { wthread *wthrp; head = PR_LIST_HEAD(&tpool->ioq.wthreads); PR_REMOVE_AND_INIT_LINK(head); wthrp = WTHREAD_LINKS_PTR(head); rval_status = PR_JoinThread(wthrp->thread); PR_ASSERT(PR_SUCCESS == rval_status); PR_DELETE(wthrp); } while (!PR_CLIST_IS_EMPTY(&tpool->timerq.wthreads)) { wthread *wthrp; head = PR_LIST_HEAD(&tpool->timerq.wthreads); PR_REMOVE_AND_INIT_LINK(head); wthrp = WTHREAD_LINKS_PTR(head); rval_status = PR_JoinThread(wthrp->thread); PR_ASSERT(PR_SUCCESS == rval_status); PR_DELETE(wthrp); } /* * Delete queued jobs */ while (!PR_CLIST_IS_EMPTY(&tpool->jobq.list)) { PRJob *jobp; head = PR_LIST_HEAD(&tpool->jobq.list); PR_REMOVE_AND_INIT_LINK(head); jobp = JOB_LINKS_PTR(head); tpool->jobq.cnt--; delete_job(jobp); } /* delete io jobs */ while (!PR_CLIST_IS_EMPTY(&tpool->ioq.list)) { PRJob *jobp; head = PR_LIST_HEAD(&tpool->ioq.list); PR_REMOVE_AND_INIT_LINK(head); tpool->ioq.cnt--; jobp = JOB_LINKS_PTR(head); delete_job(jobp); } /* delete timer jobs */ while (!PR_CLIST_IS_EMPTY(&tpool->timerq.list)) { PRJob *jobp; head = PR_LIST_HEAD(&tpool->timerq.list); PR_REMOVE_AND_INIT_LINK(head); tpool->timerq.cnt--; jobp = JOB_LINKS_PTR(head); delete_job(jobp); } PR_ASSERT(0 == tpool->jobq.cnt); PR_ASSERT(0 == tpool->ioq.cnt); PR_ASSERT(0 == tpool->timerq.cnt); delete_threadpool(tpool); return rval; }
job_t* readcmdline(char *msg) { fprintf(stdout, "%s", msg); char *cmdline = (char *)calloc(MAX_LEN_CMDLINE, sizeof(char)); if(!cmdline) { fprintf(stderr, "%s\n","malloc: no space"); return NULL; } fgets(cmdline, MAX_LEN_CMDLINE, stdin); /* sequence is true only when the command line contains ; */ bool sequence = false; /* seq_pos is used for storing the command line before ; */ int seq_pos = 0; int cmdline_pos = 0; /*iterator for command line; */ job_t *first_job = NULL; while(1) { job_t *current_job = find_last_job(first_job); int cmd_pos = 0; /* iterator for a command */ int iofile_seek = 0; /*iofile_seek for file */ bool valid_input = true; /* check for valid input */ bool end_of_input = false; /* check for end of input */ /* cmdline is NOOP, i.e., just return with spaces */ while (isspace(cmdline[cmdline_pos])){++cmdline_pos;} /* ignore any spaces */ if(cmdline[cmdline_pos] == '\n' || cmdline[cmdline_pos] == '\0' || feof(stdin)) return NULL; /* Check for invalid special symbols (characters) */ if(cmdline[cmdline_pos] == ';' || cmdline[cmdline_pos] == '&' || cmdline[cmdline_pos] == '<' || cmdline[cmdline_pos] == '>' || cmdline[cmdline_pos] == '|') return NULL; char *cmd = (char *)calloc(MAX_LEN_CMDLINE, sizeof(char)); if(!cmd) { fprintf(stderr, "%s\n","malloc: no space"); return NULL; } job_t *newjob = (job_t *)malloc(sizeof(job_t)); if(!newjob) { fprintf(stderr, "%s\n","malloc: no space"); return NULL; } if(!first_job) first_job = current_job = newjob; else { current_job->next = newjob; current_job = current_job->next; } if(!init_job(current_job)) { fprintf(stderr, "%s\n","malloc: no space"); delete_job(current_job,first_job); return NULL; } process_t *newprocess = (process_t *)malloc(sizeof(process_t)); if(!newprocess) { fprintf(stderr, "%s\n","malloc: no space"); delete_job(current_job,first_job); return NULL; } if(!init_process(newprocess)){ fprintf(stderr, "%s\n","malloc: no space"); delete_job(current_job,first_job); return NULL; } process_t *current_process = NULL; if(!current_job->first_process) current_process = current_job->first_process = newprocess; else { current_process->next = newprocess; current_process = current_process->next; } while(cmdline[cmdline_pos] != '\n' && cmdline[cmdline_pos] != '\0') { switch (cmdline[cmdline_pos]) { case '<': /* input redirection */ current_process->ifile = (char *) calloc(MAX_LEN_FILENAME, sizeof(char)); if(!current_process->ifile) { fprintf(stderr, "%s\n","malloc: no space"); delete_job(current_job,first_job); return NULL; } ++cmdline_pos; while (isspace(cmdline[cmdline_pos])){++cmdline_pos;} /* ignore any spaces */ iofile_seek = 0; while(cmdline[cmdline_pos] != '\0' && !isspace(cmdline[cmdline_pos])){ if(MAX_LEN_FILENAME == iofile_seek) { fprintf(stderr, "%s\n","malloc: no space"); delete_job(current_job,first_job); return NULL; } current_process->ifile[iofile_seek++] = cmdline[cmdline_pos++]; } current_process->ifile[iofile_seek] = '\0'; current_job->mystdin = INPUT_FD; while(isspace(cmdline[cmdline_pos])) { if(cmdline[cmdline_pos] == '\n') break; ++cmdline_pos; } valid_input = false; break; case '>': /* output redirection */ current_process->ofile = (char *) calloc(MAX_LEN_FILENAME, sizeof(char)); if(!current_process->ofile) { fprintf(stderr, "%s\n","malloc: no space"); delete_job(current_job,first_job); return NULL; } ++cmdline_pos; while (isspace(cmdline[cmdline_pos])){++cmdline_pos;} /* ignore any spaces */ iofile_seek = 0; while(cmdline[cmdline_pos] != '\0' && !isspace(cmdline[cmdline_pos])){ if(MAX_LEN_FILENAME == iofile_seek) { fprintf(stderr, "%s\n","malloc: no space"); delete_job(current_job,first_job); return NULL; } current_process->ofile[iofile_seek++] = cmdline[cmdline_pos++]; } current_process->ofile[iofile_seek] = '\0'; current_job->mystdout = OUTPUT_FD; while(isspace(cmdline[cmdline_pos])) { if(cmdline[cmdline_pos] == '\n') break; ++cmdline_pos; } valid_input = false; break; case '|': /* pipeline */ cmd[cmd_pos] = '\0'; process_t *newprocess = (process_t *)malloc(sizeof(process_t)); if(!newprocess) { fprintf(stderr, "%s\n","malloc: no space"); delete_job(current_job,first_job); return NULL; } if(!init_process(newprocess)) { fprintf(stderr, "%s\n","init_process: failed"); delete_job(current_job,first_job); return NULL; } if(!readprocessinfo(current_process, cmd)) { fprintf(stderr, "%s\n","parse cmd: error"); delete_job(current_job,first_job); return NULL; } current_process->next = newprocess; current_process = current_process->next; ++cmdline_pos; cmd_pos = 0; /*Reinitialze for new cmd */ valid_input = true; break; case '&': /* background job */ current_job->bg = true; while (isspace(cmdline[cmdline_pos])){++cmdline_pos;} /* ignore any spaces */ if(cmdline[cmdline_pos+1] != '\n' && cmdline[cmdline_pos+1] != '\0') fprintf(stderr, "reading bg: extra input ignored"); end_of_input = true; break; case ';': /* sequence of jobs*/ sequence = true; strncpy(current_job->commandinfo,cmdline+seq_pos,cmdline_pos-seq_pos); seq_pos = cmdline_pos + 1; break; case '#': /* comment */ end_of_input = true; break; default: if(!valid_input) { fprintf(stderr, "%s\n", "reading cmdline: could not fathom input"); delete_job(current_job,first_job); return NULL; } if(cmd_pos == MAX_LEN_CMDLINE-1) { fprintf(stderr,"%s\n","reading cmdline: length exceeds the max limit"); delete_job(current_job,first_job); return NULL; } cmd[cmd_pos++] = cmdline[cmdline_pos++]; break; } if(end_of_input || sequence) break; } cmd[cmd_pos] = '\0'; if(!readprocessinfo(current_process, cmd)) { fprintf(stderr,"%s\n","read process info: error"); delete_job(current_job,first_job); return NULL; } if(!sequence) { strncpy(current_job->commandinfo,cmdline+seq_pos,cmdline_pos-seq_pos); break; } sequence = false; ++cmdline_pos; } return first_job; }
/* * builtin_cmd - If the user has typed a built-in command then execute * it immediately. */ bool builtin_cmd(job_t *last_job, int argc, char **argv) { /* check whether the cmd is a built in command */ if (!strcmp("quit", argv[0])) { /* Your code here */ exit(EXIT_SUCCESS); } else if (!strcmp("jobs", argv[0])) { /* Your code here */ job_t* currentJob = active_jobs_head; job_t* deletedJob = NULL; while(currentJob != NULL) { // print active jobs and then change notified to 0 //if((currentJob->first_process)->completed == true && currentJob->notified == false) { //need to check if every process has completed for a job to be complete, not just the first process if (job_is_completed(currentJob) == true) { printf("%d (Completed): %s\n", currentJob->pgid, currentJob->commandinfo); deletedJob = currentJob; //currentJob->notified = true; } //otherwise it is stopped else if (job_is_stopped(currentJob) == true) { printf("%d (Stopped): %s\n", currentJob->pgid, currentJob->commandinfo); } else { printf("%d (Running): %s\n", currentJob->pgid, currentJob->commandinfo); } currentJob = currentJob->next; // delete job after it is completed, don't need to save notified if (deletedJob != NULL) { if (deletedJob == active_jobs_head) { active_jobs_head = deletedJob->next; free_job(deletedJob); //TBD warning about this? } else { delete_job(deletedJob, active_jobs_head); } deletedJob = NULL; } } return true; } else if (!strcmp("cd", argv[0])) { int chdir_return = chdir(argv[1]); if(chdir_return == -1) { printf("cd: %s: No such file or directory\n", argv[1]); } return true; } else if (!strcmp("bg", argv[0])) { /* Your code here */ job_t* currentJob = active_jobs_head; process_t* p2; if(argv[1] == NULL) { // continue most recent stopped job //use find_last_job currentJob = find_last_job(active_jobs_head); continue_job(currentJob); seize_tty(currentJob->pgid); p2 = currentJob->first_process; while(p2 != NULL) { p2->stopped = false; struct sigaction action; action.sa_sigaction = sighandler; sigfillset(&action.sa_mask); action.sa_flags = SA_SIGINFO; sigaction(SIGCHLD, &action, NULL); p2 = p2->next; } seize_tty(getpid()); } else { pid_t job_number = atoi(argv[1]); while(currentJob != NULL) { // Need to eventually iterate through all processes? if((job_is_stopped(currentJob)) && currentJob->pgid == job_number) { //seize_tty(currentJob->pgid); continue_job(currentJob); seize_tty(currentJob->pgid); p2 = currentJob->first_process; while (p2 != NULL) { p2->stopped = false; struct sigaction action; action.sa_sigaction = sighandler; sigfillset(&action.sa_mask); action.sa_flags = SA_SIGINFO; sigaction(SIGCHLD, &action, NULL); p2 = p2->next; } seize_tty(getpid()); break; } else if (currentJob->pgid == job_number) { printf("%s\n", "This process wasn't stopped`"); } else { printf("%s\n", "This job number is not the requested one"); } currentJob = currentJob->next; } } return true; } else if (!strcmp("fg", argv[0])) { /* Your code here */ job_t* currentJob = active_jobs_head; process_t* p2; if(argv[1] == NULL) { // continue most recent stopped job //use find_last_job currentJob = find_last_job(active_jobs_head); continue_job(currentJob); seize_tty(currentJob->pgid); p2 = currentJob->first_process; while(p2 != NULL) { waiting(p2); p2 = p2->next; } seize_tty(getpid()); } else { pid_t job_number = atoi(argv[1]); while(currentJob != NULL) { if((job_is_stopped(currentJob)) && currentJob->pgid == job_number) { //seize_tty(currentJob->pgid); continue_job(currentJob); seize_tty(currentJob->pgid); p2 = currentJob->first_process; while (p2 != NULL) { waiting(p2); p2 = p2->next; } seize_tty(getpid()); break; } else if (currentJob->pgid == job_number) { printf("%s\n", "This process wasn't stopped`"); } else { printf("%s\n", "This job number is not the requested one"); } currentJob = currentJob->next; } } return true; } /* not a builtin command */ return false; }