static void action_launch_child(svc_action_t *op) { int lpc; /* SIGPIPE is ignored (which is different from signal blocking) by the gnutls library. * Depending on the libqb version in use, libqb may set SIGPIPE to be ignored as well. * We do not want this to be inherited by the child process. By resetting this the signal * to the default behavior, we avoid some potential odd problems that occur during OCF * scripts when SIGPIPE is ignored by the environment. */ signal(SIGPIPE, SIG_DFL); #if defined(HAVE_SCHED_SETSCHEDULER) if (sched_getscheduler(0) != SCHED_OTHER) { struct sched_param sp; memset(&sp, 0, sizeof(sp)); sp.sched_priority = 0; if (sched_setscheduler(0, SCHED_OTHER, &sp) == -1) { crm_perror(LOG_ERR, "Could not reset scheduling policy to SCHED_OTHER for %s", op->id); } } #endif if (setpriority(PRIO_PROCESS, 0, 0) == -1) { crm_perror(LOG_ERR, "Could not reset process priority to 0 for %s", op->id); } /* Man: The call setpgrp() is equivalent to setpgid(0,0) * _and_ compiles on BSD variants too * need to investigate if it works the same too. */ setpgid(0, 0); /* close all descriptors except stdin/out/err and channels to logd */ for (lpc = getdtablesize() - 1; lpc > STDERR_FILENO; lpc--) { close(lpc); } #if SUPPORT_CIBSECRETS if (replace_secret_params(op->rsc, op->params) < 0) { /* replacing secrets failed! */ if (safe_str_eq(op->action,"stop")) { /* don't fail on stop! */ crm_info("proceeding with the stop operation for %s", op->rsc); } else { crm_err("failed to get secrets for %s, " "considering resource not configured", op->rsc); _exit(PCMK_OCF_NOT_CONFIGURED); } } #endif /* Setup environment correctly */ add_OCF_env_vars(op); /* execute the RA */ execvp(op->opaque->exec, op->opaque->args); /* Most cases should have been already handled by stat() */ services_handle_exec_error(op, errno); _exit(op->rc); }
/* * eval - Evaluate the command line that the user has just typed in * * If the user has requested a built-in command (quit, jobs, bg or fg) * then execute it immediately. Otherwise, fork a child process and * run the job in the context of the child. If the job is running in * the foreground, wait for it to terminate and then return. Note: * each child process must have a unique process group ID so that our * background children don't receive SIGINT (SIGTSTP) from the kernel * when we type ctrl-c (ctrl-z) at the keyboard. */ void eval(char *cmdline) { int bg; /* should the job run in bg or fg? */ struct cmdline_tokens tok; pid_t pid; /* process id of each process */ struct job_t *job; sigset_t set; sigset_t prev_set; int input_fd, output_fd; /* input and output redirect file descriptor */ /* Parse command line */ bg = parseline(cmdline, &tok); if (bg == -1) /* parsing error */ return; if (tok.argv[0] == NULL) /* ignore empty lines */ return; /* * Determine whether the command is builtin command * If so, handled by the helper function * If not, fork a child process and handle it */ if (!cmd_builtins(&tok)) { /* * Block signals before the parent add the child into job list to avoid race condition and ensure parent can reap child process */ if (sigemptyset(&set) < 0) { unix_error("sigemptyset failed.\n"); } if (sigaddset(&set, SIGINT) || sigaddset(&set, SIGTSTP) || sigaddset(&set, SIGCHLD)) { unix_error("sigaddset failed.\n"); } if (sigprocmask(SIG_BLOCK, &set, &prev_set) < 0) { unix_error("sigprocmask failed.\n"); } /* * fork a child process to run the job */ if ((pid = fork()) == 0) { /* asign unique group process to each child process * set the the group id as the process id */ if (setpgid(0, 0) < 0) { unix_error("set process group failed.\n"); return; } // unblock the signal set for receiving signals if (sigprocmask(SIG_UNBLOCK, &set, &prev_set) < 0) { unix_error("sigprocmask failed.\n"); } // redirect the input file descriptor if (tok.infile != NULL) { input_fd = open(tok.infile, O_RDONLY); if (dup2(input_fd, 0) < 0) { unix_error("Failed to restore stdin.\n"); } } // redirect the output file descriptor if (tok.outfile != NULL) { output_fd = open(tok.outfile, O_WRONLY); if (dup2(output_fd, 1) < 0) { unix_error("Failed to restore stdout.\n"); } } // execute a non-builtin process if( execve(tok.argv[0], tok.argv, environ) < 0 ) { printf("%s: Command not found!\n", tok.argv[0]); exit(0); } } // parent process add the child process in the job list addjob (job_list, pid, bg ? BG : FG, cmdline); /* * In the parent process, determine whehter the child process is a foreground process * If so, parent process should wait for it * If not, leave it as a background job */ if (!bg) { while (fgpid(job_list)) { sigsuspend(&prev_set); // wait until get the signal that the foreground child process finishes } } else { job = getjobpid(job_list, pid); printf("[%d] (%d) %s\n", job -> jid, job -> pid, cmdline); } sigprocmask(SIG_UNBLOCK, &set, &prev_set); // unblock the signal set to receive any signals } }
int setpgrp(void) { return setpgid(0,0); }
void do_pipe(char *cmds[MAXCMDS][MAXARGS], int nbcmd, int bg) { int fd[2][2], i; pid_t pid; if (verbose) printf("Entering pipe\n"); if (verbose) printf("Pipe creation\n"); if (pipe(fd[0]) == -1) { if (verbose) printf("Error in pipe creation\n"); } for (i = 0; i < nbcmd; i++) { if (i == 0) { switch(pid = fork()) { case -1 : if (verbose) unix_error("fork cmd 1 error"); case 0 : if (verbose) printf("First son process\n"); setpgid(0, 0); dup2(fd[0][1],STDOUT_FILENO); close(fd[0][0]); close(fd[0][1]); execvp(cmds[0][0],cmds[0]); printf("execvp error\n"); exit(EXIT_FAILURE); default : if (verbose) printf("Father process\n"); } } else if (i > 0 && i < nbcmd -1) { switch(pid = fork()) { case -1 : unix_error("fork cmd 2 error"); case 0 : if (verbose) printf("the %dth process\n",i); assert(pipe(fd[i%2]) != -1); setpgid(0, pid); dup2(fd[(i+1)%2][0], STDIN_FILENO); dup2(fd[i%2][1], STDOUT_FILENO); close(fd[0][0]); close(fd[0][1]); close(fd[1][1]); close(fd[1][0]); execvp(cmds[i][0],cmds[i]); printf("execvp 2 error\n"); exit(EXIT_FAILURE); default : close(fd[(i+1)%2][0]); close(fd[(i+1)%2][1]); } } else { switch(pid = fork()) { case -1 : unix_error("fork cmd 2 error"); case 0 : if (verbose) { printf("Last process\n"); } dup2(fd[(i+1)%2][0], STDIN_FILENO); close(fd[(i+1)%2][0]); close(fd[(i+1)%2][1]); execvp(cmds[i][0],cmds[i]); printf("execvp 2 error\n"); exit(EXIT_FAILURE); default: close(fd[(i+1)%2][0]); close(fd[(i+1)%2][1]); } } } jobs_addjob(pid, (bg == 1 ? BG : FG), cmds[0][0]); if (!bg) { if (verbose) printf("pipe waiting fg \n"); waitfg(pid); } return; }
void ipmi_start_daemon(struct ipmi_intf *intf) { pid_t pid; int fd; #ifdef SIGHUP sigset_t sighup; #endif #ifdef SIGHUP sigemptyset(&sighup); sigaddset(&sighup, SIGHUP); if (sigprocmask(SIG_UNBLOCK, &sighup, NULL) < 0) fprintf(stderr, "ERROR: could not unblock SIGHUP signal\n"); signal(SIGHUP, SIG_IGN); #endif #ifdef SIGTTOU signal(SIGTTOU, SIG_IGN); #endif #ifdef SIGTTIN signal(SIGTTIN, SIG_IGN); #endif #ifdef SIGQUIT signal(SIGQUIT, SIG_IGN); #endif #ifdef SIGTSTP signal(SIGTSTP, SIG_IGN); #endif pid = (pid_t) fork(); if (pid < 0 || pid > 0) exit(0); #if defined(SIGTSTP) && defined(TIOCNOTTY) if (setpgid(0, getpid()) == -1) exit(1); if ((fd = open(_PATH_TTY, O_RDWR)) >= 0) { ioctl(fd, TIOCNOTTY, NULL); close(fd); } #else if (setpgid(0, 0) == -1) exit(1); pid = (pid_t) fork(); if (pid < 0 || pid > 0) exit(0); #endif chdir("/"); umask(0); for (fd=0; fd<64; fd++) { if (fd != intf->fd) close(fd); } fd = open("/dev/null", O_RDWR); assert(0 == fd); dup(fd); dup(fd); }
gint main (gint argc, gchar **argv) { setlocale (LC_ALL, ""); GOptionContext *context = g_option_context_new ("- ibus daemon"); g_option_context_add_main_entries (context, entries, "ibus-daemon"); g_argv = g_strdupv (argv); GError *error = NULL; if (!g_option_context_parse (context, &argc, &argv, &error)) { g_printerr ("Option parsing failed: %s\n", error->message); g_error_free (error); exit (-1); } if (g_gdbus_timeout < -1) { g_printerr ("Bad timeout (must be >= -1): %d\n", g_gdbus_timeout); exit (-1); } if (g_mempro) { g_mem_set_vtable (glib_mem_profiler_table); signal (SIGUSR2, _sig_usr2_handler); } /* check uid */ { const gchar *username = ibus_get_user_name (); uid_t uid = getuid (); struct passwd *pwd = getpwuid (uid); if (pwd == NULL || g_strcmp0 (pwd->pw_name, username) != 0) { g_printerr ("Please run ibus-daemon with login user! Do not run ibus-daemon with sudo or su.\n"); exit (-1); } } /* daemonize process */ if (daemonize) { if (daemon (1, 0) != 0) { g_printerr ("Can not daemonize ibus.\n"); exit (-1); } } /* create a new process group. this is important to kill all of its children by SIGTERM at a time in bus_ibus_impl_destroy. */ setpgid (0, 0); ibus_init (); ibus_set_log_handler (g_verbose); /* check if ibus-daemon is running in this session */ if (ibus_get_address () != NULL) { IBusBus *bus = ibus_bus_new (); if (ibus_bus_is_connected (bus)) { if (!replace) { g_printerr ("current session already has an ibus-daemon.\n"); exit (-1); } ibus_bus_exit (bus, FALSE); while (ibus_bus_is_connected (bus)) { g_main_context_iteration (NULL, TRUE); } } g_object_unref (bus); } bus_server_init (); if (!single) { /* execute config component */ if (g_strcmp0 (config, "default") == 0) { BusComponent *component; component = bus_ibus_impl_lookup_component_by_name ( BUS_DEFAULT_IBUS, IBUS_SERVICE_CONFIG); if (component) { bus_component_set_restart (component, restart); } if (component == NULL || !bus_component_start (component, g_verbose)) { g_printerr ("Can not execute default config program\n"); exit (-1); } } else if (g_strcmp0 (config, "disable") != 0 && g_strcmp0 (config, "") != 0) { if (!execute_cmdline (config)) exit (-1); } /* execute panel component */ if (g_strcmp0 (panel, "default") == 0) { BusComponent *component; component = bus_ibus_impl_lookup_component_by_name ( BUS_DEFAULT_IBUS, IBUS_SERVICE_PANEL); if (component) { bus_component_set_restart (component, restart); } if (component == NULL || !bus_component_start (component, g_verbose)) { g_printerr ("Can not execute default panel program\n"); exit (-1); } } else if (g_strcmp0 (panel, "disable") != 0 && g_strcmp0 (panel, "") != 0) { if (!execute_cmdline (panel)) exit (-1); } } /* execute ibus xim server */ if (xim) { if (!execute_cmdline (LIBEXECDIR "/ibus-x11 --kill-daemon")) exit (-1); } bus_server_run (); return 0; }
int main(int argc, char *argv[]) { char buf[8192], ptyname[16], *username, *logfile; struct utmp utmp; struct sigaction act; sigset_t set; int mfd, sfd; ssize_t n; if (argc != 3) usage(); username = argv[1]; logfile = argv[2]; sigemptyset(&set); sigaddset(&set, SIGTERM); sigaddset(&set, SIGIO); if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) err(1, "sigprocmask block init"); if ((lg = fopen(logfile, "w")) == NULL) err(1, "fopen %s", logfile); if (setlinebuf(lg) != 0) err(1, "setlinebuf"); memset(&act, 0, sizeof(act)); act.sa_mask = set; act.sa_flags = SA_RESTART; act.sa_handler = terminate; if (sigaction(SIGTERM, &act, NULL) == -1) err(1, "sigaction SIGTERM"); if (sigaction(SIGINT, &act, NULL) == -1) err(1, "sigaction SIGINT"); if (openpty(&mfd, &sfd, ptyname, NULL, NULL) == -1) err(1, "openpty"); fprintf(lg, "openpty %s\n", ptyname); if ((tty = strrchr(ptyname, '/')) == NULL) errx(1, "tty: %s", ptyname); tty++; /* login(3) searches for a controlling tty, use the created one */ if (dup2(sfd, 1) == -1) err(1, "dup2 stdout"); memset(&utmp, 0, sizeof(utmp)); strlcpy(utmp.ut_line, tty, sizeof(utmp.ut_line)); strlcpy(utmp.ut_name, username, sizeof(utmp.ut_name)); time(&utmp.ut_time); login(&utmp); fprintf(lg, "login %s %s\n", username, tty); act.sa_handler = iostdin; if (sigaction(SIGIO, &act, NULL) == -1) err(1, "sigaction SIGIO"); if (setpgid(0, 0) == -1) err(1, "setpgid"); if (fcntl(0, F_SETOWN, getpid()) == -1) err(1, "fcntl F_SETOWN"); if (fcntl(0, F_SETFL, O_ASYNC) == -1) err(1, "fcntl O_ASYNC"); act.sa_handler = timeout; if (sigaction(SIGALRM, &act, NULL) == -1) err(1, "sigaction SIGALRM"); if (alarm(30) == (unsigned int)-1) err(1, "alarm"); fprintf(lg, "%s: started\n", getprogname()); if (sigprocmask(SIG_UNBLOCK, &set, NULL) == -1) err(1, "sigprocmask unblock init"); /* do not block signals during read, it has to be interrupted */ while ((n = read(mfd, buf, sizeof(buf))) > 0) { if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) err(1, "sigprocmask block write"); fprintf(lg, ">>> "); if (fwrite(buf, 1, n, lg) != (size_t)n) err(1, "fwrite %s", logfile); if (buf[n-1] != '\n') fprintf(lg, "\n"); if (sigprocmask(SIG_UNBLOCK, &set, NULL) == -1) err(1, "sigprocmask unblock write"); } if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) err(1, "sigprocmask block exit"); if (n < 0) err(1, "read %s", ptyname); fprintf(lg, "EOF %s\n", ptyname); if (logout(tty) == 0) errx(1, "logout %s", tty); fprintf(lg, "logout %s\n", tty); errx(3, "EOF"); }
int job_start(struct job *j) { struct proc *p; struct redir *redir_iter; int pipey[2] = { -1, -1 }; #define REDIR(a, b) \ do{ \ if(a != b){ \ /* close b and copy a into b */ \ if(dup2(a, b) == -1) \ perror("dup2()"); \ if(close(a) == -1) \ perror("close()"); \ } \ }while(0) for(redir_iter = j->redir; redir_iter; redir_iter = redir_iter->next){ int fd; if(redir_iter->fname){ fd = open(redir_iter->fname, O_WRONLY | O_CREAT | O_TRUNC); /* FIXME: only out for now - need "<" and ">>" */ if(fd == -1){ fprintf(stderr, "ush: open %s: %s\n", redir_iter->fname, strerror(errno)); /* FIXME: close all other fds */ return 1; } }else{ fd = redir_iter->fd_out; } fprintf(stderr, "job_start(): REDIR(%d [%s], %d)\n", fd, redir_iter->fname, redir_iter->fd_in); REDIR(fd, redir_iter->fd_in); } j->proc->in = STDIN_FILENO; for(p = j->proc; p; p = p->next){ p->err = STDERR_FILENO; if(p->next){ if(pipe(pipey) < 0){ perror("pipe()"); goto bail; } p->out = pipey[1]; p->next->in = pipey[0]; }else{ p->out = STDOUT_FILENO; } /* TODO: cd, fg, rehash */ switch(p->pid = fork()){ case 0: p->pid = getpid(); REDIR(p->in, STDIN_FILENO); REDIR(p->out, STDOUT_FILENO); REDIR(p->err, STDERR_FILENO); #undef REDIR job_close_fds(j, p->next); proc_exec(p, j->gid); break; /* unreachable */ case -1: perror("fork()"); goto bail; default: if(interactive){ if(!j->gid) j->gid = p->pid; setpgid(p->pid, j->gid); } p->state = PROC_RUN; } } /* close our access to all these pipes */ job_close_fds(j, NULL); j->state = JOB_RUNNING; return 0; bail: fprintf(stderr, "warning: error starting job: %s\n", strerror(errno)); for(; p; p = p->next) p->state = PROC_FIN; job_close_fds(j, NULL); job_sig(j, SIGCONT); return 1; }
void Setpgid(pid_t pid, pid_t pgid) { int rc; if ((rc = setpgid(pid, pgid)) < 0) unix_error("Setpgid error"); return; }
static ATTRIBUTE_NO_SANITIZE_THREAD void backtrace_sigaction(int signum, siginfo_t *info, void* ptr) { void *array[42]; size_t size; void * caller_address; ucontext_t *uc = (ucontext_t *) ptr; int gdb_pid = -1; /* get all entries on the stack */ size = backtrace(array, 42); /* Get the address at the time the signal was raised */ #if defined(REG_RIP) caller_address = (void *) uc->uc_mcontext.gregs[REG_RIP]; #elif defined(REG_EIP) caller_address = (void *) uc->uc_mcontext.gregs[REG_EIP]; #elif defined(__arm__) caller_address = (void *) uc->uc_mcontext.arm_pc; #elif defined(__mips__) caller_address = (void *) uc->uc_mcontext.sc_pc; #elif defined(REG_PC) && defined(__e2k__) caller_address = (void *) ((mcontext_t*) &uc->uc_mcontext)->mc_gregs[REG_PC]; #else /* TODO support more arch(s) */ # warning Unsupported architecture. caller_address = info->si_addr; #endif int should_die = 0; switch(info->si_signo) { case SIGXCPU: case SIGXFSZ: should_die = 1; break; case SIGABRT: case SIGALRM: if (info->si_pid == getpid()) should_die = 1; case SIGBUS: case SIGFPE: case SIGILL: case SIGSEGV: #ifndef SI_FROMKERNEL # define SI_FROMKERNEL(info) (info->si_code > 0) #endif if (SI_FROMKERNEL(info)) should_die = 1; } char time_buf[64]; time_t t = ldap_time_unsteady(); strftime(time_buf, sizeof(time_buf), "%F-%H%M%S", localtime(&t)); char name_buf[PATH_MAX]; int fd = -1; #ifdef snprintf # undef snprintf #endif if (snprintf(name_buf, sizeof(name_buf), "%s/slapd-backtrace.%s-%i.log%c", backtrace_homedir ? backtrace_homedir : ".", time_buf, getpid(), 0) > 0) fd = open(name_buf, O_CREAT | O_EXCL | O_WRONLY | O_APPEND, 0644); if (fd < 0) { if (backtrace_homedir) fd = open(strrchr(name_buf, '/') + 1, O_CREAT | O_EXCL | O_WRONLY | O_APPEND, 0644); if (fd < 0) fd = STDERR_FILENO; dprintf(fd, "\n\n*** Unable create \"%s\": %s!", name_buf, STRERROR(errno)); } dprintf(fd, "\n\n*** Signal %d (%s), address is %p from %p\n", signum, strsignal(signum), info->si_addr, (void *)caller_address); int n = readlink("/proc/self/exe", name_buf, sizeof(name_buf) - 1); if (n > 0) { name_buf[n] = 0; dprintf(fd, " Executable file %s\n", name_buf); } else { dprintf(fd, " Unable read executable name: %s\n", STRERROR(errno)); strcpy(name_buf, "unknown"); } void** actual = array; int frame = 0; for (n = 0; n < size; ++n) if (array[n] == caller_address) { frame = n; actual = array + frame; size -= frame; break; } dprintf(fd, "\n*** Backtrace by glibc:\n"); backtrace_symbols_fd(actual, size, fd); int mem_map_fd = open("/proc/self/smaps", O_RDONLY, 0); if (mem_map_fd >= 0) { char buf[1024]; dprintf(fd, "\n*** Memory usage map (by /proc/self/smaps):\n"); while(1) { int n = read(mem_map_fd, &buf, sizeof(buf)); if (n < 1) break; if (write(fd, &buf, n) != n) break; } close(mem_map_fd); } /* avoid ECHILD from waitpid() */ signal(SIGCHLD, SIG_DFL); dprintf(fd, "\n*** Backtrace by addr2line:\n"); for(n = 0; n < size; ++n) { int status = EXIT_FAILURE, child_pid = fork(); if (! child_pid) { char addr_buf[64]; close(STDIN_FILENO); dup2(fd, STDOUT_FILENO); close(fd); dprintf(STDOUT_FILENO, "(%d) %p: ", n, actual[n]); sprintf(addr_buf, "%p", actual[n]); execlp("addr2line", "addr2line", addr_buf, "-C", "-f", "-i", #if __GLIBC_PREREQ(2,14) "-p", /* LY: not available on RHEL6, guest by glibc version */ #endif "-e", name_buf, NULL); exit(EXIT_FAILURE); } else if (child_pid < 0) { dprintf(fd, "\n*** Unable complete backtrace by addr2line, sorry (%s, %d).\n", "fork", errno); break; } else if (waitpid(child_pid, &status, 0) < 0 || status != W_EXITCODE(EXIT_SUCCESS, 0)) { dprintf(fd, "\n*** Unable complete backtrace by addr2line, sorry (%s, pid %d, errno %d, status 0x%x).\n", "waitpid", child_pid, errno, status); break; } } if (is_debugger_present()) { dprintf(fd, "*** debugger already present\n"); goto ballout; } int retry_by_return = 0; if (should_die && SI_FROMKERNEL(info)) { /* LY: Expect kernel kill us again, * therefore for switch to 'guilty' thread and we may just return, * instead of sending SIGTRAP and later switch stack frame by GDB. */ retry_by_return = 1; } if (is_valgrind_present()) { dprintf(fd, "*** valgrind present, skip backtrace by gdb\n"); goto ballout; } int pipe_fd[2]; if (pipe(pipe_fd)) { pipe_fd[0] = pipe_fd[1] = -1; goto ballout; } gdb_is_ready_for_backtrace = 0; pid_t tid = syscall(SYS_gettid); gdb_pid = fork(); if (!gdb_pid) { char pid_buf[16]; sprintf(pid_buf, "%d", getppid()); dup2(pipe_fd[0], STDIN_FILENO); close(pipe_fd[1]); pipe_fd[0] = pipe_fd[1] =-1; dup2(fd, STDOUT_FILENO); dup2(fd, STDERR_FILENO); for(fd = getdtablesize(); fd > STDERR_FILENO; --fd) close(fd); setsid(); setpgid(0, 0); dprintf(STDOUT_FILENO, "\n*** Backtrace by GDB " #if GDB_SWITCH2GUILTY_THREAD "(pid %s, LWP %i, frame #%d):\n", pid_buf, tid, frame); #else "(pid %s, LWP %i, please find frame manually):\n", pid_buf, tid); #endif execlp("gdb", "gdb", "-q", "-se", name_buf, "-n", NULL); kill(getppid(), SIGKILL); dprintf(STDOUT_FILENO, "\n*** Sorry, GDB launch failed: %s\n", STRERROR(errno)); fsync(STDOUT_FILENO); exit(EXIT_FAILURE); }
static char *feh_magick_load_image(char *filename) { char argv_fd[12]; char *basename; char *tmpname; char *sfn; int fd = -1, devnull = -1; int status; if (opt.magick_timeout < 0) return NULL; basename = strrchr(filename, '/'); if (basename == NULL) basename = filename; else basename++; tmpname = feh_unique_filename("/tmp/", basename); if (strlen(tmpname) > (NAME_MAX-6)) tmpname[NAME_MAX-7] = '\0'; sfn = estrjoin("_", tmpname, "XXXXXX", NULL); free(tmpname); fd = mkstemp(sfn); if (fd == -1) return NULL; snprintf(argv_fd, sizeof(argv_fd), "png:fd:%d", fd); if ((childpid = fork()) == 0) { /* discard convert output */ devnull = open("/dev/null", O_WRONLY); dup2(devnull, 0); dup2(devnull, 1); dup2(devnull, 2); /* * convert only accepts SIGINT via killpg, a normal kill doesn't work */ setpgid(0, 0); execlp("convert", "convert", filename, argv_fd, NULL); exit(1); } else { alarm(opt.magick_timeout); waitpid(childpid, &status, 0); alarm(0); if (!WIFEXITED(status) || (WEXITSTATUS(status) != 0)) { close(fd); unlink(sfn); free(sfn); sfn = NULL; if (!opt.quiet) { if (WIFSIGNALED(status)) weprintf("%s - Conversion took too long, skipping", filename); } /* * Reap child. The previous waitpid call was interrupted by * alarm, but convert doesn't terminate immediately. * XXX * normally, if (WIFSIGNALED(status)) waitpid(childpid, &status, 0); * would suffice. However, as soon as feh has its own window, * this doesn't work anymore and the following workaround is * required. Hm. */ waitpid(-1, &status, 0); } childpid = 0; } return sfn; }
/* Execute a script, wait for termination and return its stdout. * script_name IN - Name of program being run (e.g. "StartStageIn") * script_path IN - Fully qualified program of the program to execute * script_args IN - Arguments to the script * max_wait IN - Maximum time to wait in milliseconds, * -1 for no limit (asynchronous) * data_in IN - data to use as program STDIN (NULL if not STDIN) * status OUT - Job exit code * Return stdout+stderr of spawned program, value must be xfreed. */ extern char *power_run_script(char *script_name, char *script_path, char **script_argv, int max_wait, char *data_in, int *status) { int i, new_wait, resp_size = 0, resp_offset = 0; int send_size = 0, send_offset = 0; pid_t cpid; char *resp = NULL; int fd_stdout[2] = { -1, -1 }; int fd_stdin[2] = { -1, -1 }; if ((script_path == NULL) || (script_path[0] == '\0')) { error("%s: no script specified", __func__); *status = 127; resp = xstrdup("Slurm burst buffer configuration error"); return resp; } if (slurm_get_debug_flags() & DEBUG_FLAG_POWER) { for (i = 0; i < 10; i++) { if (!script_argv[i]) break; } if (i == 0) { info("%s:", __func__); } else if (i == 1) { info("%s: %s", __func__, script_name); } else if (i == 2) { info("%s: %s %s", __func__, script_name, script_argv[1]); } else if (i == 3) { info("%s: %s %s %s", __func__, script_name, script_argv[1], script_argv[2]); } else if (i == 4) { info("%s: %s %s %s %s", __func__, script_name, script_argv[1], script_argv[2], script_argv[3]); } else if (i == 5) { info("%s: %s %s %s %s %s", __func__, script_name, script_argv[1], script_argv[2], script_argv[3], script_argv[4]); } else if (i == 6) { info("%s: %s %s %s %s %s %s", __func__, script_name, script_argv[1], script_argv[2], script_argv[3], script_argv[4], script_argv[5]); } else if (i == 7) { info("%s: %s %s %s %s %s %s %s", __func__, script_name, script_argv[1], script_argv[2], script_argv[3], script_argv[4], script_argv[5], script_argv[6]); } else { /* 8 or more args here, truncate as needed */ info("%s: %s %s %s %s %s %s %s %s", __func__, script_name, script_argv[1], script_argv[2], script_argv[3], script_argv[4], script_argv[5], script_argv[6], script_argv[7]); } if (data_in) info("%s: %s", __func__, data_in); } if (script_path[0] != '/') { error("%s: %s is not fully qualified pathname (%s)", __func__, script_name, script_path); *status = 127; resp = xstrdup("Slurm burst buffer configuration error"); return resp; } if (access(script_path, R_OK | X_OK) < 0) { error("%s: %s can not be executed (%s) %m", __func__, script_name, script_path); *status = 127; resp = xstrdup("Slurm burst buffer configuration error"); return resp; } if (data_in) { if (pipe(fd_stdin) != 0) { error("%s: pipe(): %m", __func__); *status = 127; resp = xstrdup("System error"); return resp; } } if (max_wait != -1) { if (pipe(fd_stdout) != 0) { error("%s: pipe(): %m", __func__); *status = 127; resp = xstrdup("System error"); return resp; } } if ((cpid = fork()) == 0) { int cc; cc = sysconf(_SC_OPEN_MAX); if (data_in) dup2(fd_stdin[0], STDIN_FILENO); if (max_wait != -1) { dup2(fd_stdout[1], STDERR_FILENO); dup2(fd_stdout[1], STDOUT_FILENO); for (i = 0; i < cc; i++) { if ((i != STDERR_FILENO) && (i != STDIN_FILENO) && (i != STDOUT_FILENO)) close(i); } } else { for (i = 0; i < cc; i++) { if (!data_in || (i != STDERR_FILENO)) close(i); } if ((cpid = fork()) < 0) exit(127); else if (cpid > 0) exit(0); } setpgid(0, 0); execv(script_path, script_argv); error("%s: execv(%s): %m", __func__, script_path); exit(127); } else if (cpid < 0) { if (data_in) { close(fd_stdin[0]); close(fd_stdin[1]); } if (max_wait != -1) { close(fd_stdout[0]); close(fd_stdout[1]); } error("%s: fork(): %m", __func__); } else if (max_wait != -1) { struct pollfd fds; time_t start_time = time(NULL); if (data_in) { close(fd_stdin[0]); send_size = strlen(data_in); while (send_size > send_offset) { i = write(fd_stdin[1], data_in + send_offset, send_size - send_offset); if (i == 0) { break; } else if (i < 0) { if (errno == EAGAIN) continue; error("%s: write(%s): %m", __func__, script_path); break; } else { send_offset += i; } } close(fd_stdin[1]); } resp_size = 1024; resp = xmalloc(resp_size); close(fd_stdout[1]); while (1) { fds.fd = fd_stdout[0]; fds.events = POLLIN | POLLHUP | POLLRDHUP; fds.revents = 0; if (max_wait <= 0) { new_wait = -1; } else { new_wait = (time(NULL) - start_time) * 1000 + max_wait; if (new_wait <= 0) break; } i = poll(&fds, 1, new_wait); if (i == 0) { error("%s: %s poll timeout", __func__, script_name); break; } else if (i < 0) { error("%s: %s poll:%m", __func__, script_name); break; } if ((fds.revents & POLLIN) == 0) break; i = read(fd_stdout[0], resp + resp_offset, resp_size - resp_offset); if (i == 0) { break; } else if (i < 0) { if (errno == EAGAIN) continue; error("%s: read(%s): %m", __func__, script_path); break; } else { resp_offset += i; if (resp_offset + 1024 >= resp_size) { resp_size *= 2; resp = xrealloc(resp, resp_size); } } } killpg(cpid, SIGKILL); waitpid(cpid, status, 0); close(fd_stdout[0]); } else { waitpid(cpid, status, 0); } return resp; }
void forkchild(struct job *jp, union node *n, int mode, int vforked) { int wasroot; #if JOBS /* LSC: for proper compilation with JOBS == 0 */ int pgrp; #endif const char *devnull = _PATH_DEVNULL; const char *nullerr = "Can't open %s"; wasroot = rootshell; TRACE(("Child shell %d\n", getpid())); if (!vforked) rootshell = 0; closescript(vforked); clear_traps(vforked); #if JOBS if (!vforked) jobctl = 0; /* do job control only in root shell */ if (wasroot && mode != FORK_NOJOB && mflag) { if (jp == NULL || jp->nprocs == 0) pgrp = getpid(); else pgrp = jp->ps[0].pid; /* This can fail because we are doing it in the parent also */ (void)setpgid(0, pgrp); if (mode == FORK_FG) { if (tcsetpgrp(ttyfd, pgrp) == -1) error("Cannot set tty process group (%s) at %d", strerror(errno), __LINE__); } setsignal(SIGTSTP, vforked); setsignal(SIGTTOU, vforked); } else if (mode == FORK_BG) { ignoresig(SIGINT, vforked); ignoresig(SIGQUIT, vforked); if ((jp == NULL || jp->nprocs == 0) && ! fd0_redirected_p ()) { close(0); if (open(devnull, O_RDONLY) != 0) error(nullerr, devnull); } } #else if (mode == FORK_BG) { ignoresig(SIGINT, vforked); ignoresig(SIGQUIT, vforked); if ((jp == NULL || jp->nprocs == 0) && ! fd0_redirected_p ()) { close(0); if (open(devnull, O_RDONLY) != 0) error(nullerr, devnull); } } #endif if (wasroot && iflag) { setsignal(SIGINT, vforked); setsignal(SIGQUIT, vforked); setsignal(SIGTERM, vforked); } if (!vforked) jobs_invalid = 1; }
/* * Turn job control on and off. * * Note: This code assumes that the third arg to ioctl is a character * pointer, which is true on Berkeley systems but not System V. Since * System V doesn't have job control yet, this isn't a problem now. */ MKINIT int jobctl; #if JOBS /* Minix setjobctl is defined to empty, compilation error */ void setjobctl(int on) { #ifdef OLD_TTY_DRIVER int ldisc; #endif if (on == jobctl || rootshell == 0) return; if (on) { #if defined(FIOCLEX) || defined(FD_CLOEXEC) int err; int i; if (ttyfd != -1) close(ttyfd); if ((ttyfd = open("/dev/tty", O_RDWR)) == -1) { for (i = 0; i < 3; i++) { if (isatty(i) && (ttyfd = dup(i)) != -1) break; } if (i == 3) goto out; } /* Move to a high fd */ for (i = 10; i > 2; i--) { if ((err = fcntl(ttyfd, F_DUPFD, (1 << i) - 1)) != -1) break; } if (err != -1) { close(ttyfd); ttyfd = err; } #ifdef FIOCLEX err = ioctl(ttyfd, FIOCLEX, 0); #elif FD_CLOEXEC err = fcntl(ttyfd, F_SETFD, fcntl(ttyfd, F_GETFD, 0) | FD_CLOEXEC); #endif if (err == -1) { close(ttyfd); ttyfd = -1; goto out; } #else out2str("sh: Need FIOCLEX or FD_CLOEXEC to support job control"); goto out; #endif do { /* while we are in the background */ if ((initialpgrp = tcgetpgrp(ttyfd)) < 0) { out: out2str("sh: can't access tty; job control turned off\n"); mflag = 0; return; } if (initialpgrp == -1) initialpgrp = getpgrp(); else if (initialpgrp != getpgrp()) { killpg(0, SIGTTIN); continue; } } while (0); #ifdef OLD_TTY_DRIVER if (ioctl(ttyfd, TIOCGETD, (char *)&ldisc) < 0 || ldisc != NTTYDISC) { out2str("sh: need new tty driver to run job control; job control turned off\n"); mflag = 0; return; } #endif setsignal(SIGTSTP, 0); setsignal(SIGTTOU, 0); setsignal(SIGTTIN, 0); if (getpgrp() != rootpid && setpgid(0, rootpid) == -1) error("Cannot set process group (%s) at %d", strerror(errno), __LINE__); if (tcsetpgrp(ttyfd, rootpid) == -1) error("Cannot set tty process group (%s) at %d", strerror(errno), __LINE__); } else { /* turning job control off */ if (getpgrp() != initialpgrp && setpgid(0, initialpgrp) == -1) error("Cannot set process group (%s) at %d", strerror(errno), __LINE__); if (tcsetpgrp(ttyfd, initialpgrp) == -1) error("Cannot set tty process group (%s) at %d", strerror(errno), __LINE__); close(ttyfd); ttyfd = -1; setsignal(SIGTSTP, 0); setsignal(SIGTTOU, 0); setsignal(SIGTTIN, 0); } jobctl = on; }
static int miscd_dodaemon(char *argv1, char *daemon) { struct sigaction act; char *commandline; char commbuf[10]; char ch; if (!check_file_writable(PASSFILE)) { fprintf(stderr, "Error! File %s is not writable.\n", PASSFILE); exit(-1); } if (!check_file_writable(BOARDS)) { fprintf(stderr, "Error! File %s is not writable.\n", BOARDS); exit(-1); } truncate(BOARDS, MAXBOARD * sizeof(struct boardheader)); if (load_ucache() != 0) { printf("ft,load ucache error!"); exit(-1); } /* init tmpfs */ sprintf(genbuf1,"%s/home",TMPFSROOT); mkdir(genbuf1,0700); sprintf(genbuf1,"%s/boards",TMPFSROOT); mkdir(genbuf1,0700); for (ch='A';ch<='Z';ch++) { sprintf(genbuf1,"%s/home/%c",TMPFSROOT,ch); mkdir(genbuf1,0700); } resolve_boards(); resolve_utmp(); resolve_guest_table(); if (argv1 != NULL) { switch (fork()) { case -1: printf("faint, i can't fork.\n"); exit(0); break; case 0: break; default: exit(0); break; } commandline = argv1; } else { commandline = commbuf; } setsid(); #ifdef AIX setpgrp(); #elif defined FREEBSD setpgid(0, 0); #else // by zixia setpgrp(0, 0); setpgrp(); #endif #ifdef AIX act.sa_handler = NULL; act.sa_flags = SA_RESTART | SA_NOCLDWAIT; sigaction(SIGCHLD, &act, NULL); #else act.sa_handler = reaper; act.sa_flags = SA_RESTART; sigaction(SIGCHLD, &act, NULL); #endif if (((daemon == NULL) || (!strcmp(daemon, "timed"))) && ((argv1 == NULL) || fork())) { strcpy(commandline, "timed"); timed(); exit(0); } if (((daemon == NULL) || (!strcmp(daemon, "killd"))) && ((argv1 == NULL) || fork())) { strcpy(commandline, "killd"); while (1) { time_t ft; ft = getnextday4am(); do { sleep(ft - time(0)); } while (ft > time(0)); if (argv1 == NULL) { dokilluser(); //doupdategiveupuser(); } else { switch (fork()) { case -1: bbslog("3error", "fork failed\n"); break; case 0: dokilluser(); //doupdategiveupuser(); exit(0); break; default: break; } } switch (fork()) { case -1: bbslog("3error", "fork failed\n"); break; case 0: dokillalldir(); exit(0); break; default: break; } }; exit(0); } if (((daemon == NULL) || (!strcmp(daemon, "userd"))) && ((argv1 == NULL) || fork())) { strcpy(commandline, "userd"); userd(); exit(0); } if ((daemon == NULL) || (!strcmp(daemon, "flushd"))) { strcpy(commandline, "flushd"); flushd(); exit(0); } return 0; }