// FILE *debugfp=NULL; int _evalpid(char *const argv[], char *path, int timeout, int *ppid) { pid_t pid; int status; int fd; int flags; int sig; // if (debugfp==NULL) // debugfp = fopen("/tmp/evallog.log","wb"); // char buf[254] = ""; #ifndef HAVE_X86 //we must disable this on x86 since nvram is not available at startup if (nvram_match("console_debug", "1")) { int i = 0; while (argv[i] != NULL) { fprintf(stderr, "%s ", argv[i++]); flog("%s ", argv[i - 1]); } fprintf(stderr, "\n"); flog("\n"); } #ifndef HAVE_SILENCE int i = 0; while (argv[i] != NULL) { fprintf(stderr, "%s ", argv[i++]); } fprintf(stderr, "\n"); #endif #endif switch (pid = fork()) { case -1: /* error */ perror("fork"); return errno; case 0: /* child */ /* * Reset signal handlers set for parent process */ for (sig = 0; sig < (_NSIG - 1); sig++) signal(sig, SIG_DFL); /* * Clean up */ ioctl(0, TIOCNOTTY, 0); close(STDIN_FILENO); close(STDOUT_FILENO); close(STDERR_FILENO); setsid(); /* * We want to check the board if exist UART? , add by honor * 2003-12-04 */ if ((fd = open("/dev/console", O_RDWR)) < 0) { (void)open("/dev/null", O_RDONLY); (void)open("/dev/null", O_WRONLY); (void)open("/dev/null", O_WRONLY); } else { close(fd); (void)open("/dev/console", O_RDONLY); (void)open("/dev/console", O_WRONLY); (void)open("/dev/console", O_WRONLY); } /* * Redirect stdout to <path> */ if (path) { flags = O_WRONLY | O_CREAT; if (!strncmp(path, ">>", 2)) { /* * append to <path> */ flags |= O_APPEND; path += 2; } else if (!strncmp(path, ">", 1)) { /* * overwrite <path> */ flags |= O_TRUNC; path += 1; } if ((fd = open(path, flags, 0644)) < 0) perror(path); else { dup2(fd, STDOUT_FILENO); close(fd); } } /* * execute command */ // for (i = 0; argv[i]; i++) // snprintf (buf + strlen (buf), sizeof (buf), "%s ", argv[i]); // cprintf("cmd=[%s]\n", buf); setenv("PATH", "/sbin:/bin:/usr/sbin:/usr/bin", 1); alarm(timeout); execvp(argv[0], argv); perror(argv[0]); exit(errno); default: /* parent */ if (ppid) { *ppid = pid; return 0; } else { waitpid(pid, &status, 0); if (WIFEXITED(status)) return WEXITSTATUS(status); else return status; } } }
int main(int argc, char **argv) { pid_t npid, cpid; int s, ns, cs, fc, cc, scn, scr, i; if(argc < 3){ return 1; } _max = atoi(argv[1]); if(_max < 0){ return 1; } setsid(); for(i = 0; i < sizeof(_sig) / sizeof(int); ++i){ signal(_sig[i], handler); } //limit(RLIMIT_NPROC, 64); if(_max == 0){ limit(RLIMIT_AS, 32 * 1024 * 1024); } limit(RLIMIT_CPU, 1); _pid = fork(); if(_pid < 0){ return 1; } if(_pid == 0){ if(_max <= 1){ ptrace(PTRACE_TRACEME, 0, NULL, NULL); } execv(argv[2], argv + 2); } cc = 1; fc = 0; while(cc > 0){ cpid = wait3(&cs, 0, NULL); if(WIFEXITED(cs)){ --cc; if(cpid == _pid){ s = cs; } continue; } if(WIFSIGNALED(cs)){ kill(0, WTERMSIG(cs)); } if(_max <= 1){ scn = ptrace(PTRACE_PEEKUSER, cpid, SCN, NULL); if(_bad[scn] == FORK){ scr = ptrace(PTRACE_PEEKUSER, cpid, SCR, NULL); if(scr > 0){ ++cc; if(!_max){ ptrace(PTRACE_ATTACH, scr, NULL, NULL); } ptrace(PTRACE_SYSCALL, cpid, NULL, NULL); }else if(fc < _max){ ++fc; ptrace(PTRACE_SYSCALL, cpid, NULL, NULL); }else{ kill(0, SIGKILL); } }else if(_bad[scn]){ kill(0, SIGKILL); }else{ ptrace(PTRACE_SYSCALL, cpid, NULL, NULL); } } } return WEXITSTATUS(s); }
/** * \param[in] rUser user name * \return true = success, false = failure * * \attention This function is very complex and may contain * various bugs including security ones. Please keep * it in mind.. */ bool edit_table(const std::string& rUser) { std::string tp(IncronTab::GetUserTablePath(rUser)); struct passwd* ppwd = getpwnam(rUser.c_str()); if (ppwd == NULL) { fprintf(stderr, "cannot find user '%s': %s\n", rUser.c_str(), strerror(errno)); return false; } uid_t uid = ppwd->pw_uid; uid_t gid = ppwd->pw_gid; char s[NAME_MAX]; strcpy(s, "/tmp/incron.table-XXXXXX"); uid_t iu = geteuid(); uid_t ig = getegid(); if (setegid(gid) != 0 || seteuid(uid) != 0) { fprintf(stderr, "cannot change effective UID/GID for user '%s': %s\n", rUser.c_str(), strerror(errno)); return false; } int fd = mkstemp(s); if (fd == -1) { fprintf(stderr, "cannot create temporary file: %s\n", strerror(errno)); return false; } bool ok = false; FILE* out = NULL; FILE* in = NULL; time_t mt = (time_t) 0; const char* e = NULL; std::string ed; if (setegid(ig) != 0 || seteuid(iu) != 0) { fprintf(stderr, "cannot change effective UID/GID: %s\n", strerror(errno)); close(fd); goto end; } out = fdopen(fd, "w"); if (out == NULL) { fprintf(stderr, "cannot write to temporary file: %s\n", strerror(errno)); close(fd); goto end; } in = fopen(tp.c_str(), "r"); if (in == NULL) { if (errno == ENOENT) { in = fopen("/dev/null", "r"); if (in == NULL) { fprintf(stderr, "cannot get empty table for '%s': %s\n", rUser.c_str(), strerror(errno)); fclose(out); goto end; } } else { fprintf(stderr, "cannot read old table for '%s': %s\n", rUser.c_str(), strerror(errno)); fclose(out); goto end; } } char buf[1024]; while (fgets(buf, 1024, in) != NULL) { fputs(buf, out); } fclose(in); fclose(out); struct stat st; if (stat(s, &st) != 0) { fprintf(stderr, "cannot stat temporary file: %s\n", strerror(errno)); goto end; } mt = st.st_mtime; // save modification time for detecting its change // Editor selecting algorithm: // 1. Check EDITOR environment variable // 2. Check VISUAL environment variable // 3. Try to get from configuration // 4. Check presence of /etc/alternatives/editor // 5. Use hard-wired editor e = getenv("EDITOR"); if (e == NULL) { e = getenv("VISUAL"); if (e == NULL) { if (!IncronCfg::GetValue("editor", ed)) throw InotifyException("configuration is corrupted", EINVAL); if (!ed.empty()) { e = ed.c_str(); } else { if (access(INCRON_ALT_EDITOR, X_OK) == 0) e = INCRON_ALT_EDITOR; else e = INCRON_DEFAULT_EDITOR; } } } // this block is explicite due to gotos' usage simplification { pid_t pid = fork(); if (pid == 0) { if (setgid(gid) != 0 || setuid(uid) != 0) { fprintf(stderr, "cannot set user '%s': %s\n", rUser.c_str(), strerror(errno)); goto end; } execlp(e, e, s, NULL); _exit(1); } else if (pid > 0) { int status; if (wait(&status) != pid) { perror("error while waiting for editor"); goto end; } if (!(WIFEXITED(status)) || WEXITSTATUS(status) != 0) { perror("editor finished with error"); goto end; } } else { perror("cannot start editor"); goto end; } } if (stat(s, &st) != 0) { fprintf(stderr, "cannot stat temporary file: %s\n", strerror(errno)); goto end; } if (st.st_mtime == mt) { fprintf(stderr, "table unchanged\n"); ok = true; goto end; } { IncronTab ict; if (ict.Load(s) && ict.Save(tp)) { if (chmod(tp.c_str(), S_IRUSR | S_IWUSR) != 0) { fprintf(stderr, "cannot change mode of temporary file: %s\n", strerror(errno)); } } else { fprintf(stderr, "cannot move temporary table: %s\n", strerror(errno)); goto end; } } ok = true; fprintf(stderr, "table updated\n"); end: unlink(s); return ok; }
static SolverImpl::SolverRunStatus runAndGetCexForked(::VC vc, STPBuilder *builder, ::VCExpr q, const std::vector<const Array *> &objects, std::vector<std::vector<unsigned char> > &values, bool &hasSolution, double timeout) { unsigned char *pos = shared_memory_ptr; unsigned sum = 0; for (std::vector<const Array *>::const_iterator it = objects.begin(), ie = objects.end(); it != ie; ++it) sum += (*it)->size; if (sum >= shared_memory_size) llvm::report_fatal_error("not enough shared memory for counterexample"); fflush(stdout); fflush(stderr); int pid = fork(); if (pid == -1) { klee_warning("fork failed (for STP)"); if (!IgnoreSolverFailures) exit(1); return SolverImpl::SOLVER_RUN_STATUS_FORK_FAILED; } if (pid == 0) { if (timeout) { ::alarm(0); /* Turn off alarm so we can safely set signal handler */ ::signal(SIGALRM, stpTimeoutHandler); ::alarm(std::max(1, (int)timeout)); } unsigned res = vc_query(vc, q); if (!res) { for (std::vector<const Array *>::const_iterator it = objects.begin(), ie = objects.end(); it != ie; ++it) { const Array *array = *it; for (unsigned offset = 0; offset < array->size; offset++) { ExprHandle counter = vc_getCounterExample(vc, builder->getInitialRead(array, offset)); *pos++ = getBVUnsigned(counter); } } } _exit(res); } else { int status; pid_t res; do { res = waitpid(pid, &status, 0); } while (res < 0 && errno == EINTR); if (res < 0) { klee_warning("waitpid() for STP failed"); if (!IgnoreSolverFailures) exit(1); return SolverImpl::SOLVER_RUN_STATUS_WAITPID_FAILED; } // From timed_run.py: It appears that linux at least will on // "occasion" return a status when the process was terminated by a // signal, so test signal first. if (WIFSIGNALED(status) || !WIFEXITED(status)) { klee_warning("STP did not return successfully. Most likely you forgot " "to run 'ulimit -s unlimited'"); if (!IgnoreSolverFailures) { exit(1); } return SolverImpl::SOLVER_RUN_STATUS_INTERRUPTED; } int exitcode = WEXITSTATUS(status); if (exitcode == 0) { hasSolution = true; } else if (exitcode == 1) { hasSolution = false; } else if (exitcode == 52) { klee_warning("STP timed out"); // mark that a timeout occurred return SolverImpl::SOLVER_RUN_STATUS_TIMEOUT; } else { klee_warning("STP did not return a recognized code"); if (!IgnoreSolverFailures) exit(1); return SolverImpl::SOLVER_RUN_STATUS_UNEXPECTED_EXIT_CODE; } if (hasSolution) { values = std::vector<std::vector<unsigned char> >(objects.size()); unsigned i = 0; for (std::vector<const Array *>::const_iterator it = objects.begin(), ie = objects.end(); it != ie; ++it) { const Array *array = *it; std::vector<unsigned char> &data = values[i++]; data.insert(data.begin(), pos, pos + array->size); pos += array->size; } } if (true == hasSolution) { return SolverImpl::SOLVER_RUN_STATUS_SUCCESS_SOLVABLE; } else { return SolverImpl::SOLVER_RUN_STATUS_SUCCESS_UNSOLVABLE; } } }
int main() { sigset_t sigset; sigemptyset(&sigset); sigaddset(&sigset, SIGCHLD); if (sigprocmask(SIG_BLOCK, &sigset, NULL) < 0) { fprintf(stderr, "Unable to mask SIGCHLD"); return 1; } signal(SIGCHLD, sig_hand); int fd[2]; if (pipe(fd) == -1){ fprintf(stderr, "Unable to open pipe "); return 1; } pid_t child = fork(); if (child) { // Parent proc close(fd[1]); // Close unused write end struct timespec timeout; timeout.tv_sec = 120; timeout.tv_nsec = 0; char buf[2]; read(fd[0], &buf, 1); // wait until child activate timer close(fd[0]); // This process waits enough for the child process to complete if (sigtimedwait(&sigset, NULL, &timeout) < 0) { if (errno == EAGAIN) { fprintf(stderr, "Timeout, killing child\n"); kill (child, SIGKILL); return 1; } else { fprintf(stderr, "Error in sigtimedwait"); return 1; } } int status; // In case child process is still running the test fails (assuming deadlock occurred) if (waitpid(child, &status, 0) < 0) { fprintf(stderr, "Error on waitpid"); return 1; } if(WIFEXITED(status) && WEXITSTATUS(status)==0) { fprintf(stderr, "Parent - terminate OK\n"); return 0; } return 1; } else { // inside child close(fd[0]); // Close unused read end struct sigaction sigact; struct itimerval itval; pthread_t tid; sigact.sa_handler = Handle; sigact.sa_flags = 0; sigemptyset(&sigact.sa_mask); if (sigaction(SIGVTALRM, &sigact, 0) == -1) { fprintf(stderr, "Child - Unable to set up handler\n"); return 1; } // Create a new thread that calls a system call in a loop if (pthread_create(&tid, 0, DoSysCallTillSignalsDone, 0) != 0) { fprintf(stderr, "Child - Unable to create thread\n"); return 1; } // Set timer to create an async signals itval.it_interval.tv_sec = 0; itval.it_interval.tv_usec = USLEEP_TIME; itval.it_value.tv_sec = 0; itval.it_value.tv_usec = USLEEP_TIME; if (setitimer(ITIMER_VIRTUAL, &itval, 0) == -1) { fprintf(stderr, "Child - Unable to set up timer\n"); return 1; } close(fd[1]); // send EOF to signal parent that timer is on /* * Call an analysis function in a loop . */ while (SigCount < COUNT) { volatile PF doToolAnalysis = DoToolAnalysis; doToolAnalysis(); } itval.it_value.tv_sec = 0; itval.it_value.tv_usec = 0; if (setitimer(ITIMER_VIRTUAL, &itval, 0) == -1) { fprintf(stderr, "Child - Unable to disable timer\n"); return 1; } pthread_join(tid, 0); fprintf(stderr, "Child - terminate OK\n"); return 0; } }
int jl_process_exited(int status) { return WIFEXITED(status); }
ErrorCode Process::wait() { int status, signal; ProcessInfo info; ThreadId tid; // We have at least one thread when we start waiting on a process. DS2ASSERT(!_threads.empty()); while (!_threads.empty()) { tid = blocking_waitpid(-1, &status, __WALL); DS2LOG(Debug, "wait tid=%d status=%#x", tid, status); if (tid <= 0) return kErrorProcessNotFound; auto threadIt = _threads.find(tid); if (threadIt == _threads.end()) { // If we don't know about this thread yet, but it has a WIFEXITED() or a // WIFSIGNALED() status (i.e.: it terminated), it means we already // cleaned up the thread object (e.g.: in Process::suspend), but we // hadn't waitpid()'d it yet. Avoid re-creating a Thread object here. if (WIFEXITED(status) || WIFSIGNALED(status)) { goto continue_waiting; } // A new thread has appeared that we didn't know about. Create the // Thread object and return. DS2LOG(Debug, "creating new thread tid=%d", tid); _currentThread = new Thread(this, tid); return kSuccess; } else { _currentThread = threadIt->second; } _currentThread->updateStopInfo(status); switch (_currentThread->_stopInfo.event) { case StopInfo::kEventNone: _currentThread->resume(); goto continue_waiting; case StopInfo::kEventExit: case StopInfo::kEventKill: DS2LOG(Debug, "thread %d is exiting", tid); // // Killing the main thread? // // Note(sas): This might be buggy; the main thread exiting // doesn't mean that the process is dying. // if (tid == _pid && _threads.size() == 1) { DS2LOG(Debug, "last thread is exiting"); break; } // // Remove and release the thread associated with this pid. // removeThread(tid); goto continue_waiting; case StopInfo::kEventStop: signal = _currentThread->_stopInfo.signal; DS2LOG(Debug, "stopped tid=%d status=%#x signal=%s", tid, status, Stringify::Signal(signal)); if (_passthruSignals.find(signal) != _passthruSignals.end()) { _currentThread->resume(signal); goto continue_waiting; } else { // // This is a signal that we want to transmit back to the // debugger. // break; } } break; continue_waiting: _currentThread = nullptr; continue; } if (!(WIFEXITED(status) || WIFSIGNALED(status)) || tid != _pid) { // // Suspend the process, this must be done after updating // the thread trap info. // suspend(); } if ((WIFEXITED(status) || WIFSIGNALED(status)) && tid == _pid) { _terminated = true; } return kSuccess; }
gboolean g_spawn_command_line_sync (const gchar *command_line, gchar **standard_output, gchar **standard_error, gint *exit_status, GError **error) { #ifdef G_OS_WIN32 #else pid_t pid; gchar **argv; gint argc; int stdout_pipe [2] = { -1, -1 }; int stderr_pipe [2] = { -1, -1 }; int status; int res; if (!g_shell_parse_argv (command_line, &argc, &argv, error)) return FALSE; if (standard_output && !create_pipe (stdout_pipe, error)) return FALSE; if (standard_error && !create_pipe (stderr_pipe, error)) { if (standard_output) { CLOSE_PIPE (stdout_pipe); } return FALSE; } pid = fork (); if (pid == 0) { gint i; if (standard_output) { close (stdout_pipe [0]); dup2 (stdout_pipe [1], STDOUT_FILENO); } if (standard_error) { close (stderr_pipe [0]); dup2 (stderr_pipe [1], STDERR_FILENO); } for (i = g_getdtablesize () - 1; i >= 3; i--) close (i); /* G_SPAWN_SEARCH_PATH is always enabled for g_spawn_command_line_sync */ if (!g_path_is_absolute (argv [0])) { gchar *arg0; arg0 = g_find_program_in_path (argv [0]); if (arg0 == NULL) { exit (1); } //g_free (argv [0]); argv [0] = arg0; } execv (argv [0], argv); exit (1); /* TODO: What now? */ } g_strfreev (argv); if (standard_output) close (stdout_pipe [1]); if (standard_error) close (stderr_pipe [1]); if (standard_output || standard_error) { res = read_pipes (stdout_pipe [0], standard_output, stderr_pipe [0], standard_error, error); if (res) { waitpid (pid, &status, WNOHANG); /* avoid zombie */ return FALSE; } } NO_INTR (res, waitpid (pid, &status, 0)); /* TODO: What if error? */ if (WIFEXITED (status) && exit_status) { *exit_status = WEXITSTATUS (status); } #endif return TRUE; }
static void do_master_child(void) { int lc; int pid; int status; if (SETUID(NULL, ltpuser->pw_uid) == -1) { tst_brkm(TBROK, NULL, "setuid failed to set the effective uid to %d", ltpuser->pw_uid); } for (lc = 0; TEST_LOOPING(lc); lc++) { int tst_fd; tst_count = 0; TEST(tst_fd = open(testfile, O_RDWR)); if (TEST_RETURN != -1) { tst_resm(TFAIL, "call succeeded unexpectedly"); close(tst_fd); } if (TEST_ERRNO == EACCES) { tst_resm(TPASS, "open returned errno EACCES"); } else { tst_resm(TFAIL, "open returned unexpected errno - %d", TEST_ERRNO); continue; } pid = FORK_OR_VFORK(); if (pid < 0) tst_brkm(TBROK, NULL, "Fork failed"); if (pid == 0) { int tst_fd2; /* Test to open the file in son process */ TEST(tst_fd2 = open(testfile, O_RDWR)); if (TEST_RETURN != -1) { tst_resm(TFAIL, "call succeeded unexpectedly"); close(tst_fd2); } TEST_ERROR_LOG(TEST_ERRNO); if (TEST_ERRNO == EACCES) { tst_resm(TPASS, "open returned errno EACCES"); } else { tst_resm(TFAIL, "open returned unexpected errno - %d", TEST_ERRNO); } tst_exit(); } else { /* Wait for son completion */ waitpid(pid, &status, 0); if (!WIFEXITED(status) || (WEXITSTATUS(status) != 0)) exit(WEXITSTATUS(status)); } } tst_exit(); }
static void mgt_reap_child(void) { int i; int status = 0xffff; struct vsb *vsb; pid_t r = 0; assert(child_pid != -1); /* * Close the CLI connections * This signals orderly shut down to child */ mgt_cli_stop_child(); if (child_cli_out >= 0) closex(&child_cli_out); if (child_cli_in >= 0) closex(&child_cli_in); /* Stop the poker */ if (ev_poker != NULL) { vev_del(mgt_evb, ev_poker); free(ev_poker); } ev_poker = NULL; /* Stop the listener */ if (ev_listen != NULL) { vev_del(mgt_evb, ev_listen); free(ev_listen); ev_listen = NULL; } /* Compose obituary */ vsb = VSB_new_auto(); XXXAN(vsb); /* Wait for child to die */ for (i = 0; i < mgt_param.cli_timeout; i++) { r = waitpid(child_pid, &status, WNOHANG); if (r == child_pid) break; (void)sleep(1); } if (r == 0) { VSB_printf(vsb, "Child (%jd) not dying, killing", (intmax_t)r); /* Kick it Jim... */ if (MGT_FEATURE(FEATURE_NO_COREDUMP)) (void)kill(child_pid, SIGKILL); else (void)kill(child_pid, SIGQUIT); r = waitpid(child_pid, &status, 0); } if (r != child_pid) fprintf(stderr, "WAIT 0x%jx\n", (uintmax_t)r); assert(r == child_pid); MAC_reopen_sockets(NULL); VSB_printf(vsb, "Child (%jd) %s", (intmax_t)r, status ? "died" : "ended"); if (WIFEXITED(status) && WEXITSTATUS(status)) { VSB_printf(vsb, " status=%d", WEXITSTATUS(status)); exit_status |= 0x20; if (WEXITSTATUS(status) == 1) VSC_C_mgt->child_exit = ++static_VSC_C_mgt.child_exit; else VSC_C_mgt->child_stop = ++static_VSC_C_mgt.child_stop; } if (WIFSIGNALED(status)) { VSB_printf(vsb, " signal=%d", WTERMSIG(status)); exit_status |= 0x40; VSC_C_mgt->child_died = ++static_VSC_C_mgt.child_died; } #ifdef WCOREDUMP if (WCOREDUMP(status)) { VSB_printf(vsb, " (core dumped)"); exit_status |= 0x80; VSC_C_mgt->child_dump = ++static_VSC_C_mgt.child_dump; } #endif AZ(VSB_finish(vsb)); MGT_complain(status ? C_ERR : C_INFO, "%s", VSB_data(vsb)); VSB_delete(vsb); /* Dispose of shared memory but evacuate panic messages first */ if (heritage.panic_str[0] != '\0') { mgt_panic_record(r); mgt_SHM_Destroy(1); VSC_C_mgt->child_panic = ++static_VSC_C_mgt.child_panic; } else { mgt_SHM_Destroy(MGT_DO_DEBUG(DBG_VSM_KEEP)); } mgt_SHM_Create(); mgt_SHM_Commit(); if (child_state == CH_RUNNING) child_state = CH_DIED; /* Pick up any stuff lingering on stdout/stderr */ (void)child_listener(NULL, EV_RD); closex(&child_output); VLU_Destroy(child_std_vlu); child_pid = -1; MGT_complain(C_DEBUG, "Child cleanup complete"); if (child_state == CH_DIED && mgt_param.auto_restart) mgt_launch_child(NULL); else if (child_state == CH_DIED) child_state = CH_STOPPED; else if (child_state == CH_STOPPING) child_state = CH_STOPPED; }
/* Handle breakpoints - we expect to see breakpoints in the dynamic linker * (which we set ourselves) as well as profiler marks (embedded in the * profiled application's code). */ static int ProcessBreakpoint( pid_t pid, u_long ip ) { static int ld_state = RT_CONSISTENT; // This ought to be per-pid int ptrace_sig = 0; #if defined( MD_x86 ) user_regs_struct regs; // on x86, when breakpoint was hit the EIP points to the next // instruction, so we must be careful ptrace( PTRACE_GETREGS, pid, NULL, ®s ); if( ip == Rdebug.r_brk + sizeof( opcode_type ) ) { #elif defined( MD_ppc ) if( ip == Rdebug.r_brk ) { #endif opcode_type brk_opcode = BRKPOINT; int status; int ret; /* The dynamic linker breakpoint was hit, meaning that * libraries are being loaded or unloaded. This gets a bit * tricky because we must restore the original code that was * at the breakpoint and execute it, but we still want to * keep the breakpoint. */ if( WriteMem( pid, &saved_opcode, Rdebug.r_brk, sizeof( saved_opcode ) ) != sizeof( saved_opcode ) ) printf( "WriteMem() #1 failed\n" ); ReadMem( pid, &Rdebug, (addr_off)DbgRdebug, sizeof( Rdebug ) ); dbg_printf( "ld breakpoint hit, state is " ); switch( Rdebug.r_state ) { case RT_ADD: dbg_printf( "RT_ADD\n" ); AddLibrary( pid, Rdebug.r_map ); ld_state = RT_ADD; break; case RT_DELETE: dbg_printf( "RT_DELETE\n" ); ld_state = RT_DELETE; break; case RT_CONSISTENT: dbg_printf( "RT_CONSISTENT\n" ); if( ld_state == RT_DELETE ) RemoveLibrary( pid, Rdebug.r_map ); ld_state = RT_CONSISTENT; break; default: dbg_printf( "error!\n" ); break; } #if defined( MD_x86 ) regs.eip--; ptrace( PTRACE_SETREGS, pid, NULL, ®s ); #endif // unset breakpoint, single step, re-set breakpoint if( ptrace( PTRACE_SINGLESTEP, pid, NULL, (void *)ptrace_sig ) < 0 ) perror( "ptrace()" ); do { // have to loop since SIGALRM can interrupt us here ret = waitpid( pid, &status, 0 ); } while( (ret < 0) && (errno == EINTR) ); if( ret == -1) perror( "waitpid()" ); if( WriteMem( pid, &brk_opcode, Rdebug.r_brk, sizeof( brk_opcode ) ) != sizeof( brk_opcode ) ) dbg_printf( "WriteMem() #2 failed with errno %d for pid %d, %d bytes (at %p)!\n", errno, pid, sizeof( brk_opcode ), Rdebug.r_brk ); return( TRUE ); // indicate this was our breakpoint } else { dbg_printf( "Not an ld breakpoint, assuming mark\n" ); #if defined( MD_x86 ) if( ProcessMark( pid, ®s ) ) return( TRUE ); #endif } return( FALSE ); } /* * Real time signal (SIGALRM) handler. All we really need to do is wake up * periodically to interrupt waitpid(), the signal handler need not do much * at all. */ static void alarm_handler( int signo ) { TimerTicked = TRUE; } /* Install periodic real time alarm signal */ static void InstSigHandler( int msec_period ) { struct sigaction sigalrm; struct itimerval timer; sigalrm.sa_handler = (void *)alarm_handler; sigemptyset( &sigalrm.sa_mask ); sigalrm.sa_flags = 0; sigaction( SIGALRM, &sigalrm, NULL ); timer.it_interval.tv_sec = 0; timer.it_interval.tv_usec = msec_period * 1000; timer.it_value.tv_sec = 0; timer.it_value.tv_usec = msec_period * 1000; if( setitimer( ITIMER_REAL, &timer, NULL ) ) { InternalError( MsgArray[MSG_SAMPLE_6 - ERR_FIRST_MESSAGE] ); } } /* * Main sampler loop. We run the profiled application under the control of * ptrace(). The sampler installs a SIGALRM handler which ticks at the desired * rate. Whenever the SIGALRM interrupts our own waitpid(), we send a SIGSTOP * to the profiled app and when the child app notifies us of the SIGSTOP, we * remember the current execution point and continue the profiled app. Note * that we may miss some ticks but this is not a problem - the ticks don't * even need to be regular to provide usable results. */ static void SampleLoop( pid_t pid ) { static int ptrace_sig = 0; static int do_cont = TRUE; int status; user_regs_struct regs; bool sample_continue = TRUE; int ret; opcode_type brk_opcode = BRKPOINT; TimerTicked = FALSE; InstSigHandler( SleepTime ); do { if( do_cont && ptrace( PTRACE_CONT, pid, NULL, (void *)ptrace_sig ) == -1) perror( "ptrace()" ); ret = waitpid( pid, &status, 0 ); if( (ret < 0) && (errno == EINTR) ) { /* did we get woken up by SIGALRM? */ if( TimerTicked ) { TimerTicked = FALSE; /* interrupt child process - next waitpid() will see this */ kill( pid, SIGSTOP ); } else { dbg_printf( "who the hell interrupted waitpid()?\n" ); } do_cont = FALSE; continue; } if( ret < 0 ) perror( "waitpid()" ); do_cont = TRUE; /* record current execution point */ #if defined( MD_x86 ) ptrace( PTRACE_GETREGS, pid, NULL, ®s ); #elif defined( MD_ppc ) regs.eip = ptrace( PTRACE_PEEKUSER, pid, REGSIZE * PT_NIP, NULL ); #endif if( WIFSTOPPED( status ) ) { /* If debuggee has dynamic section, try getting the r_debug struct * every time the child process stops. The r_debug data may not be * available immediately after the child process first loads. */ if( !HaveRdebug && (DbgDyn != NULL) ) { if( Get_ld_info( pid, DbgDyn, &Rdebug, &DbgRdebug ) ) { AddLibrary( pid, Rdebug.r_map ); HaveRdebug = TRUE; /* Set a breakpoint in dynamic linker. That way we can be * informed on dynamic library load/unload events. */ ReadMem( pid, &saved_opcode, Rdebug.r_brk, sizeof( saved_opcode ) ); dbg_printf( "setting ld breakpoint at %p, old opcode was %X\n", Rdebug.r_brk, saved_opcode ); WriteMem( pid, &brk_opcode, Rdebug.r_brk, sizeof( brk_opcode ) ); } } sample_continue = FALSE; switch( (ptrace_sig = WSTOPSIG( status )) ) { case SIGSEGV: dbg_printf( "SIGSEGV at %p\n", regs.eip ); sample_continue = TRUE; break; case SIGILL: dbg_printf( "SIGILL at %p\n", regs.eip ); sample_continue = TRUE; break; case SIGABRT: dbg_printf( "SIGABRT at %p\n", regs.eip ); sample_continue = TRUE; break; case SIGINT: dbg_printf( "SIGINT at %p\n", regs.eip ); sample_continue = TRUE; break; case SIGTRAP: dbg_printf( "SIGTRAP at %p\n", regs.eip ); if( ProcessBreakpoint( pid, regs.eip ) ) { // don't pass on SIGTRAP if we expected this breakpoint ptrace_sig = 0; } sample_continue = TRUE; break; case SIGSTOP: /* presumably we were behind this SIGSTOP */ RecordSample( regs.eip, 1 ); ptrace_sig = 0; sample_continue = TRUE; break; default: /* all other signals get passed down to the child and we let * the child handle them (or not handle and die) */ sample_continue = TRUE; break; } } else if( WIFEXITED( status ) ) { dbg_printf( "WIFEXITED pid %d\n", pid ); report(); sample_continue = FALSE; } else if( WIFSIGNALED( status ) ) { dbg_printf( "WIFSIGNALED pid %d\n", pid ); report(); sample_continue = FALSE; } } while( sample_continue ); } static int GetExeNameFromPid( pid_t pid, char *buffer, int max_len ) { char procfile[24]; int len; sprintf( procfile, "/proc/%d/exe", pid ); len = readlink( procfile, buffer, max_len ); if( len < 0 ) len = 0; buffer[len] = '\0'; return( len ); }
void seed_rng(void) { #ifndef OPENSSL_PRNG_ONLY int devnull; int p[2]; pid_t pid; int ret; unsigned char buf[RANDOM_SEED_SIZE]; mysig_t old_sigchld; if (RAND_status() == 1) { debug3("RNG is ready, skipping seeding"); return; } debug3("Seeding PRNG from %s", SSH_RAND_HELPER); if ((devnull = open("/dev/null", O_RDWR)) == -1) fatal("Couldn't open /dev/null: %s", strerror(errno)); if (pipe(p) == -1) fatal("pipe: %s", strerror(errno)); old_sigchld = signal(SIGCHLD, SIG_DFL); if ((pid = fork()) == -1) fatal("Couldn't fork: %s", strerror(errno)); if (pid == 0) { dup2(devnull, STDIN_FILENO); dup2(p[1], STDOUT_FILENO); /* Keep stderr open for errors */ close(p[0]); close(p[1]); close(devnull); if (original_uid != original_euid && ( seteuid(getuid()) == -1 || setuid(original_uid) == -1) ) { fprintf(stderr, "(rand child) setuid(%li): %s\n", (long int)original_uid, strerror(errno)); _exit(1); } execl(SSH_RAND_HELPER, "ssh-rand-helper", NULL); fprintf(stderr, "(rand child) Couldn't exec '%s': %s\n", SSH_RAND_HELPER, strerror(errno)); _exit(1); } close(devnull); close(p[1]); memset(buf, '\0', sizeof(buf)); ret = atomicio(read, p[0], buf, sizeof(buf)); if (ret == -1) fatal("Couldn't read from ssh-rand-helper: %s", strerror(errno)); if (ret != sizeof(buf)) fatal("ssh-rand-helper child produced insufficient data"); close(p[0]); if (waitpid(pid, &ret, 0) == -1) fatal("Couldn't wait for ssh-rand-helper completion: %s", strerror(errno)); signal(SIGCHLD, old_sigchld); /* We don't mind if the child exits upon a SIGPIPE */ if (!WIFEXITED(ret) && (!WIFSIGNALED(ret) || WTERMSIG(ret) != SIGPIPE)) fatal("ssh-rand-helper terminated abnormally"); if (WEXITSTATUS(ret) != 0) fatal("ssh-rand-helper exit with exit status %d", ret); RAND_add(buf, sizeof(buf), sizeof(buf)); memset(buf, '\0', sizeof(buf)); #endif /* OPENSSL_PRNG_ONLY */ if (RAND_status() != 1) fatal("PRNG is not seeded"); }
int main(int argc, char* argv[]){ long i; long iterations = DEFAULT_ITERATIONS; struct sched_param param; int policy, num_processes, status; double x, y; double inCircle = 0.0; double inSquare = 0.0; double pCircle = 0.0; double piCalc = 0.0; pid_t pid, wpid; int j = 0; /* Set default policy if not supplied */ if(argc < 2){ policy = SCHED_OTHER; } /* Set default number of processes */ if(argc < 3){ num_processes = LOW; } /* Set policy if supplied */ if(argc > 1){ if(!strcmp(argv[1], "SCHED_OTHER")){ policy = SCHED_OTHER; } else if(!strcmp(argv[1], "SCHED_FIFO")){ policy = SCHED_FIFO; } else if(!strcmp(argv[1], "SCHED_RR")){ policy = SCHED_RR; } else { fprintf(stderr, "Unhandeled scheduling policy\n"); exit(EXIT_FAILURE); } } /* Set # Of Processes */ if(argc > 2){ if(!strcmp(argv[2], "LOW")){ num_processes = LOW; } else if(!strcmp(argv[2], "MEDIUM")){ num_processes = MEDIUM; } else if(!strcmp(argv[2], "HIGH")){ num_processes = HIGH; } else{ fprintf(stderr, "Unhandeled number of processes\n"); exit(EXIT_FAILURE); } } /* Set process to max prioty for given scheduler */ param.sched_priority = sched_get_priority_max(policy); /* Set new scheduler policy */ fprintf(stdout, "Current Scheduling Policy: %d\n", sched_getscheduler(0)); fprintf(stdout, "Setting Scheduling Policy to: %d\n", policy); if(sched_setscheduler(0, policy, ¶m)){ perror("Error setting scheduler policy"); exit(EXIT_FAILURE); } fprintf(stdout, "New Scheduling Policy: %d\n", sched_getscheduler(0)); /* Fork number of processes specified */ printf("Number of processes to be forked %d \n", num_processes); for(i = 0; i < num_processes; i++){ if((pid = fork()) == -1){ fprintf(stderr, "Error Forking Child Process"); exit(EXIT_FAILURE); } // only if pid is 0, we are in child if(pid == 0){ for(i=0; i<iterations; i++){ x = (random() % (RADIUS * 2)) - RADIUS; y = (random() % (RADIUS * 2)) - RADIUS; if(zeroDist(x,y) < RADIUS){ inCircle++; } inSquare++; } /* Finish calculation */ pCircle = inCircle/inSquare; piCalc = pCircle * 4.0; /* Print result */ fprintf(stdout, "pi = %f\n", piCalc); exit(0); } } // terminate all children until wpid is 0 while((wpid = wait(&status)) > 0){ if(WIFEXITED(status)){ printf("Exit status of child process %d was normal \n", wpid); j++; } } printf("Total # of Processes terminated was %d\n", j); return EXIT_SUCCESS; }
static bool client_exec_script(struct master_service_connection *conn) { const char *const *args; string_t *input; void *buf; size_t prev_size, scanpos; bool header_complete = FALSE; ssize_t ret; int status; pid_t pid; net_set_nonblock(conn->fd, FALSE); input = buffer_create_dynamic(pool_datastack_create(), IO_BLOCK_SIZE); /* Input contains: VERSION .. <lf> [alarm=<secs> <lf>] "noreply" | "-" (or anything really) <lf> arg 1 <lf> arg 2 <lf> ... <lf> DATA This is quite a horrible protocol. If alarm is specified, it MUST be before "noreply". If "noreply" isn't given, something other string (typically "-") must be given which is eaten away. */ alarm(SCRIPT_READ_TIMEOUT_SECS); scanpos = 1; while (!header_complete) { const unsigned char *pos, *end; prev_size = input->used; buf = buffer_append_space_unsafe(input, IO_BLOCK_SIZE); /* peek in socket input buffer */ ret = recv(conn->fd, buf, IO_BLOCK_SIZE, MSG_PEEK); if (ret <= 0) { buffer_set_used_size(input, prev_size); if (strchr(str_c(input), '\n') != NULL) script_verify_version(t_strcut(str_c(input), '\n')); if (ret < 0) i_fatal("recv(MSG_PEEK) failed: %m"); i_fatal("recv(MSG_PEEK) failed: disconnected"); } /* scan for final \n\n */ pos = CONST_PTR_OFFSET(input->data, scanpos); end = CONST_PTR_OFFSET(input->data, prev_size + ret); for (; pos < end; pos++) { if (pos[-1] == '\n' && pos[0] == '\n') { header_complete = TRUE; pos++; break; } } scanpos = pos - (const unsigned char *)input->data; /* read data for real (up to and including \n\n) */ ret = recv(conn->fd, buf, scanpos-prev_size, 0); if (prev_size+ret != scanpos) { if (ret < 0) i_fatal("recv() failed: %m"); if (ret == 0) i_fatal("recv() failed: disconnected"); i_fatal("recv() failed: size of definitive recv() differs from peek"); } buffer_set_used_size(input, scanpos); } alarm(0); /* drop the last two LFs */ buffer_set_used_size(input, scanpos-2); args = t_strsplit(str_c(input), "\n"); script_verify_version(*args); args++; if (*args != NULL) { if (strncmp(*args, "alarm=", 6) == 0) { unsigned int seconds; if (str_to_uint(*args + 6, &seconds) < 0) i_fatal("invalid alarm option"); alarm(seconds); args++; } if (strcmp(*args, "noreply") == 0) { /* no need to fork and check exit status */ exec_child(conn, args + 1); i_unreached(); } if (**args == '\0') i_fatal("empty options"); args++; } if ((pid = fork()) == (pid_t)-1) { i_error("fork() failed: %m"); return FALSE; } if (pid == 0) { /* child */ exec_child(conn, args); i_unreached(); } /* parent */ /* check script exit status */ if (waitpid(pid, &status, 0) < 0) { i_error("waitpid() failed: %m"); return FALSE; } else if (WIFEXITED(status)) { ret = WEXITSTATUS(status); if (ret != 0) { i_error("Script terminated abnormally, exit status %d", (int)ret); return FALSE; } } else if (WIFSIGNALED(status)) { i_error("Script terminated abnormally, signal %d", WTERMSIG(status)); return FALSE; } else if (WIFSTOPPED(status)) { i_fatal("Script stopped, signal %d", WSTOPSIG(status)); return FALSE; } else { i_fatal("Script terminated abnormally, return status %d", status); return FALSE; } return TRUE; }
bool f_pcntl_wifexited(int status) { return WIFEXITED(status);}
/* * Scan the specified file system to check quota(s) present on it. */ int chkquota(const char *vfstype, const char *fsname, const char *mntpt, void *auxarg, pid_t *pidp) { struct quotaname *qnp = auxarg; struct fileusage *fup; union dinode *dp; int cg, i, mode, errs = 0, status; ino_t ino, inosused; pid_t pid; char *cp; switch (pid = fork()) { case -1: /* error */ warn("fork"); return 1; case 0: /* child */ if ((fi = open(fsname, O_RDONLY, 0)) < 0) err(1, "%s", fsname); sync(); dev_bsize = 1; for (i = 0; sblock_try[i] != -1; i++) { bread(sblock_try[i], (char *)&sblock, (long)SBLOCKSIZE); if ((sblock.fs_magic == FS_UFS1_MAGIC || (sblock.fs_magic == FS_UFS2_MAGIC && sblock.fs_sblockloc == sblock_try[i])) && sblock.fs_bsize <= MAXBSIZE && sblock.fs_bsize >= sizeof(struct fs)) break; } if (sblock_try[i] == -1) { warn("Cannot find file system superblock"); return (1); } dev_bsize = sblock.fs_fsize / fsbtodb(&sblock, 1); maxino = sblock.fs_ncg * sblock.fs_ipg; for (cg = 0; cg < sblock.fs_ncg; cg++) { ino = cg * sblock.fs_ipg; setinodebuf(ino); bread(fsbtodb(&sblock, cgtod(&sblock, cg)), (char *)(&cgblk), sblock.fs_cgsize); if (sblock.fs_magic == FS_UFS2_MAGIC) inosused = cgblk.cg_initediblk; else inosused = sblock.fs_ipg; /* * If we are using soft updates, then we can trust the * cylinder group inode allocation maps to tell us which * inodes are allocated. We will scan the used inode map * to find the inodes that are really in use, and then * read only those inodes in from disk. */ if (sblock.fs_flags & FS_DOSOFTDEP) { if (!cg_chkmagic(&cgblk)) errx(1, "CG %d: BAD MAGIC NUMBER\n", cg); cp = &cg_inosused(&cgblk)[(inosused - 1) / CHAR_BIT]; for ( ; inosused > 0; inosused -= CHAR_BIT, cp--) { if (*cp == 0) continue; for (i = 1 << (CHAR_BIT - 1); i > 0; i >>= 1) { if (*cp & i) break; inosused--; } break; } if (inosused <= 0) continue; } for (i = 0; i < inosused; i++, ino++) { if ((dp = getnextinode(ino)) == NULL || ino < ROOTINO || (mode = DIP(dp, di_mode) & IFMT) == 0) continue; if (qnp->flags & HASGRP) { fup = addid(DIP(dp, di_gid), GRPQUOTA, NULL); fup->fu_curinodes++; if (mode == IFREG || mode == IFDIR || mode == IFLNK) fup->fu_curblocks += DIP(dp, di_blocks); } if (qnp->flags & HASUSR) { fup = addid(DIP(dp, di_uid), USRQUOTA, NULL); fup->fu_curinodes++; if (mode == IFREG || mode == IFDIR || mode == IFLNK) fup->fu_curblocks += DIP(dp, di_blocks); } } } freeinodebuf(); if (flags&(CHECK_DEBUG|CHECK_VERBOSE)) { (void)printf("*** Checking "); if (qnp->flags & HASUSR) { (void)printf("%s", qfextension[USRQUOTA]); if (qnp->flags & HASGRP) (void)printf(" and "); } if (qnp->flags & HASGRP) (void)printf("%s", qfextension[GRPQUOTA]); (void)printf(" quotas for %s (%s), %swait\n", fsname, mntpt, pidp? "no" : ""); } if (qnp->flags & HASUSR) errs += update(mntpt, qnp->usrqfname, USRQUOTA); if (qnp->flags & HASGRP) errs += update(mntpt, qnp->grpqfname, GRPQUOTA); close(fi); exit (errs); break; default: /* parent */ if (pidp != NULL) { *pidp = pid; return 0; } if (waitpid(pid, &status, 0) < 0) { warn("waitpid"); return 1; } if (WIFEXITED(status)) { if (WEXITSTATUS(status) != 0) return WEXITSTATUS(status); } else if (WIFSIGNALED(status)) { warnx("%s: %s", fsname, strsignal(WTERMSIG(status))); return 1; } break; } return (0); }
void doit () { int err, i; int sockets[2]; const char *srcdir; char *pub_key_path, *priv_key_path; pid_t child; gnutls_global_init (); srcdir = getenv ("srcdir") ? getenv ("srcdir") : "."; for (i = 0; i < 4; i++) { if (i <= 1) key_id = NULL; /* try using the master key */ else if (i == 2) key_id = "auto"; /* test auto */ else if (i == 3) key_id = "f30fd423c143e7ba"; if (debug) { gnutls_global_set_log_level (5); gnutls_global_set_log_function (log_message); } err = socketpair (AF_UNIX, SOCK_STREAM, 0, sockets); if (err != 0) fail ("socketpair %s\n", strerror (errno)); pub_key_path = alloca (strlen (srcdir) + strlen (pub_key_file) + 2); strcpy (pub_key_path, srcdir); strcat (pub_key_path, "/"); strcat (pub_key_path, pub_key_file); priv_key_path = alloca (strlen (srcdir) + strlen (priv_key_file) + 2); strcpy (priv_key_path, srcdir); strcat (priv_key_path, "/"); strcat (priv_key_path, priv_key_file); child = fork (); if (child == -1) fail ("fork %s\n", strerror (errno)); if (child == 0) { /* Child process (client). */ gnutls_session_t session; gnutls_certificate_credentials_t cred; ssize_t sent; if (debug) printf ("client process %i\n", getpid ()); err = gnutls_init (&session, GNUTLS_CLIENT); if (err != 0) fail ("client session %d\n", err); if (i==0) /* we use the primary key which is RSA. Test the RSA ciphersuite */ gnutls_priority_set_direct (session, "NONE:+VERS-TLS1.0:+CIPHER-ALL:+MAC-ALL:+SIGN-ALL:+COMP-ALL:+RSA:+CTYPE-OPENPGP", NULL); else gnutls_priority_set_direct (session, "NONE:+VERS-TLS1.0:+CIPHER-ALL:+MAC-ALL:+SIGN-ALL:+COMP-ALL:+DHE-DSS:+DHE-RSA:+CTYPE-OPENPGP", NULL); gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) (intptr_t) sockets[0]); err = gnutls_certificate_allocate_credentials (&cred); if (err != 0) fail ("client credentials %d\n", err); err = gnutls_certificate_set_openpgp_key_file2 (cred, pub_key_path, priv_key_path, key_id, GNUTLS_OPENPGP_FMT_BASE64); if (err != 0) fail ("client openpgp keys %s\n", gnutls_strerror (err)); err = gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, cred); if (err != 0) fail ("client credential_set %d\n", err); gnutls_dh_set_prime_bits (session, 1024); err = gnutls_handshake (session); if (err != 0) fail ("client handshake %s (%d) \n", gnutls_strerror (err), err); else if (debug) printf ("client handshake successful\n"); sent = gnutls_record_send (session, message, sizeof (message)); if (sent != sizeof (message)) fail ("client sent %li vs. %li\n", (long) sent, (long) sizeof (message)); err = gnutls_bye (session, GNUTLS_SHUT_RDWR); if (err != 0) fail ("client bye %d\n", err); if (debug) printf ("client done\n"); gnutls_deinit(session); gnutls_certificate_free_credentials (cred); } else { /* Parent process (server). */ gnutls_session_t session; gnutls_dh_params_t dh_params; gnutls_certificate_credentials_t cred; char greetings[sizeof (message) * 2]; ssize_t received; pid_t done; int status; const gnutls_datum_t p3 = { (void *) pkcs3, strlen (pkcs3) }; if (debug) printf ("server process %i (child %i)\n", getpid (), child); err = gnutls_init (&session, GNUTLS_SERVER); if (err != 0) fail ("server session %d\n", err); gnutls_priority_set_direct (session, "NONE:+VERS-TLS1.0:+CIPHER-ALL:+MAC-ALL:+SIGN-ALL:+COMP-ALL:+DHE-DSS:+DHE-RSA:+RSA:+CTYPE-OPENPGP", NULL); gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) (intptr_t) sockets[1]); err = gnutls_certificate_allocate_credentials (&cred); if (err != 0) fail ("server credentials %d\n", err); err = gnutls_certificate_set_openpgp_key_file2 (cred, pub_key_path, priv_key_path, key_id, GNUTLS_OPENPGP_FMT_BASE64); if (err != 0) fail ("server openpgp keys %s\n", gnutls_strerror (err)); err = gnutls_dh_params_init (&dh_params); if (err) fail ("server DH params init %d\n", err); err = gnutls_dh_params_import_pkcs3 (dh_params, &p3, GNUTLS_X509_FMT_PEM); if (err) fail ("server DH params generate %d\n", err); gnutls_certificate_set_dh_params (cred, dh_params); err = gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, cred); if (err != 0) fail ("server credential_set %d\n", err); gnutls_certificate_server_set_request (session, GNUTLS_CERT_REQUIRE); err = gnutls_handshake (session); if (err != 0) fail ("server handshake %s (%d) \n", gnutls_strerror (err), err); received = gnutls_record_recv (session, greetings, sizeof (greetings)); if (received != sizeof (message) || memcmp (greetings, message, sizeof (message))) fail ("server received %li vs. %li\n", (long) received, (long) sizeof (message)); err = gnutls_bye (session, GNUTLS_SHUT_RDWR); if (err != 0) fail ("server bye %s (%d) \n", gnutls_strerror (err), err); if (debug) printf ("server done\n"); gnutls_deinit(session); gnutls_certificate_free_credentials (cred); gnutls_dh_params_deinit (dh_params); done = wait (&status); if (done < 0) fail ("wait %s\n", strerror (errno)); if (done != child) fail ("who's that?! %d\n", done); if (WIFEXITED (status)) { if (WEXITSTATUS (status) != 0) fail ("child exited with status %d\n", WEXITSTATUS (status)); } else if (WIFSIGNALED (status)) fail ("child stopped by signal %d\n", WTERMSIG (status)); else fail ("child failed: %d\n", status); } } gnutls_global_deinit (); }
int Sudo::parent() { //set the FD as non-blocking if (0 != fcntl(mPwdFd, F_SETFL, O_NONBLOCK)) { QMessageBox(QMessageBox::Critical, mDlg->windowTitle() , tr("Failed to set non-block: %1").arg(strerror(errno)), QMessageBox::Ok).exec(); return 1; } FILE * pwd_f = fdopen(mPwdFd, "r+"); if (nullptr == pwd_f) { QMessageBox(QMessageBox::Critical, mDlg->windowTitle() , tr("Failed to fdopen: %1").arg(strerror(errno)), QMessageBox::Ok).exec(); return 1; } QTextStream child_str{pwd_f}; QObject::connect(mDlg.data(), &QDialog::finished, [&] (int result) { if (QDialog::Accepted == result) { child_str << mDlg->password().append(nl); child_str.flush(); } else { stopChild(); lxqtApp->quit(); } }); QString last_line; QScopedPointer<QSocketNotifier> pwd_watcher{new QSocketNotifier{mPwdFd, QSocketNotifier::Read}}; QObject::connect(pwd_watcher.data(), &QSocketNotifier::activated, [&] { QString line = child_str.readAll(); if (line.isEmpty()) { pwd_watcher.reset(nullptr); QString const & prog = BACK_SU == mBackend ? su_prog : sudo_prog; if (last_line.startsWith(QStringLiteral("%1:").arg(prog))) { pwd_watcher.reset(nullptr); //stop the notifications events stopChild(); QMessageBox(QMessageBox::Critical, mDlg->windowTitle() , tr("Child '%1' process failed!\n%2").arg(prog).arg(last_line), QMessageBox::Ok).exec(); } lxqtApp->quit(); } else { if (line.endsWith(pwd_prompt_end)) { //if now echo is turned off, su/sudo requests password struct termios tios; //loop to be sure we don't miss the flag (we can afford such small delay in "normal" output processing) for (size_t cnt = 10; 0 < cnt && 0 == tcgetattr(mPwdFd, &tios) && (ECHO & tios.c_lflag); --cnt) QThread::msleep(10); if (!(ECHO & tios.c_lflag)) { mDlg->show(); return; } } QTextStream{stderr, QIODevice::WriteOnly} << line; //assuming text oriented output QStringList lines = line.split(nl, QString::SkipEmptyParts); last_line = lines.isEmpty() ? QString() : lines.back(); } }); lxqtApp->exec(); if (0 < mChildPid) { int res, status; res = waitpid(mChildPid, &status, 0); mRet = (mChildPid == res && WIFEXITED(status)) ? WEXITSTATUS(status) : 1; } return mRet; }
/* * Performs the interactive session. This handles data transmission between * the client and the program. Note that the notion of stdin, stdout, and * stderr in this function is sort of reversed: this function writes to * stdin (of the child program), and reads from stdout and stderr (of the * child program). */ void server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg) { fd_set *readset = NULL, *writeset = NULL; int max_fd = 0; u_int nalloc = 0; int wait_status; /* Status returned by wait(). */ pid_t wait_pid; /* pid returned by wait(). */ int waiting_termination = 0; /* Have displayed waiting close message. */ u_int max_time_milliseconds; u_int previous_stdout_buffer_bytes; u_int stdout_buffer_bytes; int type; debug("Entering interactive session."); /* Initialize the SIGCHLD kludge. */ child_terminated = 0; mysignal(SIGCHLD, sigchld_handler); if (!use_privsep) { signal(SIGTERM, sigterm_handler); signal(SIGINT, sigterm_handler); signal(SIGQUIT, sigterm_handler); } /* Initialize our global variables. */ fdin = fdin_arg; fdout = fdout_arg; fderr = fderr_arg; /* nonblocking IO */ set_nonblock(fdin); set_nonblock(fdout); /* we don't have stderr for interactive terminal sessions, see below */ if (fderr != -1) set_nonblock(fderr); if (!(datafellows & SSH_BUG_IGNOREMSG) && isatty(fdin)) fdin_is_tty = 1; connection_in = packet_get_connection_in(); connection_out = packet_get_connection_out(); notify_setup(); previous_stdout_buffer_bytes = 0; /* Set approximate I/O buffer size. */ if (packet_is_interactive()) buffer_high = 4096; else buffer_high = 64 * 1024; #if 0 /* Initialize max_fd to the maximum of the known file descriptors. */ max_fd = MAX(connection_in, connection_out); max_fd = MAX(max_fd, fdin); max_fd = MAX(max_fd, fdout); if (fderr != -1) max_fd = MAX(max_fd, fderr); #endif /* Initialize Initialize buffers. */ buffer_init(&stdin_buffer); buffer_init(&stdout_buffer); buffer_init(&stderr_buffer); /* * If we have no separate fderr (which is the case when we have a pty * - there we cannot make difference between data sent to stdout and * stderr), indicate that we have seen an EOF from stderr. This way * we don't need to check the descriptor everywhere. */ if (fderr == -1) fderr_eof = 1; server_init_dispatch(); /* Main loop of the server for the interactive session mode. */ for (;;) { /* Process buffered packets from the client. */ process_buffered_input_packets(); /* * If we have received eof, and there is no more pending * input data, cause a real eof by closing fdin. */ if (stdin_eof && fdin != -1 && buffer_len(&stdin_buffer) == 0) { if (fdin != fdout) close(fdin); else shutdown(fdin, SHUT_WR); /* We will no longer send. */ fdin = -1; } /* Make packets from buffered stderr data to send to the client. */ make_packets_from_stderr_data(); /* * Make packets from buffered stdout data to send to the * client. If there is very little to send, this arranges to * not send them now, but to wait a short while to see if we * are getting more data. This is necessary, as some systems * wake up readers from a pty after each separate character. */ max_time_milliseconds = 0; stdout_buffer_bytes = buffer_len(&stdout_buffer); if (stdout_buffer_bytes != 0 && stdout_buffer_bytes < 256 && stdout_buffer_bytes != previous_stdout_buffer_bytes) { /* try again after a while */ max_time_milliseconds = 10; } else { /* Send it now. */ make_packets_from_stdout_data(); } previous_stdout_buffer_bytes = buffer_len(&stdout_buffer); /* Send channel data to the client. */ if (packet_not_very_much_data_to_write()) channel_output_poll(); /* * Bail out of the loop if the program has closed its output * descriptors, and we have no more data to send to the * client, and there is no pending buffered data. */ if (fdout_eof && fderr_eof && !packet_have_data_to_write() && buffer_len(&stdout_buffer) == 0 && buffer_len(&stderr_buffer) == 0) { if (!channel_still_open()) break; if (!waiting_termination) { const char *s = "Waiting for forwarded connections to terminate...\r\n"; char *cp; waiting_termination = 1; buffer_append(&stderr_buffer, s, strlen(s)); /* Display list of open channels. */ cp = channel_open_message(); buffer_append(&stderr_buffer, cp, strlen(cp)); xfree(cp); } } max_fd = MAX(connection_in, connection_out); max_fd = MAX(max_fd, fdin); max_fd = MAX(max_fd, fdout); max_fd = MAX(max_fd, fderr); max_fd = MAX(max_fd, notify_pipe[0]); /* Sleep in select() until we can do something. */ wait_until_can_do_something(&readset, &writeset, &max_fd, &nalloc, max_time_milliseconds); if (received_sigterm) { logit("Exiting on signal %d", received_sigterm); /* Clean up sessions, utmp, etc. */ cleanup_exit(255); } /* Process any channel events. */ channel_after_select(readset, writeset); /* Process input from the client and from program stdout/stderr. */ process_input(readset); /* Process output to the client and to program stdin. */ process_output(writeset); } if (readset) xfree(readset); if (writeset) xfree(writeset); /* Cleanup and termination code. */ /* Wait until all output has been sent to the client. */ drain_output(); debug("End of interactive session; stdin %ld, stdout (read %ld, sent %ld), stderr %ld bytes.", stdin_bytes, fdout_bytes, stdout_bytes, stderr_bytes); /* Free and clear the buffers. */ buffer_free(&stdin_buffer); buffer_free(&stdout_buffer); buffer_free(&stderr_buffer); /* Close the file descriptors. */ if (fdout != -1) close(fdout); fdout = -1; fdout_eof = 1; if (fderr != -1) close(fderr); fderr = -1; fderr_eof = 1; if (fdin != -1) close(fdin); fdin = -1; channel_free_all(); /* We no longer want our SIGCHLD handler to be called. */ mysignal(SIGCHLD, SIG_DFL); while ((wait_pid = waitpid(-1, &wait_status, 0)) < 0) if (errno != EINTR) packet_disconnect("wait: %.100s", strerror(errno)); if (wait_pid != pid) error("Strange, wait returned pid %ld, expected %ld", (long)wait_pid, (long)pid); /* Check if it exited normally. */ if (WIFEXITED(wait_status)) { /* Yes, normal exit. Get exit status and send it to the client. */ debug("Command exited with status %d.", WEXITSTATUS(wait_status)); packet_start(SSH_SMSG_EXITSTATUS); packet_put_int(WEXITSTATUS(wait_status)); packet_send(); packet_write_wait(); /* * Wait for exit confirmation. Note that there might be * other packets coming before it; however, the program has * already died so we just ignore them. The client is * supposed to respond with the confirmation when it receives * the exit status. */ do { type = packet_read(); } while (type != SSH_CMSG_EXIT_CONFIRMATION); debug("Received exit confirmation."); return; } /* Check if the program terminated due to a signal. */ if (WIFSIGNALED(wait_status)) packet_disconnect("Command terminated on signal %d.", WTERMSIG(wait_status)); /* Some weird exit cause. Just exit. */ packet_disconnect("wait returned status %04x.", wait_status); /* NOTREACHED */ }
EXPORT_C #endif void _dbus_babysitter_unref (DBusBabysitter *sitter) { _dbus_assert (sitter != NULL); _dbus_assert (sitter->refcount > 0); sitter->refcount -= 1; if (sitter->refcount == 0) { if (sitter->socket_to_babysitter >= 0) { /* If we haven't forked other babysitters * since this babysitter and socket were * created then this close will cause the * babysitter to wake up from poll with * a hangup and then the babysitter will * quit itself. */ _dbus_close_socket (sitter->socket_to_babysitter, NULL); sitter->socket_to_babysitter = -1; } if (sitter->error_pipe_from_child >= 0) { _dbus_close_socket (sitter->error_pipe_from_child, NULL); sitter->error_pipe_from_child = -1; } if (sitter->sitter_pid > 0) { int status; int ret; /* It's possible the babysitter died on its own above * from the close, or was killed randomly * by some other process, so first try to reap it */ ret = waitpid (sitter->sitter_pid, &status, WNOHANG); /* If we couldn't reap the child then kill it, and * try again */ #ifndef __SYMBIAN32__ if (ret == 0) kill (sitter->sitter_pid, SIGKILL); #endif again: if (ret == 0) ret = waitpid (sitter->sitter_pid, &status, 0); if (ret < 0) { if (errno == EINTR) goto again; else if (errno == ECHILD) _dbus_warn ("Babysitter process not available to be reaped; should not happen\n"); else _dbus_warn ("Unexpected error %d in waitpid() for babysitter: %s\n", errno, _dbus_strerror (errno)); } else { _dbus_verbose ("Reaped %ld, waiting for babysitter %ld\n", (long) ret, (long) sitter->sitter_pid); if (WIFEXITED (sitter->status)) _dbus_verbose ("Babysitter exited with status %d\n", WEXITSTATUS (sitter->status)); else if (WIFSIGNALED (sitter->status)) _dbus_verbose ("Babysitter received signal %d\n", WTERMSIG (sitter->status)); else _dbus_verbose ("Babysitter exited abnormally\n"); } sitter->sitter_pid = -1; } if (sitter->error_watch) { _dbus_watch_invalidate (sitter->error_watch); _dbus_watch_unref (sitter->error_watch); sitter->error_watch = NULL; } if (sitter->sitter_watch) { _dbus_watch_invalidate (sitter->sitter_watch); _dbus_watch_unref (sitter->sitter_watch); sitter->sitter_watch = NULL; } if (sitter->watches) _dbus_watch_list_free (sitter->watches); dbus_free (sitter->executable); dbus_free (sitter); } }
static ReadStatus read_data (DBusBabysitter *sitter, int fd) { int what; int got; DBusError error; ReadStatus r; dbus_error_init (&error); r = read_ints (fd, &what, 1, &got, &error); switch (r) { case READ_STATUS_ERROR: _dbus_warn ("Failed to read data from fd %d: %s\n", fd, error.message); dbus_error_free (&error); return r; case READ_STATUS_EOF: return r; case READ_STATUS_OK: break; } if (got == 1) { switch (what) { case CHILD_EXITED: case CHILD_FORK_FAILED: case CHILD_EXEC_FAILED: { int arg; r = read_ints (fd, &arg, 1, &got, &error); switch (r) { case READ_STATUS_ERROR: _dbus_warn ("Failed to read arg from fd %d: %s\n", fd, error.message); dbus_error_free (&error); return r; case READ_STATUS_EOF: return r; case READ_STATUS_OK: break; } if (got == 1) { if (what == CHILD_EXITED) { sitter->have_child_status = TRUE; sitter->status = arg; _dbus_verbose ("recorded child status exited = %d signaled = %d exitstatus = %d termsig = %d\n", WIFEXITED (sitter->status), WIFSIGNALED (sitter->status), WEXITSTATUS (sitter->status), WTERMSIG (sitter->status)); } else if (what == CHILD_FORK_FAILED) { sitter->have_fork_errnum = TRUE; sitter->errnum = arg; _dbus_verbose ("recorded fork errnum %d\n", sitter->errnum); } else if (what == CHILD_EXEC_FAILED) { sitter->have_exec_errnum = TRUE; sitter->errnum = arg; _dbus_verbose ("recorded exec errnum %d\n", sitter->errnum); } } } break; case CHILD_PID: { pid_t pid = -1; r = read_pid (fd, &pid, &error); switch (r) { case READ_STATUS_ERROR: _dbus_warn ("Failed to read PID from fd %d: %s\n", fd, error.message); dbus_error_free (&error); return r; case READ_STATUS_EOF: return r; case READ_STATUS_OK: break; } sitter->grandchild_pid = pid; _dbus_verbose ("recorded grandchild pid %d\n", sitter->grandchild_pid); } break; default: _dbus_warn ("Unknown message received from babysitter process\n"); break; } } return r; }
int callPosixSpawn(const char *cmdline) { char command[1024]; char progName[1024]; char progPath[MAXPATHLEN]; char* argv[100]; int argc = 0; char *p; pid_t thePid = 0; int result = 0; int status = 0; extern char **environ; // Make a copy of cmdline because parse_posic_spawn_command_line modifies it strlcpy(command, cmdline, sizeof(command)); argc = parse_posic_spawn_command_line(const_cast<char*>(command), argv); strlcpy(progPath, argv[0], sizeof(progPath)); strlcpy(progName, argv[0], sizeof(progName)); p = strrchr(progName, '/'); if (p) { argv[0] = p+1; } else { argv[0] = progName; } #if VERBOSE_SPAWN fprintf(stderr, "***********"); for (int i=0; i<argc; ++i) { fprintf(stderr, "argv[%d]=%s", i, argv[i]); } fprintf(stderr, "***********\n"); #endif errno = 0; result = posix_spawnp(&thePid, progPath, NULL, NULL, argv, environ); #if VERBOSE_SPAWN fprintf(stderr, "callPosixSpawn command: %s", cmdline); fprintf(stderr, "callPosixSpawn: posix_spawnp returned %d: %s", result, strerror(result)); #endif if (result) { return result; } // CAF int val = waitpid(thePid, &status, WUNTRACED); // CAF if (val < 0) printf("first waitpid returned %d\n", val); if (status != 0) { #if VERBOSE_SPAWN fprintf(stderr, "waitpid() returned status=%d", status); #endif result = status; } else { if (WIFEXITED(status)) { result = WEXITSTATUS(status); if (result == 1) { #if VERBOSE_SPAWN fprintf(stderr, "WEXITSTATUS(status) returned 1, errno=%d: %s", errno, strerror(errno)); #endif result = errno; } #if VERBOSE_SPAWN else if (result) { fprintf(stderr, "WEXITSTATUS(status) returned %d", result); } #endif } // end if (WIFEXITED(status)) else } // end if waitpid returned 0 sstaus else return result; }
void _ecore_signal_call(void) { #ifdef SIGRTMIN int i, num = SIGRTMAX - SIGRTMIN; #endif volatile sig_atomic_t n; sigset_t oldset, newset; if (sig_count == 0) return; sigemptyset(&newset); sigaddset(&newset, SIGPIPE); sigaddset(&newset, SIGALRM); sigaddset(&newset, SIGCHLD); sigaddset(&newset, SIGUSR1); sigaddset(&newset, SIGUSR2); sigaddset(&newset, SIGHUP); sigaddset(&newset, SIGQUIT); sigaddset(&newset, SIGINT); sigaddset(&newset, SIGTERM); #ifdef SIGPWR sigaddset(&newset, SIGPWR); #endif #ifdef SIGRTMIN for (i = 0; i < num; i++) sigaddset(&newset, SIGRTMIN + i); #endif sigprocmask(SIG_BLOCK, &newset, &oldset); if (sigchld_count > MAXSIGQ) WRN("%i SIGCHLD in queue. max queue size %i. losing " "siginfo for extra signals.", sigchld_count, MAXSIGQ); for (n = 0; n < sigchld_count; n++) { pid_t pid; int status; while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { Ecore_Exe_Event_Del *e; /* FIXME: If this process is set respawn, respawn with a suitable backoff * period for those that need too much respawning. */ e = _ecore_exe_event_del_new(); if (e) { if (WIFEXITED(status)) { e->exit_code = WEXITSTATUS(status); e->exited = 1; } else if (WIFSIGNALED(status)) { e->exit_signal = WTERMSIG(status); e->signalled = 1; } e->pid = pid; e->exe = _ecore_exe_find(pid); if ((n < MAXSIGQ) && (sigchld_info[n].si_signo)) e->data = sigchld_info[n]; /* No need to clone this. */ if ((e->exe) && (ecore_exe_flags_get(e->exe) & (ECORE_EXE_PIPE_READ | ECORE_EXE_PIPE_ERROR))) { /* We want to report the Last Words of the exe, so delay this event. * This is twice as relevant for stderr. * There are three possibilities here - * 1 There are no Last Words. * 2 There are Last Words, they are not ready to be read. * 3 There are Last Words, they are ready to be read. * * For 1 we don't want to delay, for 3 we want to delay. * 2 is the problem. If we check for data now and there * is none, then there is no way to differentiate 1 and 2. * If we don't delay, we may loose data, but if we do delay, * there may not be data and the exit event never gets sent. * * Any way you look at it, there has to be some time passed * before the exit event gets sent. So the strategy here is * to setup a timer event that will send the exit event after * an arbitrary, but brief, time. * * This is probably paranoid, for the less paraniod, we could * check to see for Last Words, and only delay if there are any. * This has it's own set of problems. */ Ecore_Timer *doomsday_clock; doomsday_clock = _ecore_exe_doomsday_clock_get(e->exe); IF_FN_DEL(ecore_timer_del, doomsday_clock); _ecore_exe_doomsday_clock_set(e->exe, ecore_timer_add(0.1, _ecore_signal_exe_exit_delay, e)); } else { _ecore_event_add(ECORE_EXE_EVENT_DEL, e, _ecore_exe_event_del_free, NULL); } } } sig_count--; } sigchld_count = 0; if (sigusr1_count > MAXSIGQ) WRN("%i SIGUSR1 in queue. max queue size %i. losing " "siginfo for extra signals.", sigusr1_count, MAXSIGQ); for (n = 0; n < sigusr1_count; n++) { Ecore_Event_Signal_User *e; e = _ecore_event_signal_user_new(); if (e) { e->number = 1; if ((n < MAXSIGQ) && (sigusr1_info[n].si_signo)) e->data = sigusr1_info[n]; ecore_event_add(ECORE_EVENT_SIGNAL_USER, e, NULL, NULL); } sig_count--; } sigusr1_count = 0; if (sigusr2_count > MAXSIGQ) WRN("%i SIGUSR2 in queue. max queue size %i. losing " "siginfo for extra signals.", sigusr2_count, MAXSIGQ); for (n = 0; n < sigusr2_count; n++) { Ecore_Event_Signal_User *e; e = _ecore_event_signal_user_new(); if (e) { e->number = 2; if ((n < MAXSIGQ) && (sigusr2_info[n].si_signo)) e->data = sigusr2_info[n]; ecore_event_add(ECORE_EVENT_SIGNAL_USER, e, NULL, NULL); } sig_count--; } sigusr2_count = 0; if (sighup_count > MAXSIGQ) WRN("%i SIGHUP in queue. max queue size %i. losing " "siginfo for extra signals.", sighup_count, MAXSIGQ); for (n = 0; n < sighup_count; n++) { Ecore_Event_Signal_Hup *e; e = _ecore_event_signal_hup_new(); if (e) { if ((n < MAXSIGQ) && (sighup_info[n].si_signo)) e->data = sighup_info[n]; ecore_event_add(ECORE_EVENT_SIGNAL_HUP, e, NULL, NULL); } sig_count--; } sighup_count = 0; if (sigquit_count > MAXSIGQ) WRN("%i SIGQUIT in queue. max queue size %i. losing " "siginfo for extra signals.", sigquit_count, MAXSIGQ); for (n = 0; n < sigquit_count; n++) { Ecore_Event_Signal_Exit *e; e = _ecore_event_signal_exit_new(); if (e) { e->quit = 1; if ((n < MAXSIGQ) && (sigquit_info[n].si_signo)) e->data = sigquit_info[n]; ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, e, NULL, NULL); } sig_count--; } sigquit_count = 0; if (sigint_count > MAXSIGQ) WRN("%i SIGINT in queue. max queue size %i. losing " "siginfo for extra signals.", sigint_count, MAXSIGQ); for (n = 0; n < sigint_count; n++) { Ecore_Event_Signal_Exit *e; e = _ecore_event_signal_exit_new(); if (e) { e->interrupt = 1; if ((n < MAXSIGQ) && (sigint_info[n].si_signo)) e->data = sigint_info[n]; ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, e, NULL, NULL); } sig_count--; } sigint_count = 0; if (sigterm_count > MAXSIGQ) WRN("%i SIGTERM in queue. max queue size %i. losing " "siginfo for extra signals.", sigterm_count, MAXSIGQ); for (n = 0; n < sigterm_count; n++) { Ecore_Event_Signal_Exit *e; e = _ecore_event_signal_exit_new(); if (e) { e->terminate = 1; if ((n < MAXSIGQ) && (sigterm_info[n].si_signo)) e->data = sigterm_info[n]; ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, e, NULL, NULL); } sig_count--; } sigterm_count = 0; #ifdef SIGPWR if (sigpwr_count > MAXSIGQ) WRN("%i SIGPWR in queue. max queue size %i. losing " "siginfo for extra signals.", sigpwr_count, MAXSIGQ); for (n = 0; n < sigpwr_count; n++) { Ecore_Event_Signal_Power *e; e = _ecore_event_signal_power_new(); if (e) { if ((n < MAXSIGQ) && (sigpwr_info[n].si_signo)) e->data = sigpwr_info[n]; ecore_event_add(ECORE_EVENT_SIGNAL_POWER, e, NULL, NULL); } sig_count--; } sigpwr_count = 0; #endif #ifdef SIGRTMIN for (i = 0; i < num; i++) { if (sigrt_count[i] > MAXSIGQ) WRN("%i SIGRT%i in queue. max queue size %i. losing " "siginfo for extra signals.", i + 1, sigrt_count[i], MAXSIGQ); for (n = 0; n < sigrt_count[i]; n++) { Ecore_Event_Signal_Realtime *e; if ((e = _ecore_event_signal_realtime_new())) { e->num = i; if ((n < MAXSIGQ) && (sigrt_info[n][i].si_signo)) e->data = sigrt_info[n][i]; ecore_event_add(ECORE_EVENT_SIGNAL_REALTIME, e, NULL, NULL); } sig_count--; } sigrt_count[i] = 0; } #endif sigprocmask(SIG_SETMASK, &oldset, NULL); }
extern int slurm_ckpt_signal_tasks(stepd_step_rec_t *job, char *image_dir) { char *argv[4]; char context_file[MAXPATHLEN]; char pid[16]; int status; pid_t *children = NULL; int *fd = NULL; int rc = SLURM_SUCCESS; int i; char c; debug3("checkpoint/blcr: slurm_ckpt_signal_tasks: image_dir=%s", image_dir); /* * the tasks must be checkpointed concurrently. */ children = xmalloc(sizeof(pid_t) * job->node_tasks); fd = xmalloc(sizeof(int) * 2 * job->node_tasks); if (!children || !fd) { error("slurm_ckpt_signal_tasks: memory exhausted"); rc = SLURM_FAILURE; goto out; } for (i = 0; i < job->node_tasks; i ++) { fd[i*2] = -1; fd[i*2+1] = -1; } for (i = 0; i < job->node_tasks; i ++) { if (job->batch) { sprintf(context_file, "%s/script.ckpt", image_dir); } else { sprintf(context_file, "%s/task.%d.ckpt", image_dir, job->task[i]->gtid); } sprintf(pid, "%u", (unsigned int)job->task[i]->pid); if (pipe(&fd[i*2]) < 0) { error("failed to create pipes: %m"); rc = SLURM_ERROR; goto out_wait; } children[i] = fork(); if (children[i] < 0) { error("error forking cr_checkpoint"); rc = SLURM_ERROR; goto out_wait; } else if (children[i] == 0) { close(fd[i*2+1]); while(read(fd[i*2], &c, 1) < 0 && errno == EINTR); if (c) exit(-1); /* change cred to job owner */ if (setgid(job->gid) < 0) { error ("checkpoint/blcr: " "slurm_ckpt_signal_tasks: " "failed to setgid: %m"); exit(errno); } if (setuid(job->uid) < 0) { error ("checkpoint/blcr: " "slurm_ckpt_signal_tasks: " "failed to setuid: %m"); exit(errno); } if (chdir(job->cwd) < 0) { error ("checkpoint/blcr: " "slurm_ckpt_signal_tasks: " "failed to chdir: %m"); exit(errno); } argv[0] = (char *)cr_checkpoint_path; argv[1] = pid; argv[2] = context_file; argv[3] = NULL; execv(argv[0], argv); exit(errno); } close(fd[i*2]); } out_wait: c = (rc == SLURM_SUCCESS) ? 0 : 1; for (i = 0; i < job->node_tasks; i ++) { if (fd[i*2+1] >= 0) { while(write(fd[i*2+1], &c, 1) < 0 && errno == EINTR); } } /* wait children in sequence is OK */ for (i = 0; i < job->node_tasks; i ++) { if (children[i] == 0) continue; while(waitpid(children[i], &status, 0) < 0 && errno == EINTR); if (! (WIFEXITED(status) && WEXITSTATUS(status))== 0) rc = SLURM_ERROR; } out: xfree(children); xfree(fd); return rc; }
int main(void) { int pid; int rc; int pfd[2]; int status = PTS_UNRESOLVED; int s; struct sched_param sp; char buf[8]; /* Set up a pipe, for synching. */ rc = pipe(pfd); if (rc) { ERR_LOG("pipe", rc); return status; } /* get in FIFO */ sp.sched_priority = sched_get_priority_min(SCHED_FIFO); rc = sched_setscheduler(getpid(), SCHED_FIFO, &sp); if (rc) { ERR_LOG("sched_setscheduler", rc); return status; } /* Must only use a single CPU */ rc = set_affinity(0); if (rc) { ERR_LOG("set_affinity", rc); return status; } pid = fork(); if (pid == 0) child_busy(pfd[1]); if (pid < 0) { ERR_LOG("fork", rc); return status; } /* wait for child */ rc = read(pfd[0], buf, sizeof(buf)); if (rc != 2) { kill(pid, SIGTERM); waitpid(pid, NULL, 0); ERR_LOG("read", rc); return status; } /* Can only get here if sched_yield works. */ kill(pid, SIGTERM); waitpid(pid, &s, 0); status = PTS_PASS; if (WIFSIGNALED(s)) { s = WTERMSIG(s); if (s != SIGTERM) { printf("Failed: kill signal: %d, should be: %d\n", s, SIGTERM); status = PTS_FAIL; } } else if (WIFEXITED(s)) { printf("Failed: child prematurely exited with: %d\n", WEXITSTATUS(s)); status = PTS_FAIL; } if (status == PTS_PASS) printf("Test PASSED\n"); return status; }
/* * Close both pipes and free resources * * Returns: 0 on success * berrno on failure */ int close_bpipe(BPIPE *bpipe) { int chldstatus = 0; int stat = 0; int wait_option; int remaining_wait; pid_t wpid = 0; /* Close pipes */ if (bpipe->rfd) { fclose(bpipe->rfd); bpipe->rfd = NULL; } if (bpipe->wfd) { fclose(bpipe->wfd); bpipe->wfd = NULL; } if (bpipe->wait == 0) { wait_option = 0; /* wait indefinitely */ } else { wait_option = WNOHANG; /* don't hang */ } remaining_wait = bpipe->wait; /* wait for worker child to exit */ for ( ;; ) { Dmsg2(800, "Wait for %d opt=%d\n", bpipe->worker_pid, wait_option); do { wpid = waitpid(bpipe->worker_pid, &chldstatus, wait_option); } while (wpid == -1 && (errno == EINTR || errno == EAGAIN)); if (wpid == bpipe->worker_pid || wpid == -1) { berrno be; stat = errno; Dmsg3(800, "Got break wpid=%d status=%d ERR=%s\n", wpid, chldstatus, wpid==-1?be.bstrerror():"none"); break; } Dmsg3(800, "Got wpid=%d status=%d ERR=%s\n", wpid, chldstatus, wpid==-1?strerror(errno):"none"); if (remaining_wait > 0) { bmicrosleep(1, 0); /* wait one second */ remaining_wait--; } else { stat = ETIME; /* set error status */ wpid = -1; break; /* don't wait any longer */ } } if (wpid > 0) { if (WIFEXITED(chldstatus)) { /* process exit()ed */ stat = WEXITSTATUS(chldstatus); if (stat != 0) { Dmsg1(800, "Non-zero status %d returned from child.\n", stat); stat |= b_errno_exit; /* exit status returned */ } Dmsg1(800, "child status=%d\n", stat & ~b_errno_exit); } else if (WIFSIGNALED(chldstatus)) { /* process died */ #ifndef HAVE_WIN32 stat = WTERMSIG(chldstatus); #else stat = 1; /* fake child status */ #endif Dmsg1(800, "Child died from signal %d\n", stat); stat |= b_errno_signal; /* exit signal returned */ } } if (bpipe->timer_id) { stop_child_timer(bpipe->timer_id); } free(bpipe); Dmsg2(800, "returning stat=%d,%d\n", stat & ~(b_errno_exit|b_errno_signal), stat); return stat; }
int exec_str(struct sip_msg *msg, str* cmd, char *param, int param_len) { struct action act; int cmd_len; FILE *pipe; char *cmd_line; int ret; char uri_line[MAX_URI_SIZE+1]; int uri_cnt; int uri_len; int exit_status; /* pessimist: assume error by default */ ret=-1; cmd_len=cmd->len+param_len+2; cmd_line=pkg_malloc(cmd_len); if (cmd_line==0) { ret=ser_error=E_OUT_OF_MEM; LOG(L_ERR, "ERROR: exec_str: no mem for command\n"); goto error00; } /* 'command parameter \0' */ memcpy(cmd_line, cmd->s, cmd->len); cmd_line[cmd->len]=' '; memcpy(cmd_line+cmd->len+1, param, param_len);cmd_line[cmd->len+param_len+1]=0; pipe=popen( cmd_line, "r" ); if (pipe==NULL) { LOG(L_ERR, "ERROR: exec_str: cannot open pipe: %s\n", cmd_line); ser_error=E_EXEC; goto error01; } /* read now line by line */ uri_cnt=0; while( fgets(uri_line, MAX_URI_SIZE, pipe)!=NULL){ uri_len=strlen(uri_line); /* trim from right */ while(uri_len && (uri_line[uri_len-1]=='\r' || uri_line[uri_len-1]=='\n' || uri_line[uri_len-1]=='\t' || uri_line[uri_len-1]==' ' )) { DBG("exec_str: rtrim\n"); uri_len--; } /* skip empty line */ if (uri_len==0) continue; /* ZT */ uri_line[uri_len]=0; if (uri_cnt==0) { memset(&act, 0, sizeof(act)); act.type = SET_URI_T; act.val[0].type = STRING_ST; act.val[0].u.string = uri_line; if (do_action(&act, msg)<0) { LOG(L_ERR,"ERROR:exec_str : SET_URI_T action failed\n"); ser_error=E_OUT_OF_MEM; goto error02; } } else { if (append_branch(msg, uri_line, uri_len, 0, 0, Q_UNSPECIFIED, 0)==-1) { LOG(L_ERR, "ERROR: exec_str: append_branch failed;" " too many or too long URIs?\n"); goto error02; } } uri_cnt++; } if (uri_cnt==0) { LOG(L_ERR, "ERROR:exec_str: no uri from %s\n", cmd_line ); goto error02; } /* success */ ret=1; error02: if (ferror(pipe)) { LOG(L_ERR, "ERROR: exec_str: error in pipe: %s\n", strerror(errno)); ser_error=E_EXEC; ret=-1; } exit_status=pclose(pipe); if (WIFEXITED(exit_status)) { /* exited properly .... */ /* return false if script exited with non-zero status */ if (WEXITSTATUS(exit_status)!=0) ret=-1; } else { /* exited erroneously */ LOG(L_ERR, "ERROR: exec_str: cmd %.*s failed. " "exit_status=%d, errno=%d: %s\n", cmd->len, ZSW(cmd->s), exit_status, errno, strerror(errno) ); ret=-1; } error01: pkg_free(cmd_line); error00: return ret; }
static int recv_fd(int c) { int fd; uint8_t msgbuf[CMSG_SPACE(sizeof(fd))]; struct msghdr msg = { .msg_control = msgbuf, .msg_controllen = sizeof(msgbuf), }; struct cmsghdr *cmsg; struct iovec iov; uint8_t req[1]; ssize_t len; cmsg = CMSG_FIRSTHDR(&msg); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; cmsg->cmsg_len = CMSG_LEN(sizeof(fd)); msg.msg_controllen = cmsg->cmsg_len; iov.iov_base = req; iov.iov_len = sizeof(req); msg.msg_iov = &iov; msg.msg_iovlen = 1; len = recvmsg(c, &msg, 0); if (len > 0) { memcpy(&fd, CMSG_DATA(cmsg), sizeof(fd)); return fd; } return len; } static int net_bridge_run_helper(const char *helper, const char *bridge) { sigset_t oldmask, mask; int pid, status; char *args[5]; char **parg; int sv[2]; sigemptyset(&mask); sigaddset(&mask, SIGCHLD); sigprocmask(SIG_BLOCK, &mask, &oldmask); if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) == -1) { return -1; } /* try to launch bridge helper */ pid = fork(); if (pid == 0) { int open_max = sysconf(_SC_OPEN_MAX), i; char fd_buf[6+10]; char br_buf[6+IFNAMSIZ] = {0}; char helper_cmd[PATH_MAX + sizeof(fd_buf) + sizeof(br_buf) + 15]; for (i = 0; i < open_max; i++) { if (i != STDIN_FILENO && i != STDOUT_FILENO && i != STDERR_FILENO && i != sv[1]) { close(i); } } snprintf(fd_buf, sizeof(fd_buf), "%s%d", "--fd=", sv[1]); if (strrchr(helper, ' ') || strrchr(helper, '\t')) { /* assume helper is a command */ if (strstr(helper, "--br=") == NULL) { snprintf(br_buf, sizeof(br_buf), "%s%s", "--br=", bridge); } snprintf(helper_cmd, sizeof(helper_cmd), "%s %s %s %s", helper, "--use-vnet", fd_buf, br_buf); parg = args; *parg++ = (char *)"sh"; *parg++ = (char *)"-c"; *parg++ = helper_cmd; *parg++ = NULL; execv("/bin/sh", args); } else { /* assume helper is just the executable path name */ snprintf(br_buf, sizeof(br_buf), "%s%s", "--br=", bridge); parg = args; *parg++ = (char *)helper; *parg++ = (char *)"--use-vnet"; *parg++ = fd_buf; *parg++ = br_buf; *parg++ = NULL; execv(helper, args); } _exit(1); } else if (pid > 0) { int fd; close(sv[1]); do { fd = recv_fd(sv[0]); } while (fd == -1 && errno == EINTR); close(sv[0]); while (waitpid(pid, &status, 0) != pid) { /* loop */ } sigprocmask(SIG_SETMASK, &oldmask, NULL); if (fd < 0) { fprintf(stderr, "failed to recv file descriptor\n"); return -1; } if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { return fd; } } fprintf(stderr, "failed to launch bridge helper\n"); return -1; }
/* Thread function */ void * threaded(void * arg) { int ret, status; pid_t child, ctl; /* Wait main thread has registered the handler */ ret = pthread_mutex_lock(&mtx); if (ret != 0) { UNRESOLVED(ret, "Failed to lock mutex"); } ret = pthread_mutex_unlock(&mtx); if (ret != 0) { UNRESOLVED(ret, "Failed to unlock mutex"); } /* fork */ child = fork(); if (child == -1) { UNRESOLVED(errno, "Failed to fork"); } /* child */ if (child == 0) { if (nerrors) { FAILED("Errors occured in the child"); } /* We're done */ exit(PTS_PASS); } /* Parent joins the child */ ctl = waitpid(child, &status, 0); if (ctl != child) { UNRESOLVED(errno, "Waitpid returned the wrong PID"); } if (!WIFEXITED(status) || (WEXITSTATUS(status) != PTS_PASS)) { FAILED("Child exited abnormally"); } if (nerrors) { FAILED("Errors occured in the parent (only)"); } /* quit */ return NULL; }
int main(int argc, char *argv[]) { pid_t pid; int ch, status; struct timeval before, after; struct rusage ru; int exitonsig = 0; while ((ch = getopt(argc, argv, "lp")) != -1) { switch(ch) { case 'l': lflag = 1; break; case 'p': portableflag = 1; break; default: usage(); /* NOTREACHED */ } } argc -= optind; argv += optind; if (argc < 1) usage(); gettimeofday(&before, (struct timezone *)NULL); switch(pid = vfork()) { case -1: /* error */ perror("time"); exit(1); /* NOTREACHED */ case 0: /* child */ execvp(*argv, argv); perror(*argv); _exit((errno == ENOENT) ? 127 : 126); /* NOTREACHED */ } /* parent */ (void)signal(SIGINT, SIG_IGN); (void)signal(SIGQUIT, SIG_IGN); while (wait3(&status, 0, &ru) != pid) ; gettimeofday(&after, (struct timezone *)NULL); if (WIFSIGNALED(status)) exitonsig = WTERMSIG(status); if (!WIFEXITED(status)) fprintf(stderr, "Command terminated abnormally.\n"); timersub(&after, &before, &after); if (portableflag) { fprintf(stderr, "real %9ld.%02ld\n", after.tv_sec, after.tv_usec/10000); fprintf(stderr, "user %9ld.%02ld\n", ru.ru_utime.tv_sec, ru.ru_utime.tv_usec/10000); fprintf(stderr, "sys %9ld.%02ld\n", ru.ru_stime.tv_sec, ru.ru_stime.tv_usec/10000); } else { fprintf(stderr, "%9ld.%02ld real ", after.tv_sec, after.tv_usec/10000); fprintf(stderr, "%9ld.%02ld user ", ru.ru_utime.tv_sec, ru.ru_utime.tv_usec/10000); fprintf(stderr, "%9ld.%02ld sys\n", ru.ru_stime.tv_sec, ru.ru_stime.tv_usec/10000); } if (lflag) { int hz; long ticks; int mib[2]; struct clockinfo clkinfo; size_t size; mib[0] = CTL_KERN; mib[1] = KERN_CLOCKRATE; size = sizeof(clkinfo); if (sysctl(mib, 2, &clkinfo, &size, NULL, 0) < 0) err(1, "sysctl"); hz = clkinfo.hz; ticks = hz * (ru.ru_utime.tv_sec + ru.ru_stime.tv_sec) + hz * (ru.ru_utime.tv_usec + ru.ru_stime.tv_usec) / 1000000; fprintf(stderr, "%10ld %s\n", ru.ru_maxrss, "maximum resident set size"); fprintf(stderr, "%10ld %s\n", ticks ? ru.ru_ixrss / ticks : 0, "average shared memory size"); fprintf(stderr, "%10ld %s\n", ticks ? ru.ru_idrss / ticks : 0, "average unshared data size"); fprintf(stderr, "%10ld %s\n", ticks ? ru.ru_isrss / ticks : 0, "average unshared stack size"); fprintf(stderr, "%10ld %s\n", ru.ru_minflt, "minor page faults"); fprintf(stderr, "%10ld %s\n", ru.ru_majflt, "major page faults"); fprintf(stderr, "%10ld %s\n", ru.ru_nswap, "swaps"); fprintf(stderr, "%10ld %s\n", ru.ru_inblock, "block input operations"); fprintf(stderr, "%10ld %s\n", ru.ru_oublock, "block output operations"); fprintf(stderr, "%10ld %s\n", ru.ru_msgsnd, "messages sent"); fprintf(stderr, "%10ld %s\n", ru.ru_msgrcv, "messages received"); fprintf(stderr, "%10ld %s\n", ru.ru_nsignals, "signals received"); fprintf(stderr, "%10ld %s\n", ru.ru_nvcsw, "voluntary context switches"); fprintf(stderr, "%10ld %s\n", ru.ru_nivcsw, "involuntary context switches"); } if (exitonsig) { if (signal(exitonsig, SIG_DFL) == SIG_ERR) perror("signal"); else kill(getpid(), exitonsig); } exit(WIFEXITED(status) ? WEXITSTATUS(status) : EXIT_FAILURE); }