/* Kill all inferiors. */ static int win32_kill (int pid) { struct process_info *process; if (current_process_handle == NULL) return -1; TerminateProcess (current_process_handle, 0); for (;;) { if (!child_continue (DBG_CONTINUE, -1)) break; if (!WaitForDebugEvent (¤t_event, INFINITE)) break; if (current_event.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT) break; else if (current_event.dwDebugEventCode == OUTPUT_DEBUG_STRING_EVENT) { struct target_waitstatus our_status = { 0 }; handle_output_debug_string (&our_status); } } win32_clear_inferiors (); process = find_process_pid (pid); remove_process (process); return 0; }
void do_job_notification(pid_t pid) { process *p, *q; /* Update status information for child processes. */ update_status(); for(p = first_process; p; p = q) { q = p->next; if(pid == 0 || pid == p->pid) { /* if all processes have completed, tell the user * the job has completed and delete it from the list of active jobs. */ if(p->completed) { format_job_info(p, "completed"); remove_process(p); free(p); } else if(p->stopped) { format_job_info(p, "stopped"); } /* Don't day anything about jobs that are still running. */ else { format_job_info(p, "running"); } } } }
static void handle_exit(Event *event) { debug(DEBUG_FUNCTION, "handle_exit(pid=%d, status=%d)", event->proc->pid, event->e_un.ret_val); if (event->proc->state != STATE_IGNORED) { output_line(event->proc, "+++ exited (status %d) +++", event->e_un.ret_val); } remove_process(event->proc); }
static void handle_exit_signal(Event *event) { debug(DEBUG_FUNCTION, "handle_exit_signal(pid=%d, signum=%d)", event->proc->pid, event->e_un.signum); if (event->proc->state != STATE_IGNORED) { output_line(event->proc, "+++ killed by %s +++", shortsignal(event->proc, event->e_un.signum)); } remove_process(event->proc); }
static void clean_up(int sig) { int status; int ret; /* Clean up any children that has started before */ do { ret = waitpid(0, &status, WNOHANG); if (ret > 0) remove_process(ret); } while (ret > 0); }
/* removes all processes from a job */ void remove_all_processes(job *j) { if (j->first_process == NULL) { //printf("no processes to remove\n"); return; } else { process *first_process = j->first_process; process *k = first_process; process *tmp = k; /* to save k once k is removed */ if (k->next == NULL) { /* this is the only process, so remove */ remove_process(j, k->pid); return; } while (k != NULL) { /* remove all the processes */ tmp = k; remove_process(j, k->pid); k = tmp->next; } //printf("all processes removed!"); } }
void process_bootstrap( pcb * control_block ){ proc_pointer = (control_block->process); (*proc_pointer)(); control_block->process_state = TERMINATED_STATE; remove_process(control_block); total_procs--; if(total_procs > 0){ release_processor(); } else { rtx_dbug_outs((CHAR *)"rtx: All running processes have terminated.\r\n"); asm("move.l #0,%d0"); asm("TRAP #15"); } return; }
/* See if any test processes have exceeded the timeout */ static int check_processes (time_t timeout) { struct process *current; time_t now = time (NULL); current = process_head; while (current != NULL) { if (now - current->time > timeout) { remove_process (current->pid); return (ETOOLONG); } current = current->next; } return (ENOERR); }
/*===========================================================================* * sem_process_vm_notify * *===========================================================================*/ PUBLIC void sem_process_vm_notify(void) { endpoint_t pt; int r; while ((r = vm_query_exit(&pt)) >= 0) { /* for each enpoint 'pt', check whether it's waiting... */ remove_process(pt); if (r == 0) break; } if (r < 0) printf("IPC: query exit error!\n"); }
void * request_memory_block() { int i; for( i = 0; i < 32; i++ ){ if( memoryBlocks[i].status != 1 ) { memoryBlocks[i].status = 1; return memoryBlocks[i].location; } } #ifdef _ERR_ exception(OUT_OF_MEM); #endif insert_blocked_process(remove_process(running), running->process_priority, BLOCKED_MEM_STATE); release_processor(); return request_memory_block(); }
void kill(int pid) { if (pid==0) return; int flag=0; process_slot * start = current; process_slot * this = current; do { if (this->process->pid==pid) { set_parents(pid,this->process->ppid); remove_process(this->process); flag=1; } this=this->next; }while (this != start && flag == 0); }
/* * Function: PRIPRE_scheduler * Description: Processes jobs based on Priority with Preemption algorithm. * Checks for preemption at given time quantum. */ void PRIPRE_scheduler() { float timer = 0, quantum_used = 0; Process *current = head_link, *running = NULL, *selected = NULL; while (1) { current = head_link, running = selected; if (current == NULL) { break; } while (1) { // Iteratively selects the job which has highest priority at given point of time // and incase of a tie, selects the one with lowest id for processing if (current != NULL && current->job->arrival_time <= timer) { if (selected == NULL || current->job->priority < selected->job->priority || (current->job->priority == selected->job->priority && current->job->id < selected->job->id)) { selected = current; } current = current->next; } else if (current != NULL && selected == NULL) { timer += time_quantum; } else { break; } } // running stores the prev. 'process/process state'. If it is different from selected, // then 'process/process state' has changed and details are logged if (running == NULL || running->job->id == selected->job->id) { timer += time_quantum, quantum_used += time_quantum; selected->job->run_time -= time_quantum; if (selected->job->run_time <= 0) { print_util(selected->job->id, timer - quantum_used, timer); remove_process(selected); selected = NULL, quantum_used = 0; } } else { print_util(running->job->id, timer - quantum_used, timer); quantum_used = 0; } } }
static int uwbrdev_release(struct inode *inode, struct file *file) { struct net_adapter *adapter; struct process_descriptor *procdsc; int current_tgid = 0; pr_debug("release: tgid=%d, pid=%d", current->tgid, current->pid); adapter = (struct net_adapter *)(file->private_data); if (adapter == NULL) { pr_debug("can't find adapter"); return -ENODEV; } current_tgid = current->tgid; procdsc = process_by_id(adapter, current_tgid); /* process is not exist. (open process != close process) */ if (procdsc == NULL) { current_tgid = adapter->pdata->g_cfg->temp_tgid; pr_debug("release: pid changed: %d", current_tgid); procdsc = process_by_id(adapter, current_tgid); } if (procdsc == NULL) { /*not found */ pr_debug("process %d not found", current_tgid); return -ESRCH; } /* RELEASE READ THREAD */ if (procdsc->irp) { procdsc->irp = false; wake_up_interruptible(&procdsc->read_wait); } spin_lock(&adapter->ctl.apps.lock); remove_process(adapter, current_tgid); spin_unlock(&adapter->ctl.apps.lock); return 0; }
/* * Function: FCFS_scheduler * Description: Process jobs as per First Come First Served algorithm. */ void FCFS_scheduler() { float timer = 0, quantum_used = 0; Process *current = head_link, *selected = NULL; while (1) { current = head_link; if (current == NULL) { break; } // If selected is not NULL, it means the prev. selected process hasn't finished its processing if (selected == NULL) { while (1) { // Iteratively selects the job which came first to the scheduler queue if (current != NULL && current->job->arrival_time <= timer) { if (selected == NULL || current->job->arrival_time < selected->job->arrival_time || (current->job->arrival_time == selected->job->arrival_time && current->job->id < selected->job->id)) { selected = current; } current = current->next; } else if (current != NULL && selected == NULL) { timer += time_quantum; } else { break; } } } timer += time_quantum, quantum_used += time_quantum; selected->job->run_time -= time_quantum; if (selected->job->run_time <= 0) { print_util(selected->job->id, timer - quantum_used, timer); remove_process(selected); selected = NULL, quantum_used = 0; } } }
/* * Function: PRI_scheduler * Description: Process jobs on the basis of priorities assigned to them. * Highest priority jobs get processed first. Higher priority jobs are the ones * having lesser priority values. */ void PRI_scheduler() { float timer = 0, quantum_used = 0; Process *current = head_link, *selected = NULL; while (1) { current = head_link; if (current == NULL) { break; } // If selected is not NULL, it means the prev. selected job hasn't finished with its processing if (selected == NULL) { while (1) { // Iteratively selects the job which has highest priority at given point of time // and incase of a tie, selects the one with lowest id for processing if (current != NULL && current->job->arrival_time <= timer) { if (selected == NULL || current->job->priority < selected->job->priority || (current->job->priority == selected->job->priority && current->job->id < selected->job->id)) { selected = current; } current = current->next; } else if (current != NULL && selected == NULL) { timer += time_quantum; } else { break; } } } timer += time_quantum, quantum_used += time_quantum; selected->job->run_time -= time_quantum; if (selected->job->run_time <= 0) { print_util(selected->job->id, timer - quantum_used, timer); remove_process(selected); selected = NULL, quantum_used = 0; } } }
/* Detach from inferior PID. */ static int win32_detach (int pid) { struct process_info *process; winapi_DebugActiveProcessStop DebugActiveProcessStop = NULL; winapi_DebugSetProcessKillOnExit DebugSetProcessKillOnExit = NULL; #ifdef _WIN32_WCE HMODULE dll = GetModuleHandle (_T("COREDLL.DLL")); #else HMODULE dll = GetModuleHandle (_T("KERNEL32.DLL")); #endif DebugActiveProcessStop = GETPROCADDRESS (dll, DebugActiveProcessStop); DebugSetProcessKillOnExit = GETPROCADDRESS (dll, DebugSetProcessKillOnExit); if (DebugSetProcessKillOnExit == NULL || DebugActiveProcessStop == NULL) return -1; { struct thread_resume resume; resume.thread = minus_one_ptid; resume.kind = resume_continue; resume.sig = 0; win32_resume (&resume, 1); } if (!DebugActiveProcessStop (current_process_id)) return -1; DebugSetProcessKillOnExit (FALSE); process = find_process_pid (pid); remove_process (process); win32_clear_inferiors (); return 0; }
static void handle_exec(Event * event) { Process * proc = event->proc; pid_t saved_pid; debug(DEBUG_FUNCTION, "handle_exec(pid=%d)", proc->pid); if (proc->state == STATE_IGNORED) { untrace_pid(proc->pid); remove_process(proc); return; } output_line(proc, "--- Called exec() ---"); proc->mask_32bit = 0; proc->personality = 0; proc->arch_ptr = NULL; free(proc->filename); proc->filename = pid2name(proc->pid); saved_pid = proc->pid; proc->pid = 0; breakpoints_init(proc, 0); proc->pid = saved_pid; proc->callstack_depth = 0; continue_process(proc->pid); }
static void win32_mourn (struct process_info *process) { remove_process (process); }
void limit_process(pid_t pid, double limit, int include_children) { //slice of the slot in which the process is allowed to run struct timespec twork; //slice of the slot in which the process is stopped struct timespec tsleep; //when the last twork has started struct timeval startwork; //when the last twork has finished struct timeval endwork; //initialization memset(&twork, 0, sizeof(struct timespec)); memset(&tsleep, 0, sizeof(struct timespec)); memset(&startwork, 0, sizeof(struct timeval)); memset(&endwork, 0, sizeof(struct timeval)); //last working time in microseconds unsigned long workingtime = 0; //generic list item struct list_node *node; //counter int c = 0; //get a better priority increase_priority(); //build the family init_process_group(&pgroup, pid, include_children); if (verbose) printf("Members in the process group owned by %d: %d\n", pgroup.target_pid, pgroup.proclist->count); //rate at which we are keeping active the processes (range 0-1) //1 means that the process are using all the twork slice double workingrate = -1; while(1) { update_process_group(&pgroup); if (pgroup.proclist->count==0) { if (verbose) printf("No more processes.\n"); break; } //total cpu actual usage (range 0-1) //1 means that the processes are using 100% cpu double pcpu = -1; //estimate how much the controlled processes are using the cpu in the working interval for (node = pgroup.proclist->first; node != NULL; node = node->next) { struct process *proc = (struct process*)(node->data); if (proc->cpu_usage < 0) { continue; } if (pcpu < 0) pcpu = 0; pcpu += proc->cpu_usage; } //adjust work and sleep time slices if (pcpu < 0) { //it's the 1st cycle, initialize workingrate pcpu = limit; workingrate = limit; twork.tv_nsec = TIME_SLOT * limit * 1000; } else { //adjust workingrate workingrate = MIN(workingrate / pcpu * limit, 1); twork.tv_nsec = TIME_SLOT * 1000 * workingrate; } tsleep.tv_nsec = TIME_SLOT * 1000 - twork.tv_nsec; if (verbose) { if (c%200==0) printf("\n%%CPU\twork quantum\tsleep quantum\tactive rate\n"); if (c%10==0 && c>0) printf("%0.2lf%%\t%6ld us\t%6ld us\t%0.2lf%%\n", pcpu*100, twork.tv_nsec/1000, tsleep.tv_nsec/1000, workingrate*100); } //resume processes node = pgroup.proclist->first; while (node != NULL) { struct list_node *next_node = node->next; struct process *proc = (struct process*)(node->data); if (kill(proc->pid,SIGCONT) != 0) { //process is dead, remove it from family if (verbose) fprintf(stderr, "SIGCONT failed. Process %d dead!\n", proc->pid); //remove process from group delete_node(pgroup.proclist, node); remove_process(&pgroup, proc->pid); } node = next_node; } //now processes are free to run (same working slice for all) gettimeofday(&startwork, NULL); nanosleep(&twork, NULL); gettimeofday(&endwork, NULL); workingtime = timediff(&endwork, &startwork); long delay = workingtime - twork.tv_nsec/1000; if (c>0 && delay>10000) { //delay is too much! signal to user? //fprintf(stderr, "%d %ld us\n", c, delay); } if (tsleep.tv_nsec>0) { //stop processes only if tsleep>0 node = pgroup.proclist->first; while (node != NULL) { struct list_node *next_node = node->next; struct process *proc = (struct process*)(node->data); if (kill(proc->pid,SIGSTOP)!=0) { //process is dead, remove it from family if (verbose) fprintf(stderr, "SIGSTOP failed. Process %d dead!\n", proc->pid); //remove process from group delete_node(pgroup.proclist, node); remove_process(&pgroup, proc->pid); } node = next_node; } //now the processes are sleeping nanosleep(&tsleep,NULL); } c++; } close_process_group(&pgroup); }
void RequestHandler::handling_thread(g_message* _request) { // wrap in local for auto-delete g_local < g_message > request(_request); // read parameters g_pid requester_pid = g_get_pid_for_tid(request()->sender); g_fd requesters_output = request()->parameterA; g_fd requesters_input = request()->parameterB; g_pid my_pid = g_get_pid(); // register a name std::stringstream namestr; namestr << "windowserver:handler@"; namestr << requester_pid; g_task_register_id(namestr.str().c_str()); // clone pipe ends g_fs_clonefd_status clone_input_status; g_fd requester_out = g_clone_fd_s(requesters_input, requester_pid, my_pid, &clone_input_status); if (clone_input_status != G_FS_CLONEFD_SUCCESSFUL) { g_logger::log("unable to clone input file descriptor (%i in process %i) on open request (status: %i)", requesters_input, requester_pid, clone_input_status); return; } g_fs_clonefd_status clone_output_status; g_fd requester_in = g_clone_fd_s(requesters_output, requester_pid, my_pid, &clone_output_status); if (clone_output_status != G_FS_CLONEFD_SUCCESSFUL) { g_logger::log("unable to clone output file descriptor (%i in process %i) on open request (status: %i)", requesters_input, requester_pid, clone_output_status); return; } // send response g_message_empty (response); response.type = G_UI_COMMAND_OPEN_RESPONSE; response.topic = request()->topic; g_send_msg(request()->sender, &response); // add process add_process(requester_pid, requester_out, requester_in); // start event dispatch thread g_create_thread((void*) &event_dispatch_thread); while (true) { // read transaction id uint32_t idlen = sizeof(g_ui_transaction_id); uint8_t id[idlen]; g_read(requester_in, id, idlen); g_ui_transaction_id transaction = *((g_ui_transaction_id*) id); // read length uint32_t lenlen = sizeof(uint32_t); uint8_t len[lenlen]; g_read(requester_in, len, lenlen); uint32_t length = *((uint32_t*) len); // read data // TODO limit data uint8_t* data = new uint8_t[length]; int32_t rd = 0; while (rd < length) { rd += g_read(requester_in, &data[rd], length - rd); } g_value_placer data_reader(data); // handle command g_ui_protocol_command_id command = data_reader.get<g_ui_protocol_command_id>(); if (command == G_UI_PROTOCOL_CREATE_WINDOW) { uint32_t window_id; g_ui_protocol_status status = createWindow(&window_id); // write response uint32_t response_len = G_UI_PROTOCOL_HEADER_LENGTH + G_UI_PROTOCOL_CREATE_WINDOW_RESPONSE_LENGTH; g_local < uint8_t > response(new uint8_t[response_len]); g_value_placer response_writer(response()); response_writer.put(G_UI_PROTOCOL_CREATE_WINDOW); response_writer.put(status); response_writer.put(window_id); send(requester_out, transaction, response(), response_len); } else if (command == G_UI_PROTOCOL_SET_VISIBLE) { uint32_t component_id = data_reader.get<uint32_t>(); bool visible = data_reader.get<uint8_t>(); // handle command g_ui_protocol_status status = setVisible(component_id, visible); // write response uint32_t response_len = G_UI_PROTOCOL_HEADER_LENGTH + G_UI_PROTOCOL_SET_VISIBLE_RESPONSE_LENGTH; g_local < uint8_t > response(new uint8_t[response_len]); g_value_placer response_writer(response()); response_writer.put(G_UI_PROTOCOL_SET_VISIBLE); response_writer.put(status); send(requester_out, transaction, response(), response_len); } else if (command == G_UI_PROTOCOL_CREATE_COMPONENT) { uint32_t component_type = data_reader.get<uint32_t>(); // handle command uint32_t component_id; g_ui_protocol_status status = createComponent(component_type, &component_id); // write response uint32_t response_length = G_UI_PROTOCOL_HEADER_LENGTH + G_UI_PROTOCOL_CREATE_COMPONENT_RESPONSE_LENGTH; g_local < uint8_t > response(new uint8_t[response_length]); g_value_placer response_writer(response()); response_writer.put(G_UI_PROTOCOL_CREATE_COMPONENT); response_writer.put(status); response_writer.put(component_id); send(requester_out, transaction, response(), response_length); } else if (command == G_UI_PROTOCOL_ADD_COMPONENT) { uint32_t parent_id = data_reader.get<uint32_t>(); uint32_t child_id = data_reader.get<uint32_t>(); // handle command g_ui_protocol_status status = addComponent(parent_id, child_id); // write response uint32_t response_length = G_UI_PROTOCOL_HEADER_LENGTH + G_UI_PROTOCOL_ADD_COMPONENT_RESPONSE_LENGTH; g_local < uint8_t > response(new uint8_t[response_length]); g_value_placer response_writer(response()); response_writer.put(G_UI_PROTOCOL_ADD_COMPONENT); response_writer.put(status); send(requester_out, transaction, response(), response_length); } else if (command == G_UI_PROTOCOL_SET_TITLE) { uint32_t component_id = data_reader.get<uint32_t>(); uint32_t title_length = data_reader.get<uint32_t>(); g_local<char> title(new char[title_length]); data_reader.get((uint8_t*) title(), title_length); // handle command g_ui_protocol_status status = setTitle(component_id, title()); // write response uint32_t response_length = G_UI_PROTOCOL_HEADER_LENGTH + G_UI_PROTOCOL_SET_TITLE_RESPONSE_LENGTH; g_local < uint8_t > response(new uint8_t[response_length]); g_value_placer response_writer(response()); response_writer.put(G_UI_PROTOCOL_SET_TITLE); response_writer.put(status); send(requester_out, transaction, response(), response_length); } else if (command == G_UI_PROTOCOL_GET_TITLE) { uint32_t component_id = data_reader.get<uint32_t>(); // handle command std::string title; g_ui_protocol_status status = getTitle(component_id, title); int title_length = title.length() + 1; // write response uint32_t response_length = G_UI_PROTOCOL_HEADER_LENGTH + G_UI_PROTOCOL_GET_TITLE_RESPONSE_LENGTH + title_length; g_local < uint8_t > response(new uint8_t[response_length]); g_value_placer response_writer(response()); response_writer.put(G_UI_PROTOCOL_GET_TITLE); response_writer.put(status); response_writer.put(title_length); response_writer.put((uint8_t*) title.c_str(), title_length); send(requester_out, transaction, response(), response_length); } else if (command == G_UI_PROTOCOL_SET_BOUNDS) { uint32_t component_id = data_reader.get<uint32_t>(); int32_t x = data_reader.get<int32_t>(); int32_t y = data_reader.get<int32_t>(); int32_t width = data_reader.get<int32_t>(); int32_t height = data_reader.get<int32_t>(); // handle command g_ui_protocol_status status = setBounds(component_id, x, y, width, height); // write response uint32_t response_length = G_UI_PROTOCOL_HEADER_LENGTH + G_UI_PROTOCOL_SET_BOUNDS_RESPONSE_LENGTH; g_local < uint8_t > response(new uint8_t[response_length]); g_value_placer response_writer(response()); response_writer.put(G_UI_PROTOCOL_SET_BOUNDS); response_writer.put(status); send(requester_out, transaction, response(), response_length); } else if (command == G_UI_PROTOCOL_SET_ACTION_LISTENER) { uint32_t component_id = data_reader.get<uint32_t>(); // handle command uint32_t listener_id; g_ui_protocol_status status = setActionListener(requester_pid, component_id, &listener_id); // write response uint32_t response_length = G_UI_PROTOCOL_HEADER_LENGTH + G_UI_PROTOCOL_SET_ACTION_LISTENER; g_local < uint8_t > response(new uint8_t[response_length]); g_value_placer response_writer(response()); response_writer.put<g_ui_protocol_command_id>(G_UI_PROTOCOL_SET_ACTION_LISTENER); response_writer.put<g_ui_protocol_status>(status); response_writer.put<uint32_t>(listener_id); send(requester_out, transaction, response(), response_length); } } // TODO close all windows // TODO remove listeners remove_process(requester_pid); }
/* execute test binary */ int check_bin(char *tbinary, time_t timeout) { pid_t child_pid; int result, res = 0; if (timeout > 0) res = check_processes(timeout); if (res == ETOOLONG) { #if USE_SYSLOG syslog(LOG_ERR, "test-binary %s exceeded time limit %ld", tbinary, timeout); #endif /* USE_SYSLOG */ return res; } child_pid = fork(); if (!child_pid) { /* child, exit immediately, if no test binary given */ if (tbinary == NULL) exit(0); /* Don't want the stdin and stdout of our test program * to cause trouble * So make stdout and stderr go to their respective files */ if (!freopen("/var/log/watchdog/test-bin.stdout", "a+", stdout)) exit (errno); if (!freopen("/var/log/watchdog/test-bin.stderr", "a+", stderr)) exit (errno); /* else start binary */ execl(tbinary, tbinary, NULL); /* execl should only return in case of an error */ /* so we return that error */ exit(errno); } else if (child_pid < 0) { /* fork failed */ int err = errno; if (errno == EAGAIN) { /* process table full */ #if USE_SYSLOG syslog(LOG_ERR, "process table is full!"); #endif /* USE_SYSLOG */ return (EREBOOT); } else if (softboot) return (err); else return (ENOERR); } else { int ret, err; /* fork was okay, add child to process list */ add_process(child_pid); /* wait for child(s) to stop */ /* but only after a short sleep */ sleep(tint >> 1); do { ret = waitpid(-1, &result, WNOHANG); err = errno; if (ret > 0) remove_process(ret); } while (ret > 0 && WIFEXITED(result) != 0 && WEXITSTATUS(result) == 0); /* check result: */ /* ret < 0 => error */ /* ret == 0 => no more child returned, however we may already have caught the actual child */ /* WIFEXITED(result) == 0 => child did not exit normally but was killed by signal which was not caught */ /* WEXITSTATUS(result) != 0 => child returned an error code */ if (ret > 0) { if (WIFEXITED(result) != 0) { /* if one of the scripts returns an error code just return that code */ #if USE_SYSLOG syslog(LOG_ERR, "test binary returned %d", WEXITSTATUS(result)); #endif /* USE_SYSLOG */ return (WEXITSTATUS(result)); } else if (WIFSIGNALED(result) != 0) { /* if one of the scripts was killed return ECHKILL */ #if USE_SYSLOG syslog(LOG_ERR, "test binary was killed by uncaught signal %d", WTERMSIG(result)); #endif /* USE_SYSLOG */ return (ECHKILL); } } else { /* in case there are still old childs running due to an error */ /* log that error */ if (err != 0 && err != ECHILD) { #if USE_SYSLOG errno = err; syslog(LOG_ERR, "child %d did not exit immediately (error = %d = '%m')", child_pid, err); #else /* USE_SYSLOG */ perror(progname); #endif /* USE_SYSLOG */ if (softboot) return (err); } } } return (ENOERR); }