/* Make j the last async process * * If jobs are compiled in then this routine expects sigchld to be blocked. */ static void j_set_async(Job *j) { Job *jl, *oldest; if (async_job && (async_job->flags & (JF_KNOWN|JF_ZOMBIE)) == JF_ZOMBIE) remove_job(async_job, "async"); if (!(j->flags & JF_STARTED)) { internal_errorf(0, "j_async: job not started"); return; } async_job = j; async_pid = j->last_proc->pid; while (nzombie > child_max) { oldest = (Job *) 0; for (jl = job_list; jl; jl = jl->next) if (jl != async_job && (jl->flags & JF_ZOMBIE) && (!oldest || jl->age < oldest->age)) oldest = jl; if (!oldest) { /* XXX debugging */ if (!(async_job->flags & JF_ZOMBIE) || nzombie != 1) { internal_errorf(0, "j_async: bad nzombie (%d)", nzombie); nzombie = 0; } break; } remove_job(oldest, "zombie"); } }
int close_quejob_by_jobid( char *job_id) { int rc = PBSE_NONE; job *pjob = NULL; if (LOGLEVEL >= 10) { LOG_EVENT(PBSEVENT_JOB, PBS_EVENTCLASS_JOB, __func__, job_id); } if ((pjob = svr_find_job(job_id, FALSE)) == NULL) { rc = PBSE_JOBNOTFOUND; return(rc); } mutex_mgr pjob_mutex = mutex_mgr(pjob->ji_mutex, true); if (pjob->ji_qs.ji_substate != JOB_SUBSTATE_TRANSICM) { remove_job(&newjobs,pjob); svr_job_purge(pjob); pjob = NULL; } else if (pjob->ji_qs.ji_svrflags & JOB_SVFLG_HERE) { remove_job(&newjobs,pjob); pjob->ji_qs.ji_state = JOB_STATE_QUEUED; pjob->ji_qs.ji_substate = JOB_SUBSTATE_QUEUED; rc = svr_enquejob(pjob, FALSE, -1, false); if ((rc == PBSE_JOBNOTFOUND) || (rc == PBSE_JOB_RECYCLED)) { pjob = NULL; } else if (rc != PBSE_NONE) { job_abt(&pjob, msg_err_noqueue); pjob = NULL; } } if (pjob == NULL) pjob_mutex.set_lock_on_exit(false); return(rc); } /* close_quejob_by_jobid() */
/* Displays the command strings and status for all current jobs */ void builtin_jobs() { job_t* j; job_t* prev; //Previous point needed because need to remove jobs AFTER getting next job in list int i; for (prev = NULL, j=first_job, i = 1; j; prev = j, j=j->next, i++){ //for each job, print status, then remove if completed fprintf(stdout, "[%d] %d(%s): %s\n", i, j->pgid, job_status(j), j->commandinfo); if (prev && job_is_completed(prev)) remove_job(prev); } if (prev && job_is_completed(prev)){ remove_job(prev); } }
static int remove_queued_job(int id) { struct queue *q = NULL; int err = -ENXIO; if (id < 0) return -EINVAL; mutex_lock(&qmutex); INFO("removing job[%d]", id); if (qlen > 0) { q = remove_job(id); if (q) { qlen--; destroy_job(q->job); kfree(q); err = 0; INFO("job [%d] removed", id); wake_up_all(&pwq); } } mutex_unlock(&qmutex); return err; }
/* list jobs for top-level notification */ void j_notify(void) { Job *j, *tmp; sigset_t omask; sigprocmask(SIG_BLOCK, &sm_sigchld, &omask); for (j = job_list; j; j = j->next) { #ifdef JOBS if (Flag(FMONITOR) && (j->flags & JF_CHANGED)) j_print(j, JP_MEDIUM, shl_out); #endif /* JOBS */ /* Remove job after doing reports so there aren't * multiple +/- jobs. */ if (j->state == PEXITED || j->state == PSIGNALLED) j->flags |= JF_REMOVE; } for (j = job_list; j; j = tmp) { tmp = j->next; if (j->flags & JF_REMOVE) remove_job(j, "notify"); } shf_flush(shl_out); sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); }
void *remove_some_recycle_jobs( void *vp) { int i; int iter = -1; job *pjob = NULL; pthread_mutex_lock(recycler.rc_mutex); for (i = 0; i < JOBS_TO_REMOVE; i++) { pjob = next_job_from_recycler(&recycler.rc_jobs,&iter); if (pjob == NULL) break; if (LOGLEVEL >= 10) log_event(PBSEVENT_JOB, PBS_EVENTCLASS_JOB, __func__, pjob->ji_qs.ji_jobid); remove_job(&recycler.rc_jobs, pjob); unlock_ji_mutex(pjob, __func__, (char *)"1", LOGLEVEL); free(pjob->ji_mutex); memset(pjob, 255, sizeof(job)); free(pjob); } pthread_mutex_unlock(recycler.rc_mutex); return(NULL); } /* END remove_some_recycle_jobs() */
/*- *----------------------------------------------------------------------- * Job_CatchChildren -- * Handle the exit of a child. Called by handle_running_jobs * * Side Effects: * The job descriptor is removed from the list of children. * * Notes: * We do waits, blocking or not, according to the wisdom of our * caller, until there are no more children to report. For each * job, call process_job_status to finish things off. *----------------------------------------------------------------------- */ void Job_CatchChildren() { pid_t pid; /* pid of dead child */ LstNode jnode; /* list element for finding job */ int status; /* Exit/termination status */ /* * Don't even bother if we know there's no one around. */ if (nJobs == 0) return; while ((pid = waitpid(WAIT_ANY, &status, WNOHANG)) > 0) { handle_all_signals(); jnode = Lst_Find(&runningJobs, JobCmpPid, &pid); if (jnode == NULL) { Error("Child (%ld) not in table?", (long)pid); } else { remove_job(jnode, status); } } }
void work_fail(Job *job) { MemBlock *block = new_response(MSG_WORK_FAIL, strlen(job->handle), (unsigned char*)job->handle); incRef(block); // Make sure the first listener doesn't decRef to 0 causing the block to be returned g_ptr_array_foreach(job->listeners, (GFunc)client_send, block); decRef(block); remove_job(job); }
static PCOMP_CONTEXT win9x_get_connection(PCOMP_CONTEXT context) { apr_os_sock_info_t sockinfo; int len, salen; #if APR_HAVE_IPV6 salen = sizeof(struct sockaddr_in6); #else salen = sizeof(struct sockaddr_in); #endif if (context == NULL) { /* allocate the completion context and the transaction pool */ apr_allocator_t *allocator; apr_thread_mutex_lock(child_lock); context = apr_pcalloc(pchild, sizeof(COMP_CONTEXT)); apr_allocator_create(&allocator); apr_allocator_max_free_set(allocator, ap_max_mem_free); apr_pool_create_ex(&context->ptrans, pchild, NULL, allocator); apr_allocator_owner_set(allocator, context->ptrans); apr_pool_tag(context->ptrans, "transaction"); apr_thread_mutex_unlock(child_lock); } while (1) { apr_pool_clear(context->ptrans); context->ba = apr_bucket_alloc_create(context->ptrans); context->accept_socket = remove_job(); if (context->accept_socket == INVALID_SOCKET) { return NULL; } len = salen; context->sa_server = apr_palloc(context->ptrans, len); if (getsockname(context->accept_socket, context->sa_server, &len)== SOCKET_ERROR) { ap_log_error(APLOG_MARK, APLOG_WARNING, apr_get_netos_error(), ap_server_conf, "getsockname failed"); continue; } len = salen; context->sa_client = apr_palloc(context->ptrans, len); if ((getpeername(context->accept_socket, context->sa_client, &len)) == SOCKET_ERROR) { ap_log_error(APLOG_MARK, APLOG_WARNING, apr_get_netos_error(), ap_server_conf, "getpeername failed"); memset(&context->sa_client, '\0', sizeof(context->sa_client)); } sockinfo.os_sock = &context->accept_socket; sockinfo.local = context->sa_server; sockinfo.remote = context->sa_client; sockinfo.family = context->sa_server->sa_family; sockinfo.type = SOCK_STREAM; apr_os_sock_make(&context->sock, &sockinfo, context->ptrans); return context; } }
int remove_job_by_pid(job *jobs, pid_t pid) { int jid = pid_to_jid(jobs, pid); if(jid >= 0) { remove_job(jobs, jid); return jid; } else { return -1; } }
END_TEST START_TEST(remove_job_test) { all_jobs alljobs; int result; struct job *test_job = job_alloc(); result = remove_job(NULL,test_job); fail_unless(result != PBSE_NONE, "remove from null array fail"); result = remove_job(&alljobs,NULL); fail_unless(result != PBSE_NONE, "NULL job remove fail"); insert_job(&alljobs,test_job); result = remove_job(&alljobs,test_job); fail_unless(result == PBSE_NONE, "job remove fail"); }
/* * The scheduler must be called within a critical section since it * changes global state, and since dispatch() needs to be called * within a critical section. Disable_count for current_running is * checked to see that it's != 0. The scheduler also handles saving * the current interrupt controller mask (which is later restored in * setup_current_running()). */ void scheduler(void) { unsigned long long t; /* * Save hardware interrupt mask in the pcb struct. The mask * will be restored in setup_current_running() */ current_running->int_controller_mask = ((uint16_t)inb(0x21)) | (((uint16_t)inb(0xa1)) << 8); ASSERT(current_running->disable_count != 0); do { switch (current_running->status) { case SLEEPING: t = get_timer(); if (current_running->wakeup_time < t) current_running->status = RUNNING; /* FALLTHROUGH */ case RUNNING: /* pick the next job to run */ current_running = current_running->next; break; case BLOCKED: /* if no more jobs, halt */ if (current_running->next == current_running) { HALT("No more jobs."); } current_running = current_running->next; /* Remove the job from the ready queue */ remove_job(current_running->previous); break; case EXITED: /* if no more jobs, loop forever */ if (current_running->next == current_running) { HALT("No more jobs."); } current_running = current_running->next; /* * Remove pcb from the ready queue and insert * it into the free_pcb queue */ free_pcb(current_running->previous); break; default: HALT("Invalid job status."); break; } } while (current_running->status != RUNNING); /* .. and run it */ dispatch(); }
static mono_native_thread_return_t thread_func (void *thread_data) { thread_init_func (thread_data); mono_mutex_lock (&lock); for (;;) { /* * It's important that we check the continue idle flag with the lock held. * Suppose we didn't check with the lock held, and the result is FALSE. The * main thread might then set continue idle and signal us before we can take * the lock, and we'd lose the signal. */ gboolean do_idle = continue_idle_job (); SgenThreadPoolJob *job = get_job_and_set_in_progress (); if (!job && !do_idle) { /* * pthread_cond_wait() can return successfully despite the condition * not being signalled, so we have to run this in a loop until we * really have work to do. */ mono_cond_wait (&work_cond, &lock); continue; } mono_mutex_unlock (&lock); if (job) { job->func (thread_data, job); mono_mutex_lock (&lock); SGEN_ASSERT (0, job->state == STATE_IN_PROGRESS, "The job should still be in progress."); job->state = STATE_DONE; remove_job (job); /* * Only the main GC thread will ever wait on the done condition, so we don't * have to broadcast. */ mono_cond_signal (&done_cond); } else { SGEN_ASSERT (0, do_idle, "Why did we unlock if we still have to wait for idle?"); SGEN_ASSERT (0, idle_job_func, "Why do we have idle work when there's no idle job function?"); do { idle_job_func (thread_data); do_idle = continue_idle_job (); } while (do_idle && !job_queue.next_slot); mono_mutex_lock (&lock); if (!do_idle) mono_cond_signal (&done_cond); } } }
static unsigned int is_job_done (pid_t pid, unsigned int print, unsigned int details) { int status; int idx = index_of (pid); job *j = get_job (idx); const char l = (j == list->tail) ? '+' : '-'; pid_t p = waitpid (pid, &status, WNOHANG|WUNTRACED); if (p == -1) { warn ("jobs [%d] %d (%s)", j->content->job, j->content->pid, j->content->cmd); remove_job (idx); return TRUE; } if (j == NULL) { fprintf (stderr, "'%d': no such job\n", pid); return TRUE; } if (j->content->stopped && print) { if (details) { int i; fprintf (stdout, "[%d] %c %d suspended: %s", j->content->job, l, pid, j->content->cmd); for (i = 0; i < j->content->argc; i++) { char q; switch (j->content->protected[i]) { case NONE: q = '\0'; break; case DOUBLE_QUOTE: q = '"'; break; case SINGLE_QUOTE: q = '\''; } fprintf (stdout, " %c%s%c", q, j->content->argv[i], q); } fprintf (stdout, "\n"); } else { fprintf (stdout, "[%d] %c %d (%s) suspended\n", j->content->job, l, pid, j->content->cmd); } /* well, it's a lie but we don't want to print it twice */ return TRUE; }
void handle_child_death(int sig) { signal(SIGCHLD, handle_child_death); int status; int p; sig = sig+1; while((p=waitpid(-1, &status, WNOHANG)) != -1) { remove_job(p); } }
void execute_job(job_t* job) { /*Check commandline for built-in commands*/ if (check_command(job, "cd")) { //change directory - alter current directory and remove completed job chdir(job->first_process->argv[1]); remove_job(job); } else if (check_command(job, "jobs")) { //display current jobs and their statuses (stati?) remove_job(job); builtin_jobs(); } else if (check_command(job, "bg")) { //resume background job with specified number resume_background_job(atoi(job->first_process->argv[1])); //atoi interprets string as integer value remove_job(job); } else if (check_command(job, "fg")) { //continue foreground job with specified number resume_foreground_job(atoi(job->first_process->argv[1])); remove_job(job); } else { //Default case, not built in command - spawn the new job spawn_job(job, !job->bg); } }
/* list jobs for jobs built-in */ int j_jobs(const char *cp, int slp, int nflag) /* 0: short, 1: long, 2: pgrp */ { Job *j, *tmp; int how; int zflag = 0; sigset_t omask; sigprocmask(SIG_BLOCK, &sm_sigchld, &omask); if (nflag < 0) { /* kludge: print zombies */ nflag = 0; zflag = 1; } if (cp) { int ecode; if ((j = j_lookup(cp, &ecode)) == (Job *) 0) { sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); bi_errorf("%s: %s", cp, lookup_msgs[ecode]); return 1; } } else j = job_list; how = slp == 0 ? JP_MEDIUM : (slp == 1 ? JP_LONG : JP_PGRP); for (; j; j = j->next) { if ((!(j->flags & JF_ZOMBIE) || zflag) && (!nflag || (j->flags & JF_CHANGED))) { j_print(j, how, shl_stdout); if (j->state == PEXITED || j->state == PSIGNALLED) j->flags |= JF_REMOVE; } if (cp) break; } /* Remove jobs after printing so there won't be multiple + or - jobs */ for (j = job_list; j; j = tmp) { tmp = j->next; if (j->flags & JF_REMOVE) remove_job(j, "jobs"); } sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); return 0; }
void wait_foreground_job(struct job* job) { int status, pid; tcsetpgrp(shell_in, job->pgid); /* bring group foreground */ do { pid = waitpid(-1, &status, WUNTRACED); } while (jobs_update_status(pid, status) && !job_stopped(job)); /* Wait until job is stopped */ /* If the job is done, remove it from the list */ if (job_completed(job)) { remove_job(job); } /* bring shell to foreground */ tcsetpgrp(shell_in, shell_pgid); tcsetattr(shell_in, TCSADRAIN, &io_flags); }
void stop_all_listening(Client *cli) { if (!cli->listening) return; int i; Job *job; for(i = 0; i < cli->listening->len; i++) { job = g_ptr_array_index(cli->listening, i); g_ptr_array_remove_fast(job->listeners, cli); if (!job->background && job->listeners->len == 0) { #if DEBUG g_debug("[%s] removing non-background job with no listeners: %s", cli->id, job->handle); #endif remove_job(job); } } client_clear_listening(cli); }
/**************************************************************************** Message Handler: work_fail(handle) ****************************************************************************/ int msg_work_fail(Client *cli, MemBlock *block) { Job *job = g_hash_table_lookup(g_jobs, block->bytes + HEADER_SIZE); if (!job || job->worker != cli) { #if DEBUG g_debug("[%s] work_fail (%s) - not_worker", cli->id, block->bytes + HEADER_SIZE); #endif client_send(cli, new_error_response("not_worker", "")); return 0; } #if DEBUG g_debug("[%s] work_fail (%s)", cli->id, block->bytes + HEADER_SIZE); #endif set_message_magic(block, MAGIC_RESPONSE); g_ptr_array_foreach(job->listeners, (GFunc)client_send, block); remove_job(job); return 0; }
void handle_all_jobs_output(void) { int nfds; struct timeval timeout; LstNode ln, ln2; Job *job; int i; int status; /* no jobs */ if (Lst_IsEmpty(&runningJobs)) return; (void)fflush(stdout); memcpy(actual_mask, output_mask, mask_size); timeout.tv_sec = SEL_SEC; timeout.tv_usec = SEL_USEC; nfds = select(largest_fd+1, actual_mask, NULL, NULL, &timeout); handle_all_signals(); for (ln = Lst_First(&runningJobs); nfds && ln != NULL; ln = ln2) { ln2 = Lst_Adv(ln); job = (Job *)Lst_Datum(ln); job->flags &= ~JOB_DIDOUTPUT; for (i = 1; i >= 0; i--) { if (FD_ISSET(job->in[i].fd, actual_mask)) { nfds--; handle_job_output(job, i, false); } } if (job->flags & JOB_DIDOUTPUT) { if (waitpid(job->pid, &status, WNOHANG) == job->pid) { remove_job(ln, status); } else { Lst_Requeue(&runningJobs, ln); } } } }
int consumer(void *data){ struct job *job = NULL; int err = 0; top: /* waiting for jobs */ wait_event_interruptible(consumers, prod_cons_q_len > 0); /* module exit, killing the thread */ if(thread_exit == 1) goto exit; mutex_lock(&big_mutex); if(prod_cons_q_len > 0){ job = remove_job(prod_cons_q); if(IS_ERR(job)){ err = PTR_ERR(job); goto out; } prod_cons_q_len--; } mutex_unlock(&big_mutex); wake_up_all(&producers); err = process_job(job); schedule(); goto top; out: mutex_unlock(&big_mutex); exit: return err; }
void *remove_some_recycle_jobs( void *vp) { int i; all_jobs_iterator *iter = NULL; job *pjob = NULL; pthread_mutex_lock(recycler.rc_mutex); recycler.rc_jobs.lock(); iter = recycler.rc_jobs.get_iterator(); recycler.rc_jobs.unlock(); for (i = 0; i < JOBS_TO_REMOVE; i++) { pjob = next_job_from_recycler(&recycler.rc_jobs,iter); if (pjob == NULL) break; if (LOGLEVEL >= 10) log_event(PBSEVENT_JOB, PBS_EVENTCLASS_JOB, __func__, pjob->ji_qs.ji_jobid); pjob->ji_being_recycled = FALSE; //Need to set the being_recycled flag to false or //or remove_job won't remove it. remove_job(&recycler.rc_jobs, pjob); unlock_ji_mutex(pjob, __func__, "1", LOGLEVEL); free(pjob->ji_mutex); memset(pjob, 255, sizeof(job)); free(pjob); } pthread_mutex_unlock(recycler.rc_mutex); if (iter != NULL) delete iter; return(NULL); } /* END remove_some_recycle_jobs() */
/* list jobs for top-level notification */ void j_notify(void) { Job *j, *tmp; sigset_t omask; sigprocmask(SIG_BLOCK, &sm_sigchld, &omask); for (j = job_list; j; j = j->next) { /* Remove job after doing reports so there aren't * multiple +/- jobs. */ if (j->state == PEXITED || j->state == PSIGNALLED) j->flags |= JF_REMOVE; } for (j = job_list; j; j = tmp) { tmp = j->next; if (j->flags & JF_REMOVE) remove_job(j, "notify"); } shf_flush(shl_out); sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); }
/**************************************************************************** Message Handler: work_complete(handle, result) ****************************************************************************/ int msg_work_complete(Client *cli, MemBlock *block) { char *handle = (char*)block->bytes + HEADER_SIZE; Job *job = g_hash_table_lookup(g_jobs, handle); if (!job || job->worker != cli) { #if DEBUG g_debug("[%s] work_complete (%s) - not_worker", cli->id, handle); #endif client_send(cli, new_error_response("not_worker", job?"You don't own this job":"Unknown job")); return 0; } #if DEBUG g_debug("[%s] work_complete (%s) : %ld bytes", cli->id, handle, block->nbytes - HEADER_SIZE - strlen(handle) - 1); #endif set_message_magic(block, MAGIC_RESPONSE); g_ptr_array_foreach(job->listeners, (GFunc)client_send, block); remove_job(job); return 0; }
void notify_background_jobs() { job* j, * next; int pid, status; do { pid = waitpid(-1, &status, WUNTRACED | WNOHANG); } while (jobs_update_status(pid, status)); /* Update all pending job signals */ for (j = jobs_head->next; j; j = next) { next = j->next; /* Notify user of job completed or stopped */ if (job_completed(j)) { printf("[%d] completed\n", j->pgid); remove_job(j); /* Completed jobs are removed from the list */ } else if (job_stopped(j) && !j->notified) { j->notified = true; printf("\n[%d] suspended\n", j->pgid); } } }
void children (int signum) { int status; pid_t pid = waitpid(-1,&status,WUNTRACED); int exited = WIFEXITED(status); int stopped = WIFSTOPPED(status); JobList *j = findJob(pid); if(!j) return; if(exited) { remove_job(pid); printf("Job [%d] %s terminated\n", j->id, j->comm); } else if(stopped) { printf("Job [%d] %s stopped\n", j->id, j->comm); } }
//******************************************** // function name: ExeCmd // Description: interperts and executes built-in commands // Parameters: pointer to jobs, command string // Returns: 0 - success,1 - failure //************************************************************************************** int ExeCmd(pJob* head, char* lineSize, char* cmdString) { char* cmd; char* args[MAX_ARG]; char pwd[MAX_LINE_SIZE]; static char last_dir[MAX_LINE_SIZE]; char* delimiters = " \t\n"; int i = 0; /*========used in kill command=======*/ int signal_number, Job_number, signal_sent; int found_job_pid; char found_job_name[MAX_LINE_SIZE]; /*===================================*/ /*========used in fg command=========*/ int child_done_id, fg_runner_pid, fg_req_JID; /*===================================*/ /*========used in bg command=========*/ int bg_runner_pid; /*===================================*/ bool illegal_cmd = FALSE; // illegal command cmd = strtok(lineSize, delimiters); if (cmd == NULL) return 0; args[0] = cmd; L_Fg_Cmd = cmd; for (i=1; i<MAX_ARG; i++) { args[i] = strtok(NULL, delimiters); } /*************************************************/ // Built in Commands /*************************************************/ if (!strcmp(cmd, "cd") ) { getcwd(pwd,sizeof(pwd)); if(!strcmp(args[1], "-")) { if(last_dir[0]!=0) { chdir(last_dir); } else { perror("smash error: > no previous path exists\n"); } } else { if(!chdir(args[1])) { strcpy(last_dir,pwd); } else { printf("smash error: > \"%s\" -path not found\n",args[1]); illegal_cmd = TRUE; } } } /*************************************************/ else if (!strcmp(cmd, "pwd")) { if(getcwd(pwd,sizeof(pwd))!= NULL) { fprintf(stdout,"%s\n",pwd); } else { perror("smash error: > pwd error\n"); } } /*************************************************/ else if (!strcmp(cmd, "mkdir")) { if(mkdir(args[1], 0755)) { if(EEXIST == errno) { printf("smash error: > \"%s\" -directory already exists\n",args[1]); } else { printf("smash error: > \"%s\" -cannot create directory\n",args[1]); } } } /*************************************************/ else if (!strcmp(cmd, "jobs")) { print_jobs(*head); } /*************************************************/ else if (!strcmp(cmd, "kill")) { if(args[1][0] != '-') { printf("smash error: > \"%s\"",cmdString); return -1; } signal_number=atoi(args[1]+1); Job_number=atoi(args[2]); //search requested job found_job_pid=find_job_PID(*head,Job_number); if(found_job_pid==-1) { printf("smash error: > kill %d - job does not exist\n",Job_number); return -1; } else { switch (signal_number) { case SIGTSTP: signal_sent=kill(found_job_pid,SIGTSTP); printf("signal SIGTSTP was sent to pid %d\n",found_job_pid); if(signal_sent!=0) { printf("smash error: > kill %d - cannot send signal\n",Job_number); } strcpy(found_job_name,find_job_name(*head,found_job_pid)); remove_job(head,found_job_pid); insert_job(head, found_job_pid, found_job_name, SUSPENDED); break; case SIGINT: signal_sent=kill(found_job_pid,SIGINT); printf("signal SIGINT was sent to pid %d\n",found_job_pid); if(signal_sent!=0) { printf("smash error: > kill %d - cannot send signal\n",Job_number); } remove_job(head,found_job_pid); break; case SIGTERM: signal_sent=kill(found_job_pid,SIGTERM); printf("signal SIGTERM was sent to pid %d\n",found_job_pid); if(signal_sent!=0) { printf("smash error: > kill %d - cannot send signal\n",Job_number); } remove_job(head,found_job_pid); break; default: signal_sent=kill(found_job_pid,signal_number); if(signal_sent!=0) { printf("smash error: > kill %d - cannot send signal\n",Job_number); } printf("signal %d was sent to pid %d\n",signal_number,found_job_pid); } } } /*************************************************/ else if (!strcmp(cmd, "showpid")) { printf("smash pid is %d\n",getpid()); } /*************************************************/ else if (!strcmp(cmd, "fg")) { if(args[1]==NULL) { Last_Bg_Pid=get_last_job_pid(*head); fg_runner_pid=Last_Bg_Pid; } else { fg_req_JID=atoi(args[1]); fg_runner_pid=find_job_PID(*head,fg_req_JID); } if (fg_runner_pid== -1)// No jobs in the Bg { perror("smash error: requested process not found\n"); } else if(is_suspended(*head,fg_runner_pid)== SUSPENDED) { kill(fg_runner_pid,SIGCONT); printf("signal SIGCONT was sent to pid %d\n",fg_runner_pid); unsuspend(*head,fg_runner_pid); Susp_Bg_Pid=get_last_suspended_job_pid(*head); } GPid=fg_runner_pid; L_Fg_Cmd = find_job_name(*head,fg_runner_pid); do { child_done_id = wait(NULL); if((child_done_id==-1)&&(errno==EINTR)) //child is gone due to inerrupt { break; } } while((child_done_id != fg_runner_pid) && (fg_runner_pid != Susp_Bg_Pid)); remove_job(head,fg_runner_pid); GPid= -1; } /*************************************************/ else if (!strcmp(cmd, "bg")) { if(args[1]==NULL) { bg_runner_pid=get_last_suspended_job_pid(*head); } else { fg_req_JID=atoi(args[1]); bg_runner_pid=find_job_PID(*head, fg_req_JID); if(is_suspended(*head,bg_runner_pid)==NOT_SUSPENDED) { perror("smash error: > bg called on un-suspended job\n"); return -1; } } strcpy(found_job_name,find_job_name(*head,bg_runner_pid)); printf("%s",found_job_name); kill(bg_runner_pid,SIGCONT); printf("signal SIGCONT was sent to pid %d\n",bg_runner_pid); unsuspend(*head,bg_runner_pid); Susp_Bg_Pid=get_last_suspended_job_pid(*head); } /*************************************************/ else if (!strcmp(cmd, "quit")) { if(args[1]==NULL) { destroy_list(head); exit(0); } else if (!strcmp(args[1], "kill")) { if (kill_jobs(*head) != -1) { destroy_list(head); exit(0); } else { exit (-1); } } else perror("smash error: > quit called with illegal argument\n"); return -1; } /*************************************************/ else // external command { ExeExternal(args, cmdString); return 0; } if (illegal_cmd == TRUE) { printf("smash error: > \"%s\"\n", cmdString); return 1; } return 0; }
//************************************************************************************** // function name: main // Description: main function of smash. get command from user and calls command functions //************************************************************************************** int main(int argc, char *argv[]) { char cmdString[MAX_LINE_SIZE]; pJob* job_list_head_ptr; struct sigaction ctrl_z_act; struct sigaction ctrl_c_act; //struct sigaction sigchld_act; fill_action(&ctrl_z_act, &ctrl_z_handler); fill_action(&ctrl_c_act, &ctrl_c_handler); //fill_action(&sigchld_act, &sigchld_handler); sigaction(SIGTSTP, &ctrl_z_act,NULL); sigaction(SIGINT, &ctrl_c_act,NULL); //sigaction(SIGCHLD,&sigchld_act,NULL); int dead_pid; //signal declaretions //NOTE: the signal handlers and the function/s that sets the handler should be found in siganls.c /* add your code here */ /************************************/ //NOTE: the signal handlers and the function/s that sets the handler should be found in siganls.c //set your signal handlers here /* add your code here */ /************************************/ /************************************/ // Init globals GPid = -1; Last_Bg_Pid = -1; Susp_Bg_Pid = -1; susp = 0; job_list_head = NULL; job_list_head_ptr = &job_list_head; #if 0 L_Fg_Cmd =(char*)malloc(sizeof(char)*(MAX_LINE_SIZE+1)); if (L_Fg_Cmd == NULL) exit (-1); L_Fg_Cmd[0] = '\0'; #endif while (1) { printf("smash > "); while((dead_pid=waitpid(-1,NULL,WNOHANG))>0)// This loop is in charge of handling zombies { remove_job(&job_list_head,dead_pid); } if((dead_pid==-1) && (errno=EINTR)) { //refresh_list(job_list_head_ptr); } fgets(lineSize, MAX_LINE_SIZE, stdin); strcpy(cmdString, lineSize); cmdString[strlen(lineSize)-1]='\0'; // perform a complicated Command if(!ExeComp(lineSize)) continue; // background command if(!BgCmd(lineSize, job_list_head_ptr)) continue; // built in commands ExeCmd(&job_list_head, lineSize, cmdString); /* initialize for next line read*/ lineSize[0]='\0'; cmdString[0]='\0'; fflush(stdout); fflush(stdin); } return 0; }
int /* O - Exit status */ main(int argc, /* I - Number of command-line arguments */ char *argv[]) /* I - Command-line arguments */ { int i; /* Looping var */ int status; /* Test status */ char *op, /* Operation to test */ **opargs, /* Remaining arguments */ *dest; /* Destination */ int cupslpd_argc; /* Argument count for cups-lpd */ char *cupslpd_argv[1000]; /* Arguments for cups-lpd */ int cupslpd_stdin[2], /* Standard input for cups-lpd */ cupslpd_stdout[2], /* Standard output for cups-lpd */ cupslpd_pid, /* Process ID for cups-lpd */ cupslpd_status; /* Status of cups-lpd process */ /* * Collect command-line arguments... */ op = NULL; opargs = argv + argc; dest = NULL; cupslpd_argc = 1; cupslpd_argv[0] = (char *)"cups-lpd"; for (i = 1; i < argc; i ++) if (!strncmp(argv[i], "-o", 2)) { cupslpd_argv[cupslpd_argc++] = argv[i]; if (!argv[i][2]) { i ++; if (i >= argc) usage(); cupslpd_argv[cupslpd_argc++] = argv[i]; } } else if (argv[i][0] == '-') usage(); else if (!op) op = argv[i]; else if (!dest) dest = argv[i]; else { opargs = argv + i; break; } if (!op || (!strcmp(op, "print-job") && (!dest || !opargs)) || (!strcmp(op, "remove-job") && (!dest || !opargs)) || (strcmp(op, "print-job") && strcmp(op, "print-waiting") && strcmp(op, "remove-job") && strcmp(op, "status-long") && strcmp(op, "status-short"))) { printf("op=\"%s\", dest=\"%s\", opargs=%p\n", op, dest, opargs); usage(); } /* * Run the cups-lpd program using pipes... */ cupslpd_argv[cupslpd_argc] = NULL; pipe(cupslpd_stdin); pipe(cupslpd_stdout); if ((cupslpd_pid = fork()) < 0) { /* * Error! */ perror("testlpd: Unable to fork"); return (1); } else if (cupslpd_pid == 0) { /* * Child goes here... */ dup2(cupslpd_stdin[0], 0); close(cupslpd_stdin[0]); close(cupslpd_stdin[1]); dup2(cupslpd_stdout[1], 1); close(cupslpd_stdout[0]); close(cupslpd_stdout[1]); execv("./cups-lpd", cupslpd_argv); perror("testlpd: Unable to exec ./cups-lpd"); exit(errno); } else { close(cupslpd_stdin[0]); close(cupslpd_stdout[1]); } /* * Do the operation test... */ if (!strcmp(op, "print-job")) status = print_job(cupslpd_stdin[1], cupslpd_stdout[0], dest, opargs); else if (!strcmp(op, "print-waiting")) status = print_waiting(cupslpd_stdin[1], cupslpd_stdout[0], dest); else if (!strcmp(op, "remove-job")) status = remove_job(cupslpd_stdin[1], cupslpd_stdout[0], dest, opargs); else if (!strcmp(op, "status-long")) status = status_long(cupslpd_stdin[1], cupslpd_stdout[0], dest, opargs); else if (!strcmp(op, "status-short")) status = status_short(cupslpd_stdin[1], cupslpd_stdout[0], dest, opargs); else { printf("Unknown operation \"%s\"!\n", op); status = 1; } /* * Kill the test program... */ close(cupslpd_stdin[1]); close(cupslpd_stdout[0]); while (wait(&cupslpd_status) != cupslpd_pid); printf("cups-lpd exit status was %d...\n", cupslpd_status); /* * Return the test status... */ return (status); }