void reattach_tty(char *tty, char *password) { int s = -1; char *name; struct sockaddr_in addr; struct hostent *hp; int len = 0; fd_set rd_fd; struct timeval tm = {0}; char chr_c[] = "\003"; /* * this buffer has to be big enough to handle a full screen of * information from the detached process. */ unsigned char buffer[6 * BIG_BUFFER_SIZE+1]; char *p; int port = 0; #if defined (TIOCGWINSZ) struct winsize window; #endif memset(&parm, 0, sizeof(struct param)); if (!(name = find_detach_socket(socket_path, tty))) { fprintf(stderr, "No detached process to attach too\r\n"); _exit(1); } strcpy(parm.cookie, get_cookie(name)); if (!*parm.cookie) _exit(1); if ((p = strrchr(name, '/'))) p++; sscanf(p, "%d.%*s.%*s", &port); displays = 1; if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { displays = 0; _exit(1); } chmod(name, SOCKMODE); set_socket_options(s); memset(&addr, 0, sizeof(struct sockaddr_in)); addr.sin_port = htons(port); addr.sin_family = AF_INET; if((hp = gethostbyname("localhost"))) memcpy(&addr.sin_addr, hp->h_addr, hp->h_length); else inet_aton("127.0.0.1", (struct in_addr *)&addr.sin_addr); if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) { fprintf(stderr, "connection refused for %s\r\n", name); _exit(1); } parm.pid = getpid(); parm.pgrp = getpgrp(); parm.uid = getuid(); strcpy(parm.tty, ttyname(0)); strncpy(parm.termid, getenv("TERM"), 80); if (password) strncpy(parm.password, password, 60); fprintf(stderr, "attempting to wakeup %s\r\n", find_tty_name(name)); #if defined (TIOCGWINSZ) if (ioctl(0, TIOCGWINSZ, &window) > -1) { parm.cols = window.ws_col; parm.rows = window.ws_row; } else #endif { parm.cols = 79; parm.rows = 25; } write(s, &parm, sizeof(struct param)); sleep(2); alarm(15); len = read(s, &parm, sizeof(struct param)); alarm(0); if (len <= 0) { fprintf(stderr, "[1;37merror[0;37m reconnecting to %s\r\n", find_tty_name(name)); displays = 0; chmod(name, SOCKMODE); exit(1); } unlink(name); term_init(parm.termid); set_term_eight_bit(1); charset_ibmpc(); term_clear_screen(); term_resize(); term_move_cursor(0,0); my_signal(SIGPIPE, handle_pipe, 0); my_signal(SIGINT, handle_ctrlc, 0); my_signal(SIGHUP, handle_hup, 0); /* * according to MHacker we need to set errno to 0 under BSD. * for some reason we get a address in use from a socket * */ errno = 0; while (1) { FD_ZERO(&rd_fd); FD_SET(0, &rd_fd); FD_SET(s, &rd_fd); tm.tv_sec = 2; switch(select(s+1, &rd_fd, NULL, NULL, &tm)) { case -1: if (ctrl_c) { write(s, chr_c, 1); ctrl_c = 0; } else if (errno != EINTR) { close(s); _exit(1); } break; case 0: break; default: { if (FD_ISSET(0, &rd_fd)) { len = read(0, buffer, sizeof(buffer)-1); write(s, buffer, len); } if (FD_ISSET(s, &rd_fd)) { len = read(s, buffer, sizeof(buffer)-1); write(1, buffer, len); } } } } close(s); fprintf(stderr, "Never should have got here"); _exit(1); return; /* error return */ }
static void tstp(int dummy GCC_UNUSED) { SCREEN *sp = CURRENT_SCREEN; sigset_t mask, omask; sigaction_t act, oact; #ifdef SIGTTOU int sigttou_blocked; #endif T(("tstp() called")); /* * The user may have changed the prog_mode tty bits, so save them. * * But first try to detect whether we still are in the foreground * process group - if not, an interactive shell may already have * taken ownership of the tty and modified the settings when our * parent was stopped before us, and we would likely pick up the * settings already modified by the shell. */ if (sp != 0 && !sp->_endwin) /* don't do this if we're not in curses */ #if HAVE_TCGETPGRP if (tcgetpgrp(STDIN_FILENO) == getpgrp()) #endif NCURSES_SP_NAME(def_prog_mode) (NCURSES_SP_ARG); /* * Block window change and timer signals. The latter * is because applications use timers to decide when * to repaint the screen. */ (void) sigemptyset(&mask); #ifdef SIGALRM (void) sigaddset(&mask, SIGALRM); #endif #if USE_SIGWINCH (void) sigaddset(&mask, SIGWINCH); #endif (void) sigprocmask(SIG_BLOCK, &mask, &omask); #ifdef SIGTTOU sigttou_blocked = sigismember(&omask, SIGTTOU); if (!sigttou_blocked) { (void) sigemptyset(&mask); (void) sigaddset(&mask, SIGTTOU); (void) sigprocmask(SIG_BLOCK, &mask, NULL); } #endif /* * End window mode, which also resets the terminal state to the * original (pre-curses) modes. */ NCURSES_SP_NAME(endwin) (NCURSES_SP_ARG); /* Unblock SIGTSTP. */ (void) sigemptyset(&mask); (void) sigaddset(&mask, SIGTSTP); #ifdef SIGTTOU if (!sigttou_blocked) { /* Unblock this too if it wasn't blocked on entry */ (void) sigaddset(&mask, SIGTTOU); } #endif (void) sigprocmask(SIG_UNBLOCK, &mask, NULL); /* Now we want to resend SIGSTP to this process and suspend it */ act.sa_handler = SIG_DFL; sigemptyset(&act.sa_mask); act.sa_flags = 0; #ifdef SA_RESTART act.sa_flags |= SA_RESTART; #endif /* SA_RESTART */ sigaction(SIGTSTP, &act, &oact); kill(getpid(), SIGTSTP); /* Process gets suspended...time passes...process resumes */ T(("SIGCONT received")); sigaction(SIGTSTP, &oact, NULL); NCURSES_SP_NAME(flushinp) (NCURSES_SP_ARG); /* * If the user modified the tty state while suspended, he wants * those changes to stick. So save the new "default" terminal state. */ NCURSES_SP_NAME(def_shell_mode) (NCURSES_SP_ARG); /* * This relies on the fact that doupdate() will restore the * program-mode tty state, and issue enter_ca_mode if need be. */ NCURSES_SP_NAME(doupdate) (NCURSES_SP_ARG); /* Reset the signals. */ (void) sigprocmask(SIG_SETMASK, &omask, NULL); }
void UnistdGetpgrp(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs) { ReturnValue->Val->Integer = getpgrp(); }
static void background(void) { /* * A process is a process group leader if its process ID * (getpid()) and its process group ID (getpgrp()) are the same. */ /* * To create a new session (and thereby lose our controlling * terminal) we cannot be a process group leader. * * To guarantee we are not a process group leader, we fork and * let the parent process exit. */ if (getpid() == getpgrp()) { pid_t pid; pid = fork(); switch (pid) { case -1: abort(); /* leave footprints */ break; case 0: /* child */ break; default: /* parent */ exit(0); break; } } /* * By here, we are not a process group leader, so we can make a * new session and become the session leader. */ { pid_t sid = setsid(); if (sid == -1) { static char err[] = "bosserver: WARNING: setsid() failed\n"; write(STDERR_FILENO, err, sizeof err - 1); } } /* * Once we create a new session, the current process is a * session leader without a controlling tty. * * On some systems, the first tty device the session leader * opens automatically becomes the controlling tty for the * session. * * So, to guarantee we do not acquire a controlling tty, we fork * and let the parent process exit. The child process is not a * session leader, and so it will not acquire a controlling tty * even if it should happen to open a tty device. */ if (getpid() == getpgrp()) { pid_t pid; pid = fork(); switch (pid) { case -1: abort(); /* leave footprints */ break; case 0: /* child */ break; default: /* parent */ exit(0); break; } } /* * check that we no longer have a controlling tty */ { int fd; fd = open("/dev/tty", O_RDONLY); if (fd >= 0) { static char err[] = "bosserver: WARNING: /dev/tty still attached\n"; close(fd); write(STDERR_FILENO, err, sizeof err - 1); } } }
void usage() { fprintf(stderr,"Usage:\n\t%s cmd1 [arg1...] = cmd2 [arg2...]\n\n",progname); kill(getpgrp(),SIGTERM); exit (-1); }
extern int main(int argc, char **argv) { char req_buf[COMM_BUF_SIZE], resp_buf[COMM_BUF_SIZE]; /* The character string buffers passed from and to client programs. The strings follow a format defined in atm.h and the parameters are read in and out using sptring processing calls sprintf() and sscanf(). */ int conn; /* A handle on which connection (client) the request came from. Not used initially but included so that in the future different requests could be processed cuncurrently. */ int trans_id; /* The transaction type of the current request */ int done=0; DPRINTF(("SERVER: main() pid %d, ppid %d, pgrp %d\n",getpid(), getppid(), getpgrp())); atm_server_init(argc, argv); for(;;) { server_comm_get_request(&conn, req_buf); sscanf(req_buf, "%d", &trans_id); DPRINTF(("SERVER: main(), request received\n")); switch(trans_id) { case OPEN_ACCT_TRANS: open_account(resp_buf); break; case DEPOSIT_TRANS: deposit(req_buf, resp_buf); break; case WITHDRAW_TRANS: withdraw(req_buf, resp_buf); break; case BALANCE_TRANS: balance(req_buf, resp_buf); break; case SHUTDOWN: if (shutdown_req(req_buf, resp_buf)) done = 1; break; default: handle_bad_trans_id(req_buf, resp_buf); break; } server_comm_send_response(conn, resp_buf); DPRINTF(("SERVER: main(), response sent\n")); if(done) break; } DPRINTF(("SERVER: main(), shuting down\n")); server_comm_shutdown(); return 0; }
int main(int argc, char *argv[]) { int c; int fd; char path[PATH_MAX]; int pid; int detach = 0; int netns = 0; int mountns = 0; int mountnspid = 0; int pidns = 0; int printpid = 0; int mountprocfs = 0; static struct sched_param sp; while ((c = getopt(argc, argv, "+cdnmiufpa:b:k:j:g:r:vh")) != -1) switch (c) { case 'c': /* close file descriptors except stdin/out/error */ for (fd = getdtablesize(); fd > 2; fd--) close(fd); break; case 'd': /* detach from tty */ detach = 1; /* delay setsid() incase new PID namespace */ break; case 'n': /* run in network namespace */ if (unshare(CLONE_NEWNET) == -1) { perror("unshare"); return 1; } netns = NET_NS_CREATE; break; case 'm': /* run in mount namespace */ if (unshare(CLONE_NEWNS) == -1) { perror("unshare"); return 1; } /* mount sysfs to pick up the new network namespace */ mountns = MOUNT_NS_CREATE; /* delay mount of /sysfs */ break; case 'i': /* run in new PID namespace */ if (unshare(CLONE_NEWPID) == -1) { perror("unshare"); return 1; } pidns = PID_NS_CREATE; /* record creation of PID namespace */ break; case 'u': /* run in new UTS namespace */ if (unshare(CLONE_NEWUTS) == -1) { perror("unshare"); return 1; } break; case 'f': /* mount procfs (for new PID namespaces) */ mountprocfs = TRUE; /* delay mounting proc until new NS established */ break; case 'p': /* print pid */ printpid = TRUE; /* delay printing PID until after NS procesisng*/ break; case 'a': /* Attach to pid's network namespace */ pid = atoi(optarg); sprintf(path, "/proc/%d/ns/net", pid); if (attachToNS(path) != 0) { return 1; } netns = NET_NS_JOIN; break; case 'b': /* Attach to pid's mount namespace */ mountns = MOUNT_NS_JOIN; /* delay joining mount namespace */ mountnspid = atoi(optarg); /* record PID to join */ break; case 'k': /* Attach to pid's PID namespace */ pid = atoi(optarg); sprintf(path, "/proc/%d/ns/pid", pid); if (attachToNS(path) != 0) { return 1; } pidns = PID_NS_JOIN; /* record join of PID namespace */ break; case 'j': /* Attach to pid's UTS namespace */ pid = atoi(optarg); sprintf(path, "/proc/%d/ns/uts", pid); if (attachToNS(path) != 0) { return 1; } break; case 'g': /* Attach to cgroup */ cgroup(optarg); break; case 'r': /* Set RT scheduling priority */ sp.sched_priority = atoi(optarg); if (sched_setscheduler(getpid(), SCHED_RR, &sp) < 0) { perror("sched_setscheduler"); return 1; } break; case 'v': printf("%s\n", VERSION); exit(0); case 'h': usage(argv[0]); exit(0); default: usage(argv[0]); exit(1); } /* fork to create / join PID namespace */ if (pidns == PID_NS_CREATE || pidns == PID_NS_JOIN) { int status = 0; pid_t pid = fork(); switch (pid) { case -1: perror("fork"); return 1; case 0: /* child */ break; default: /* parent */ /* print global PID (not namespace PID)*/ if (printpid == 1) { printf("\001%d\n", pid); fflush(stdout); } /* wait on the PID to handle attachment for 'mx'*/ if (waitpid(pid, &status, 0) == -1) return 1; if (WIFEXITED(status)) /* caught child exit, forward return code*/ return WEXITSTATUS(status); else if (WIFSIGNALED(status)) kill(getpid(), WTERMSIG(status)); /* child exit failed, (although return won't distinguish) */ return 1; } } /* if requested, we are in the new/requested PID namespace */ /* completed performing other namespaces (PID/network) operations */ /* go ahead and join the mount namespace if requested */ if (mountns == MOUNT_NS_JOIN && mountnspid != FALSE) { sprintf(path, "/proc/%d/ns/mnt", pid); if (attachToNS(path) != 0) { return 1; } } /* if mount of procfs requested, check for pidns and mountns */ if (mountprocfs && (pidns != PID_NS_CREATE || mountns != MOUNT_NS_CREATE)) { /* requested procfs, but required PID and/or mount namespace missing */ return 1; } /* mount procfs to pick up the new PID namespace */ if (mountprocfs && (mount("none", "/proc", NULL, MS_PRIVATE | MS_REC, NULL) != 0 || mount("proc", "/proc", "proc", MS_NOSUID | MS_NOEXEC | MS_NODEV, NULL) != 0)) { perror("mount"); } /* mount sysfs to pick up the new PID namespace */ if (netns == NET_NS_CREATE && mountns == MOUNT_NS_CREATE) { if (mount("sysfs", "/sys", "sysfs", MS_MGC_VAL, NULL) == -1) { perror("mount"); return 1; } } /* setsid() if requested & required (not needed if using PID namespace) */ if (detach == 1 && pidns == FALSE) { if (getpgrp() == getpid()) { switch (fork()) { case -1: perror("fork"); return 1; case 0: /* child */ break; default: /* parent */ return 0; } } setsid(); } /* print pid if requested (if in new namespace, we don't print local PID) */ if (printpid == 1 && pidns == 0) { printf("\001%d\n", getpid()); fflush(stdout); } /* launch if requested */ if (optind < argc) { execvp(argv[optind], &argv[optind]); perror(argv[optind]); return 1; } usage(argv[0]); return 0; }
void setosjobid(pid_t sid, gid_t *add_grp_id_ptr, struct passwd *pw) { FILE *fp=NULL; shepherd_trace("setosjobid: uid = "pid_t_fmt", euid = "pid_t_fmt, getuid(), geteuid()); # if defined(SOLARIS) || defined(ALPHA) || defined(LINUX) || defined(FREEBSD) || defined(DARWIN) /* Read SgeId from config-File and create Addgrpid-File */ { char *cp; if ((cp = search_conf_val("add_grp_id"))) *add_grp_id_ptr = atol(cp); else *add_grp_id_ptr = 0; } if ((fp = fopen("addgrpid", "w")) == NULL) { shepherd_error(1, "can't open \"addgrpid\" file"); } fprintf(fp, gid_t_fmt"\n", *add_grp_id_ptr); FCLOSE(fp); # elif defined(HP1164) || defined(AIX) { if ((fp = fopen("addgrpid", "w")) == NULL) { shepherd_error(1, "can't open \"addgrpid\" file"); } fprintf(fp, pid_t_fmt"\n", getpgrp()); FCLOSE(fp); } # else { char osjobid[100]; if ((fp = fopen("osjobid", "w")) == NULL) { shepherd_error(1, "can't open \"osjobid\" file"); } if(sge_switch2start_user() == 0) { # if defined(IRIX) { /* The following block contains the operations necessary for * IRIX6.2 (and later) to set array session handles (ASHs) and * service provider info (SPI) records */ struct acct_spi spi; int ret; char *cp; shepherd_trace("in irix code"); /* get _local_ array session id */ if ((ret=newarraysess())) { shepherd_error(1, "error: can't create ASH; errno=%d", ret); } /* retrieve array session id we just assigned to the process and * write it to the os-jobid file */ sprintf(osjobid, "%lld", getash()); shepherd_trace(osjobid); /* set service provider information (spi) record */ strncpy(spi.spi_company, "SGE", 8); strncpy(spi.spi_initiator, get_conf_val("spi_initiator"), 8); strncpy(spi.spi_origin, get_conf_val("queue"),16); strcpy(spi.spi_spi, "Job "); strncat(spi.spi_spi, get_conf_val("job_id"),11); if ((ret=setspinfo(&spi))) { shepherd_error(1, "error: can't set SPI; errno=%d", ret); } if ((cp = search_conf_val("acct_project"))) { prid_t proj; if (strcasecmp(cp, "none") && ((proj = projid(cp)) >= 0)) { shepherd_trace("setting project \"%s\" to id %lld", cp, proj); if (setprid(proj) == -1) shepherd_trace("failed setting project id"); } else { shepherd_trace("can't get id for project \"%s\"", cp); } } else { shepherd_trace("can't get configuration entry for projects"); } } # elif defined(CRAY) { char *cp; { int jobid; if ((jobid=setjob(pw->pw_uid, 0)) < 0) { shepherd_error(1, "error: can't set job ID; errno = %d", errno); } if (sesscntl(jobid, S_ADDFL, S_BATCH) == -1) { shepherd_error(1, "error: sesscntl(%d, S_ADDFL, S_BATCH) failed," " errno = %d", sid, errno); } sprintf(osjobid, "%d", jobid); } if ((cp = search_conf_val("acct_project"))) { int proj; if (strcasecmp(cp, "none") && ((proj = nam2acid(cp)) >= 0)) { shephed_trace("setting project \"%s\" to acid %d", cp, proj); if (acctid(0, proj) == -1) { shepherd_trace("failed setting project id (acctid)"); } } else { shepherd_trace("can't get id for project \"%s\"", cp); } } else { shepherd_trace("can't get configuration entry for projects"); } } # elif defined(NECSX4) || defined(NECSX5) { id_t jobid = 0; dispset2_t attr; int value; /* * Create new Super-UX job */ if (setjid() == -1) { shepherd_trace("ERROR: can't set jobid: %s[%d]", strerror(errno), errno); } else { jobid = getjid(0); shepherd_trace("Created job with id: "sge_u32, (u_long32) jobid); } sprintf(osjobid, sge_u32, (u_long32) jobid); /* * We will use limits for the whole job */ set_rlimits_os_job_id(jobid); /* * The job will use the resources of the configured * Resource Sharing Group (rsg) */ { char *rsg_id_string; int rsg_id; char fsg_dev_string[256]; rsg_id_string = get_conf_val("processors"); rsg_id = atoi(rsg_id_string); if (rsg_id) { int fd; sprintf(fsg_dev_string, "/dev/rsg/%d", rsg_id); fd = open(fsg_dev_string, O_RDONLY); if (fd <= 0) { shepherd_trace("ERROR: can't switch to rsg%d because can't open" "device: %s[%d]", rsg_id, strerror(errno), errno); } else { if (ioctl(fd, RSG_JUMP, NULL) == -1) { close(fd); shepherd_trace("ERROR: can't switch to rsg%d: %s[%d]", rsg_id, strerror(errno), errno); return; } else { close(fd); shepherd_trace("switched to rsg%d", rsg_id); } } } else { shepherd_trace("using default rsg", rsg_id); } } /* * Set scheduling parameter for job */ if (((attr.basepri = atoi(get_conf_val("nec_basepriority"))) != NEC_UNDEF_VALUE) && ((attr.modcpu = atoi(get_conf_val("nec_modcpu"))) != NEC_UNDEF_VALUE) && ((attr.tickcnt = atoi(get_conf_val("nec_tickcnt"))) != NEC_UNDEF_VALUE) && ((attr.dcyfctr = atoi(get_conf_val("nec_dcyfctr"))) != NEC_UNDEF_VALUE) && ((attr.dcyintvl = atoi(get_conf_val("nec_dcyintvl"))) != NEC_UNDEF_VALUE) && ((attr.tmslice = atoi(get_conf_val("nec_timeslice"))) != NEC_UNDEF_VALUE) && ((attr.mempri = atoi(get_conf_val("nec_memorypriority"))) != NEC_UNDEF_VALUE) && ((attr.szefctmrt = atoi(get_conf_val("nec_mrt_size_effct"))) != NEC_UNDEF_VALUE) && ((attr.priefctmrt = atoi(get_conf_val("nec_mrt_pri_effct"))) != NEC_UNDEF_VALUE) && ((attr.minmrt = atoi(get_conf_val("nec_mrt_minimum"))) != NEC_UNDEF_VALUE) && ((attr.agrange = atoi(get_conf_val("nec_aging_range"))) != NEC_UNDEF_VALUE) && ((attr.spinherit = atoi(get_conf_val("nec_slavepriority"))) != NEC_UNDEF_VALUE) && ((attr.concpu = atoi(get_conf_val("nec_cpu_count"))) != NEC_UNDEF_VALUE)) { if (dispcntl(SG_JID, getjid(0), DCNTL_SET2, &attr) == -1) { shepherd_trace("ERROR: can't set scheduling parameter: %s[%d]", strerror(errno), errno); } else { shepherd_trace("control parameters for active process scheduling modified"); print_scheduling_parameters(attr); } } else { shepherd_trace("we do not control active process scheduling"); } } # else /* write a default os-jobid to file */ sprintf(osjobid, pid_t_fmt, sid); # endif sge_switch2admin_user(); } else /* not running as super user --> we want a default os-jobid */ sprintf(osjobid, "0"); if(fprintf(fp, "%s\n", osjobid) < 0) shepherd_trace("error writing osjobid file"); FCLOSE(fp); /* Close os-jobid file */ } # endif return; FCLOSE_ERROR: shepherd_error(1, "can't close file"); }
/*** Return process group id of calling process. @function getpgrp @treturn int process group id of calling process @see getpid */ static int Pgetpgrp(lua_State *L) { checknargs(L, 0); return pushintresult(getpgrp ()); }
/* * 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; /* if the pid is 0, it is the child. */ int jid; /* if the child runs in background, we should know the jid and print the infomation */ /* * Use new_mask to mask three signals. * Before the child process execve(), we should unblock these signals. * When it comes to parent process, we should set the old_mask set to * it after we add the job in job_list. */ sigset_t new_mask, old_mask; /* Parse command line */ bg = parseline(cmdline, &tok); /* * Maybe there are some more errors that we should return. * I did not meet them. If I met an error condition, I will * make an improvement as soon as possible. */ if (bg == -1) return; /* parsing error */ if (tok.argv[0] == NULL) return; /* ignore empty lines */ /* * As it is said in the writeup, If the first word is a built-in command, the * shell immediately executes the command in the current process. Otherwise, * the word is assumed to be the pathname of an executable program. In this * case, the shell forks a child process, then loads and runs the program in * the context of the child. * 1. If it is a built-in command, builtinCommand function will handle it. * 2. If it is a executable program, the function returns 0. * 3. Then, we should block the signals before we fork a child. * 4. Put the child in a new process group. * 5. Set the I/O Redirection and make the signal default. * 6. Execute the program and exit. * 7. Add the job and unblock the signals in parent. * 8. If the child runs in foreground, wait for it. */ if (!builtinCommand(tok)) { Sigemptyset(&new_mask); Sigaddset(&new_mask, SIGCHLD); Sigaddset(&new_mask, SIGINT); Sigaddset(&new_mask, SIGTSTP); Sigprocmask(SIG_BLOCK, &new_mask, &old_mask); if (0 == (pid = Fork())) { int fdout, fdin; Setpgid(0, 0); dup2(fdout = getfd(OUT, tok.outfile), STDOUT_FILENO); dup2(fdin = getfd(IN, tok.infile), STDIN_FILENO); if (!bg) { tcsetpgrp(STDIN_FILENO, getpgrp()); } Signal(SIGCHLD, SIG_DFL); Signal(SIGINT, SIG_DFL); Signal(SIGTSTP, SIG_DFL); Sigprocmask(SIG_UNBLOCK, &new_mask, NULL); if (execve(tok.argv[0], tok.argv, environ) < 0) { printf("%s: Command not found.\n", tok.argv[0]); exit(0); } if (STDOUT_FILENO != fdout) { close(fdout); } if (STDIN_FILENO != fdin) { close(fdin); } exit(0); } if (bg) { addjob(job_list, pid, BG, cmdline); Sigprocmask(SIG_SETMASK, &old_mask, NULL); jid = pid2jid(pid); printf("[%d] (%d) %s\n", jid, pid, cmdline); } else { addjob(job_list, pid, FG, cmdline); Sigprocmask(SIG_SETMASK, &old_mask, NULL); /* * If the child runs in foreground, we should wait for it. I think it is * the most tricky thing in this shell lab. I test everything I know. Then, * I found the sigsuspend() function had the best performance. * 1. pause(). * It is the first way I think about. When I do manually from the * command line, It is OK. However, when it comes to trace file, sometimes * it is OK, sometimes it will cause an error. * 2. sleep(1), usleep(n), or something like these. * Although Michael said that we cannot use sleep, I do not know what to do * and what the performance is. So, I test it. When I ran it from the * command line, I could not find any wrong. When it comes to the trace * files, there are lots of errors. It seems that it is not a good way. -_-b * 3. sleep(0), sleep(0), sleep(0)... * When I found the information in the Internet, someone said 3 or more * sleep(0) could be a good choice for wait. The fact is that it can pass * a lot of trace files, but the performance is not stable. Also, I think * it will waste the CPU resource. * sigsuspend() is the only way that I found could pass the ./sdriver. If there * is annother better way, I will be very interested in it. If you would like * to tell a better solution, I will be very happy. */ while (fgpid(job_list)) { sigsuspend(&old_mask); } } } return; }
void setjobctl(int on) { int i; if (on == jobctl || rootshell == 0) return; if (on) { if (ttyfd != -1) close(ttyfd); if ((ttyfd = open(_PATH_TTY, O_RDWR | O_CLOEXEC)) < 0) { i = 0; while (i <= 2 && !isatty(i)) i++; if (i > 2 || (ttyfd = fcntl(i, F_DUPFD_CLOEXEC, 10)) < 0) { jobctl_notty(); return; } } if (ttyfd < 10) { /* * Keep our TTY file descriptor out of the way of * the user's redirections. */ if ((i = fcntl(ttyfd, F_DUPFD_CLOEXEC, 10)) < 0) { jobctl_notty(); return; } close(ttyfd); ttyfd = i; } do { /* while we are in the background */ initialpgrp = tcgetpgrp(ttyfd); if (initialpgrp < 0) { jobctl_notty(); return; } if (initialpgrp != getpgrp()) { if (!iflag) { initialpgrp = -1; jobctl_notty(); return; } kill(0, SIGTTIN); continue; } } while (0); setsignal(SIGTSTP); setsignal(SIGTTOU); setsignal(SIGTTIN); setpgid(0, rootpid); tcsetpgrp(ttyfd, rootpid); } else { /* turning job control off */ setpgid(0, initialpgrp); if (ttyfd >= 0) { tcsetpgrp(ttyfd, initialpgrp); close(ttyfd); ttyfd = -1; } setsignal(SIGTSTP); setsignal(SIGTTOU); setsignal(SIGTTIN); } jobctl = on; }
/* * main - The shell's main routine */ int main(int argc, char **argv) { char c; char cmdline[MAXLINE]; /* cmdline for fgets */ int emit_prompt = 1; /* emit prompt (default) */ /* Redirect stderr to stdout (so that driver will get all output * on the pipe connected to stdout) */ dup2(1, 2); /* Parse the command line */ while ((c = getopt(argc, argv, "hvp")) != EOF) { switch (c) { case 'h': /* print help message */ usage(); break; case 'v': /* emit additional diagnostic info */ verbose = 1; break; case 'p': /* don't print a prompt */ emit_prompt = 0; /* handy for automatic testing */ break; default: usage(); } } /* Install the signal handlers */ /* These are the ones you will need to implement */ Signal(SIGINT, sigint_handler); /* ctrl-c */ Signal(SIGTSTP, sigtstp_handler); /* ctrl-z */ Signal(SIGCHLD, sigchld_handler); /* Terminated or stopped child */ Signal(SIGTTIN, SIG_IGN); Signal(SIGTTOU, SIG_IGN); /* This one provides a clean way to kill the shell */ Signal(SIGQUIT, sigquit_handler); /* Initialize the job list */ initjobs(job_list); /* Execute the shell's read/eval loop */ while (1) { if (tcgetpgrp(STDIN_FILENO) != getpgrp()) { tcsetpgrp(STDIN_FILENO, getpgrp()); } if (emit_prompt) { printf("%s", prompt); fflush(stdout); } if ((fgets(cmdline, MAXLINE, stdin) == NULL) && ferror(stdin)) app_error("fgets error"); if (feof(stdin)) { /* End of file (ctrl-d) */ printf ("\n"); fflush(stdout); fflush(stderr); exit(0); } /* Remove the trailing newline */ cmdline[strlen(cmdline)-1] = '\0'; /* Evaluate the command line */ eval(cmdline); fflush(stdout); fflush(stdout); } exit(0); /* control never reaches here */ }
int main(int argc, char *argv[]) { printf("hello,main()\n"); printf("test group id: %d pid : %d ppid: %d \n",getpgrp(),getpid(),getppid()); //sleep(5); return 0; }
int main() { pid_t pid1,pid2; pid_t pid; int status; if((pid1 = fork()) < 0) { perror("Fail to fork"); exit(EXIT_FAILURE); }else if(pid1 == 0){ setpgrp(); // 自己创建一个组,PGID == PID printf("Create child process pid1 (PID : %d PGID : %d).\n",getpid(),getpgrp()); while(1); }else{ if((pid2 = fork()) < 0) { perror("Fail to fork"); exit(EXIT_FAILURE); }else if(pid2 == 0){ printf("Create child process pid2 (PID : %d PGID : %d).\n",getpid(),getpgrp()); while(1); // printf("Child process (PID : %d PGID :%d) exit.\n",getpid(),getpgrp()); }else{ sleep(1); printf("Father PID : %d.\n",getpid()); while(1) { printf("The father waitpid .\n"); pid = waitpid(-1,&status,WUNTRACED | WCONTINUED | WNOHANG); if(pid == -1) break; printf("CHILD PID : %d.\n",pid); if(WIFEXITED(status)) { printf("Normal exit.\n"); }else if(WIFSIGNALED(status)){ printf("EXIT by signal(%d).\n",WTERMSIG(status)); }else if(WIFSTOPPED(status)){ printf("Stop by signal(%d).\n",WSTOPSIG(status)); }else if(WIFCONTINUED(status)){ printf("Continue bys SIGCONT.\n"); }else{ printf("Unknown.\n"); } } } } return 0; }
void OsInit(void) { static Bool been_here = FALSE; static char* admpath = ADMPATH; static char* devnull = "/dev/null"; char fname[PATH_MAX]; #ifdef macII set42sig(); #endif if (!been_here) { #if !defined(__SCO__) && !defined(__CYGWIN__) && !defined(__UNIXWARE__) fclose(stdin); fclose(stdout); #endif /* * If a write of zero bytes to stderr returns non-zero, i.e. -1, * then writing to stderr failed, and we'll write somewhere else * instead. (Apparently this never happens in the Real World.) */ if (write (2, fname, 0) == -1) { FILE *err; if (strlen (display) + strlen (admpath) + 1 < sizeof fname) sprintf (fname, admpath, display); else strcpy (fname, devnull); /* * uses stdio to avoid os dependencies here, * a real os would use * open (fname, O_WRONLY|O_APPEND|O_CREAT, 0666) */ if (!(err = fopen (fname, "a+"))) err = fopen (devnull, "w"); if (err && (fileno(err) != 2)) { dup2 (fileno (err), 2); fclose (err); } #if defined(SYSV) || defined(SVR4) || defined(WIN32) || defined(__CYGWIN__) { static char buf[BUFSIZ]; setvbuf (stderr, buf, _IOLBF, BUFSIZ); } #else setlinebuf(stderr); #endif } #ifndef X_NOT_POSIX if (getpgrp () == 0) setpgid (0, 0); #else #if !defined(SYSV) && !defined(WIN32) if (getpgrp (0) == 0) setpgrp (0, getpid ()); #endif #endif #ifdef RLIMIT_DATA if (limitDataSpace >= 0) { struct rlimit rlim; if (!getrlimit(RLIMIT_DATA, &rlim)) { if ((limitDataSpace > 0) && (limitDataSpace < rlim.rlim_max)) rlim.rlim_cur = limitDataSpace; else rlim.rlim_cur = rlim.rlim_max; (void)setrlimit(RLIMIT_DATA, &rlim); } } #endif #ifdef RLIMIT_STACK if (limitStackSpace >= 0) { struct rlimit rlim; if (!getrlimit(RLIMIT_STACK, &rlim)) { if ((limitStackSpace > 0) && (limitStackSpace < rlim.rlim_max)) rlim.rlim_cur = limitStackSpace; else rlim.rlim_cur = rlim.rlim_max; (void)setrlimit(RLIMIT_STACK, &rlim); } } #endif #ifdef RLIMIT_NOFILE if (limitNoFile >= 0) { struct rlimit rlim; if (!getrlimit(RLIMIT_NOFILE, &rlim)) { if ((limitNoFile > 0) && (limitNoFile < rlim.rlim_max)) rlim.rlim_cur = limitNoFile; else rlim.rlim_cur = rlim.rlim_max; #if 0 if (rlim.rlim_cur > MAXSOCKS) rlim.rlim_cur = MAXSOCKS; #endif (void)setrlimit(RLIMIT_NOFILE, &rlim); } } #endif #ifdef SERVER_LOCK LockServer(); #endif been_here = TRUE; } TimerInit(); #ifdef DDXOSINIT OsVendorInit(); #endif /* * No log file by default. OsVendorInit() should call LogInit() with the * log file name if logging to a file is desired. */ LogInit(NULL, NULL); #ifdef SMART_SCHEDULE if (!SmartScheduleDisable) if (!SmartScheduleInit ()) SmartScheduleDisable = TRUE; #endif OsInitAllocator(); if (!OsDelayInitColors) OsInitColors(); }
int main(int argc, char **argv) { int masterr, masterw, slaver, slavew, pid; char ptyname[FILENAME_MAX]; bufchain tochild, tostdout; int tochild_active, tostdout_active, fromstdin_active, fromchild_active; int exitcode = -1; pid_t childpid = -1; --argc, ++argv; /* point at argument after "--" */ /* * Allocate the pipe for transmitting signals back to the * top-level select loop. */ if (pipe(signalpipe) < 0) { perror("pipe"); return 1; } /* * Now that pipe exists, we can set up the SIGCHLD handler to * write to one end of it. We needn't already know details like * which child pid we're waiting for, because we don't need that * until we respond to reading the far end of the pipe in the * main select loop. */ signal(SIGCHLD, sigchld); /* * Allocate the pty or pipes. */ masterr = pty_get(ptyname); masterw = dup(masterr); slaver = open(ptyname, O_RDWR); slavew = dup(slaver); if (slaver < 0) { perror("slave pty: open"); return 1; } bufchain_init(&tochild); bufchain_init(&tostdout); tochild_active = tostdout_active = TRUE; fromchild_active = fromstdin_active = TRUE; /* * Fork and execute the command. */ pid = fork(); if (pid < 0) { perror("fork"); return 1; } if (pid == 0) { int i; /* * We are the child. */ close(masterr); close(masterw); fcntl(slaver, F_SETFD, 0); /* don't close on exec */ fcntl(slavew, F_SETFD, 0); /* don't close on exec */ close(0); dup2(slaver, 0); close(1); dup2(slavew, 1); int fd; close(2); dup2(slavew, 2); setsid(); setpgid(0, 0); tcsetpgrp(0, getpgrp()); if ((fd = open("/dev/tty", O_RDWR)) >= 0) { ioctl(fd, TIOCNOTTY); close(fd); } ioctl(slavew, TIOCSCTTY); /* Close everything _else_, for tidiness. */ for (i = 3; i < 1024; i++) close(i); if (argc > 0) { execvp(argv[0], argv); /* assumes argv has trailing NULL */ } else { execl(getenv("SHELL"), getenv("SHELL"), NULL); } /* * If we're here, exec has gone badly foom. */ perror("exec"); exit(127); } /* * Now we're the parent. Close the slave fds and start copying * stuff back and forth. */ close(slaver); close(slavew); childpid = pid; tcgetattr(0, &oldattrs); newattrs = oldattrs; newattrs.c_iflag &= ~(IXON | IXOFF | ICRNL | INLCR); newattrs.c_oflag &= ~(ONLCR | OCRNL); newattrs.c_lflag &= ~(ISIG | ICANON | ECHO); atexit(attrsonexit); tcsetattr(0, TCSADRAIN, &newattrs); while (1) { fd_set rset, wset; char buf[65536]; int maxfd, ret; FD_ZERO(&rset); FD_ZERO(&wset); maxfd = 0; FD_SET(signalpipe[0], &rset); maxfd = max(signalpipe[0]+1, maxfd); if (tochild_active && bufchain_size(&tochild)) { FD_SET(masterw, &wset); maxfd = max(masterw+1, maxfd); } if (tostdout_active && bufchain_size(&tostdout)) { FD_SET(1, &wset); maxfd = max(1+1, maxfd); } if (fromstdin_active && bufchain_size(&tochild) < LOCALBUF_LIMIT) { FD_SET(0, &rset); maxfd = max(0+1, maxfd); } if (fromchild_active && bufchain_size(&tostdout) < LOCALBUF_LIMIT) { FD_SET(masterr, &rset); maxfd = max(masterr+1, maxfd); } do { ret = select(maxfd, &rset, &wset, NULL, NULL); } while (ret < 0 && (errno == EINTR || errno == EAGAIN)); if (ret < 0) { perror("select"); return 1; } if (FD_ISSET(masterr, &rset)) { if (FD_ISSET(masterr, &rset)) { ret = read(masterr, buf, sizeof(buf)); if (ret <= 0) { /* * EIO from a pty master just means end of * file, annoyingly. Why can't it report * ordinary EOF? */ if (errno == EIO) ret = 0; if (ret < 0) { perror("child process: read"); } close(masterr); fromchild_active = FALSE; ret = 0; } } else ret = 0; if (ret) { bufchain_add(&tostdout, buf, ret); } } if (FD_ISSET(0, &rset)) { if (FD_ISSET(0, &rset)) { ret = read(0, buf, sizeof(buf)); if (ret <= 0) { if (ret < 0) { perror("stdin: read"); } close(0); fromstdin_active = FALSE; ret = 0; } } else ret = 0; if (ret) { bufchain_add(&tochild, buf, ret); } } if (FD_ISSET(1, &wset)) { void *data; int len, ret; bufchain_prefix(&tostdout, &data, &len); if ((ret = write(1, data, len)) < 0) { perror("stdout: write"); close(1); close(masterr); tostdout_active = fromchild_active = FALSE; } else bufchain_consume(&tostdout, ret); } if (FD_ISSET(masterw, &wset)) { void *data; int len; bufchain_prefix(&tochild, &data, &len); if ((ret = write(masterw, data, len)) < 0) { perror("child process: write"); close(0); close(masterw); tochild_active = fromstdin_active = FALSE; } else bufchain_consume(&tochild, ret); } if (FD_ISSET(signalpipe[0], &rset)) { ret = read(signalpipe[0], buf, 1); if (ret == 1 && buf[0] == 'C') { int pid, code; pid = wait(&code); /* reap the exit code */ if (pid == childpid) exitcode = code; } } /* * If there can be no further data from a direction (the * input fd has been closed and the buffered data is used * up) but its output fd is still open, close it. */ if (!fromstdin_active && !bufchain_size(&tochild) && tochild_active) { tochild_active = FALSE; close(masterw); } if (!fromchild_active && !bufchain_size(&tostdout) && tostdout_active){ tostdout_active = FALSE; close(1); } /* * Termination condition with pipes is that there's still * data flowing in at least one direction. * * Termination condition for a pty-based run is that the * child process hasn't yet terminated and/or there is * still buffered data to send. */ if (exitcode < 0) /* process is still active */; else if (tochild_active && bufchain_size(&tochild)) /* data still to be sent to child's children */; else if (tostdout_active && bufchain_size(&tostdout)) /* data still to be sent to stdout */; else break; /* terminate */ } close(masterw); close(masterr); if (exitcode < 0) { int pid, code; pid = wait(&code); exitcode = code; } return (WIFEXITED(exitcode) ? WEXITSTATUS(exitcode) : 128 | WTERMSIG(exitcode)); }
static int G__posix__0_35(G__value* result7, G__CONST char* funcname, struct G__param* libp, int hash) { G__letint(result7, 105, (long) getpgrp()); return(1 || funcname || hash || result7 || libp) ; }
/*---------------------------------------------------------------------------*/ void matar_procesos_propios() { killpg(getpgrp(),SIGINT); killpg(getpgrp(),SIGQUIT); killpg(getpgrp(),SIGKILL); }
/* * do_child_1() */ void do_child_1(void) { int kid_count, fork_kid_pid[MAXKIDS]; int ret_val; int i, j, k, found; int group1, group2; int wait_kid_pid[MAXKIDS], status; setup_sigint(); group1 = getpgrp(); for (kid_count = 0; kid_count < MAXKIDS; kid_count++) { if (kid_count == (MAXKIDS / 2)) { group2 = setpgrp(); } intintr = 0; ret_val = FORK_OR_VFORK(); if (ret_val == 0) { /* child */ #ifdef UCLINUX if (self_exec(argv0, "n", 2) < 0) { tst_resm(TFAIL, "Fork kid %d failed. " "errno = %d", kid_count, errno); exit(ret_val); } #else do_exit(); #endif /*NOTREACHED*/ } else if (ret_val < 0) { tst_resm(TFAIL, "Fork kid %d failed. " "errno = %d", kid_count, errno); exit(ret_val); } /* parent */ fork_kid_pid[kid_count] = ret_val; } #ifdef UCLINUX /* Give the kids a chance to setup SIGINT again, since this is * cleared by exec(). */ sleep(3); #endif /* Now send all the kids a SIGINT to tell them to * proceed */ for (i = 0; i < MAXKIDS; i++) { if (kill(fork_kid_pid[i], SIGINT) < 0) { tst_resm(TFAIL, "Kill of child %d " "failed, errno = %d", i, errno); exit(-1); } } /* * Wait till all kids have terminated. Stash away their * pid's in an array. */ kid_count = 0; errno = 0; while (((ret_val = waitpid(-1, &status, 0)) != -1) || (errno == EINTR)) { if (ret_val == -1) { continue; } if (!WIFEXITED(status)) { tst_resm(TFAIL, "Child %d did not exit " "normally", ret_val); flag = FAILED; printf("status: %d\n", status); } else { if (WEXITSTATUS(status) != 3) { tst_resm(TFAIL, "Child %d" "exited with wrong " "status", ret_val); tst_resm(TFAIL, "Expected 3 " "got %d ", WEXITSTATUS(status)); flag = FAILED; } } wait_kid_pid[kid_count++] = ret_val; } /* * Check that for every entry in the fork_kid_pid array, * there is a matching pid in the wait_kid_pid array. If * not, it's an error. */ for (i = 0; i < kid_count; i++) { found = 0; for (j = 0; j < MAXKIDS; j++) { if (fork_kid_pid[j] == wait_kid_pid[i]){ found = 1; break; } } if (!found) { tst_resm(TFAIL, "Did not find a " "wait_kid_pid for the " "fork_kid_pid of %d", fork_kid_pid[j]); for (k = 0; k < MAXKIDS; k++) { tst_resm(TFAIL, "fork_kid_pid[%d] = " "%d", k, fork_kid_pid[k]); } for (k = 0; k < kid_count; k++) { tst_resm(TFAIL, "wait_kid_pid[%d] = " "%d", k, wait_kid_pid[k]); } flag = FAILED; } } if (flag) { exit(1); } else { exit(0); } }
/* * Start up the process with the given args */ INTERNAL int start_agent(AGENT_REQ *areq, char *cmd, char *args, int *retpid) { int argc; char *argv[MAX_ARGS]; char hostname[AGENTD_NAMELEN]; int childpid; int pid, exitstat; int pipeout[2], pipeerr[2]; int rc; EVENT_AGENTD_STAT estat; EVENT_AGENTD_LOG elogout, elogerr; char msg[200]; char cmdpath[PATHLEN]; if (WorkDir) make_path(cmdpath, ExecPath, cmd); else strcpy(cmdpath, cmd); argv[0] = cmd; argc = 1; if (Verbose) printf("0: %s (%s)\n", argv[0], cmdpath); rc = parse_args(args, argv, 1); if (rc < 0) { return(0); } argc = rc; /**************************/ /****** START DEBUG *******/ #ifdef FAKE_THIS_FOR_DEBUGGING printf("start_agent: sleeping\n"); if (areq) { areq->status = AGENTD_AGENT_RUNNING; areq->pid = 9999999; estat.reqseq = EventSeq(areq->ereq); estat.tag = areq->ereq.tag; estat.reqtype = AGENTD_CTL_START; estat.result = 9999999; estat.rstatus = AGENTD_STATUS_OK; SEND(EventFrom(areq->ereq), AGENTD_STAT, estat); } sleep(10); if (areq) { areq->status = AGENTD_AGENT_EXIT; estat.result = 0; estat.rstatus = AGENTD_AGENT_EXIT; SEND(EventFrom(areq->ereq), AGENTD_STAT, estat); } printf("start_agent: exiting\n"); return(AGENTD_STATUS_OK); #endif /******** END DEBUG *******/ /**************************/ if (pipe(pipeout) != SYS_OK) { fprintf(stderr, "start_agent: couldn't create stdout pipe\n"); perror("start_agent"); return(AGENTD_STATUS_RUNERR); } if (pipe(pipeerr) != SYS_OK) { fprintf(stderr, "start_agent: couldn't create stderr pipe\n"); perror("start_agent"); return(AGENTD_STATUS_RUNERR); } childpid = fork(); if (childpid < 0) { /* Error occurred */ fprintf(stderr, "start_agent: fork failed\n"); perror("start_agent"); close(pipeout[0]); close(pipeout[1]); close(pipeerr[0]); close(pipeerr[1]); return(AGENTD_STATUS_RUNERR); } /* * Exec command from newly forked process */ if (childpid == 0) { /* Child process */ int fdin; int argc; int rc; /**** event_exit_(); ****/ if (WorkDir) chdir(WorkPath); /* stdin */ fdin = open("/dev/null", O_RDONLY); dup2(fdin, 0); close(fdin); /* stdout */ rc = dup2(pipeout[1], 1); close(pipeout[0]); close(pipeout[1]); if (rc < 0) printf("start_agent: couldn't dup pipe as stdout"); /* stderr */ rc = dup2(pipeerr[1], 2); close(pipeerr[0]); close(pipeerr[1]); if (rc < 0) printf("start_agent: couldn't dup pipe as stderr"); /* Create a new process group */ setpgrp(); fprintf(stderr, "agentd: child proc %d, pgrp %d execing %s\n", getpid(), getpgrp(), cmd); execv(cmdpath, argv); /* If exec returns it means an error occurred */ close(0); close(1); close(2); exit(AGENTD_STATUS_RUNERR); } signal(SIGABRT, SIG_IGN); if (Verbose) printf("start_agent: created child process %d\n", childpid); /* Report startup status to requester */ if (areq) { areq->status = AGENTD_AGENT_RUNNING; areq->pid = childpid; estat.reqseq = EventSeq(areq->ereq); estat.tag = areq->ereq.tag; estat.reqtype = AGENTD_CTL_START; estat.result = childpid; estat.rstatus = AGENTD_STATUS_OK; SEND(EventFrom(areq->ereq), AGENTD_STAT, estat); } gethostname(hostname, sizeof(hostname)); /* Set up stderr */ elogerr.head.to = EVENT_BCAST_NOTME; elogerr.type = AGENTD_LOG_STDERR; elogerr.flags = pipeerr[0]; elogerr.pid = childpid; strcpy(elogerr.hostname, hostname); strcpy(elogerr.program, cmd); /* Start reader thread and wait for it to initialize */ if (Verbose) printf("start_agent: starting reader thread for stderr\n"); mp_task(reader, &elogerr, 0); mp_decsema(ReadInit); /* Broadcast a message */ sprintf(elogerr.msg, "agentd: agent started as pid %d\n", childpid); SEND(EVENT_BCAST_NOTME, AGENTD_LOG, elogerr); /* Now do the same for stdout */ elogout.head.to = EVENT_BCAST_NOTME; elogout.type = AGENTD_LOG_STDOUT; elogout.flags = pipeout[0]; elogout.pid = childpid; strcpy(elogout.hostname, hostname); strcpy(elogout.program, cmd); if (Verbose) printf("start_agent: starting reader thread for stdout\n"); mp_task(reader, &elogout, 0); mp_decsema(ReadInit); /* Wait for child (agent) process to exit */ if (Verbose) printf("start_agent: waiting for agent proc %d\n", childpid); pid = waitpid(childpid, &exitstat, 0); if (pid <= 0) { perror("start_agent: waitpid"); } if (WIFSIGNALED(exitstat)) sprintf(msg, "agent %d exited on signal %s with rc %d", childpid, signame(WTERMSIG(exitstat)), WEXITSTATUS(exitstat)); else sprintf(msg, "agent %d exited normally with rc %d", childpid, WEXITSTATUS(exitstat)); if (Verbose) printf("start_agent: %s\n", msg); /* Set exit and write to pipe to wake up readers */ mp_lock(Exitlock); Exit = childpid; sleep(5); /* delay to let things quiesce */ write(pipeout[1], EofStr, strlen(EofStr)+1); write(pipeerr[1], EofStr, strlen(EofStr)+1); if (Verbose) printf("start_agent: %d.%d waiting for 2 %d.readers to exit\n", getpid(), mp_gettid(), childpid); mp_decsema(Exitwait); if (Verbose) printf("start_agent: %d.%d waiting for 1 %d.reader to exit\n", getpid(), mp_gettid(), childpid); mp_decsema(Exitwait); if (Verbose) printf("start_agent: %d.%d all %d.readers exited\n", getpid(), mp_gettid(), childpid); Exit = 0; mp_unlock(Exitlock); /* Broadcast a message */ sprintf(elogerr.msg, "agentd: %s\n", msg); SEND(EVENT_BCAST_NOTME, AGENTD_LOG, elogerr); close(pipeout[0]); close(pipeout[1]); close(pipeerr[0]); close(pipeerr[1]); /* * Report exit status back to requester */ if (areq) { areq->status = AGENTD_AGENT_EXIT; estat.result = exitstat; estat.rstatus = AGENTD_AGENT_EXIT; SEND(EventFrom(areq->ereq), AGENTD_STAT, estat); } if (retpid) *retpid = childpid; return(AGENTD_STATUS_OK); }
pid_t Getpgrp(void) { return getpgrp(); }
status_t Shell::_Spawn(int row, int col, const char *encoding, int argc, const char **argv) { const char *kDefaultShellCommand[] = { "/bin/sh", "--login", NULL }; if (argv == NULL || argc == 0) { argv = kDefaultShellCommand; argc = 2; } signal(SIGTTOU, SIG_IGN); #ifdef __HAIKU__ // get a pseudo-tty int master = posix_openpt(O_RDWR | O_NOCTTY); const char *ttyName; #else /* __HAIKU__ */ /* * Get a pseudo-tty. We do this by cycling through files in the * directory. The operating system will not allow us to open a master * which is already in use, so we simply go until the open succeeds. */ char ttyName[B_PATH_NAME_LENGTH]; int master = -1; DIR *dir = opendir("/dev/pt/"); if (dir != NULL) { struct dirent *dirEntry; while ((dirEntry = readdir(dir)) != NULL) { // skip '.' and '..' if (dirEntry->d_name[0] == '.') continue; char ptyName[B_PATH_NAME_LENGTH]; snprintf(ptyName, sizeof(ptyName), "/dev/pt/%s", dirEntry->d_name); master = open(ptyName, O_RDWR); if (master >= 0) { // Set the tty that corresponds to the pty we found snprintf(ttyName, sizeof(ttyName), "/dev/tt/%s", dirEntry->d_name); break; } else { // B_BUSY is a normal case if (errno != B_BUSY) fprintf(stderr, B_TRANSLATE("could not open %s: %s\n"), ptyName, strerror(errno)); } } closedir(dir); } #endif /* __HAIKU__ */ if (master < 0) { fprintf(stderr, B_TRANSLATE("Didn't find any available pseudo ttys.")); return errno; } #ifdef __HAIKU__ if (grantpt(master) != 0 || unlockpt(master) != 0 || (ttyName = ptsname(master)) == NULL) { close(master); fprintf(stderr, B_TRANSLATE("Failed to init pseudo tty.")); return errno; } #endif /* __HAIKU__ */ /* * Get the modes of the current terminal. We will duplicates these * on the pseudo terminal. */ thread_id terminalThread = find_thread(NULL); /* Fork a child process. */ if ((fProcessID = fork()) < 0) { close(master); return B_ERROR; } handshake_t handshake; if (fProcessID == 0) { // Now in child process. // close the PTY master side close(master); /* * Make our controlling tty the pseudo tty. This hapens because * we cleared our original controlling terminal above. */ /* Set process session leader */ if (setsid() < 0) { handshake.status = PTY_NG; snprintf(handshake.msg, sizeof(handshake.msg), B_TRANSLATE("could not set session leader.")); send_handshake_message(terminalThread, handshake); exit(1); } /* open slave pty */ int slave = -1; if ((slave = open(ttyName, O_RDWR)) < 0) { handshake.status = PTY_NG; snprintf(handshake.msg, sizeof(handshake.msg), B_TRANSLATE("can't open tty (%s)."), ttyName); send_handshake_message(terminalThread, handshake); exit(1); } /* set signal default */ signal(SIGCHLD, SIG_DFL); signal(SIGHUP, SIG_DFL); signal(SIGQUIT, SIG_DFL); signal(SIGTERM, SIG_DFL); signal(SIGINT, SIG_DFL); signal(SIGTTOU, SIG_DFL); struct termios tio; /* get tty termios (not necessary). * TODO: so why are we doing it ? */ tcgetattr(slave, &tio); initialize_termios(tio); /* * change control tty. */ dup2(slave, 0); dup2(slave, 1); dup2(slave, 2); /* close old slave fd. */ if (slave > 2) close(slave); /* * set terminal interface. */ if (tcsetattr(0, TCSANOW, &tio) == -1) { handshake.status = PTY_NG; snprintf(handshake.msg, sizeof(handshake.msg), B_TRANSLATE("failed set terminal interface (TERMIOS).")); send_handshake_message(terminalThread, handshake); exit(1); } /* * set window size. */ handshake.status = PTY_WS; send_handshake_message(terminalThread, handshake); receive_handshake_message(handshake); if (handshake.status != PTY_WS) { handshake.status = PTY_NG; snprintf(handshake.msg, sizeof(handshake.msg), B_TRANSLATE("mismatch handshake.")); send_handshake_message(terminalThread, handshake); exit(1); } struct winsize ws = { handshake.row, handshake.col }; ioctl(0, TIOCSWINSZ, &ws); tcsetpgrp(0, getpgrp()); // set this process group ID as the controlling terminal #ifndef __HAIKU__ ioctl(0, 'pgid', getpid()); #endif set_thread_priority(find_thread(NULL), B_NORMAL_PRIORITY); /* pty open and set termios successful. */ handshake.status = PTY_OK; send_handshake_message(terminalThread, handshake); /* * setenv TERM and TTY. */ setenv("TERM", "xterm", true); setenv("TTY", ttyName, true); setenv("TTYPE", encoding, true); execve(argv[0], (char * const *)argv, environ); // Exec failed. // TODO: This doesn't belong here. sleep(1); BString alertCommand = "alert --stop '"; alertCommand += B_TRANSLATE("Cannot execute \"%command\":\n\t%error"); alertCommand += "' '"; alertCommand += B_TRANSLATE("Use default shell"); alertCommand += "' '"; alertCommand += B_TRANSLATE("Abort"); alertCommand += "'"; alertCommand.ReplaceFirst("%command", argv[0]); alertCommand.ReplaceFirst("%error", strerror(errno)); int returnValue = system(alertCommand.String()); if (returnValue == 0) { execl(kDefaultShellCommand[0], kDefaultShellCommand[0], kDefaultShellCommand[1], NULL); } exit(1); } /* * In parent Process, Set up the input and output file pointers so * that they can write and read the pseudo terminal. */ /* * close parent control tty. */ int done = 0; while (!done) { receive_handshake_message(handshake); switch (handshake.status) { case PTY_OK: done = 1; break; case PTY_NG: fprintf(stderr, "%s\n", handshake.msg); done = -1; break; case PTY_WS: handshake.row = row; handshake.col = col; handshake.status = PTY_WS; send_handshake_message(fProcessID, handshake); break; } } if (done <= 0) return B_ERROR; fFd = master; return B_OK; }
int main(int argc, char *argv[]) { log_options_t logopt = LOG_OPTS_STDERR_ONLY; job_desc_msg_t desc; resource_allocation_response_msg_t *alloc; time_t before, after; allocation_msg_thread_t *msg_thr; char **env = NULL, *cluster_name; int status = 0; int retries = 0; pid_t pid = getpid(); pid_t tpgid = 0; pid_t rc_pid = 0; int i, rc = 0; static char *msg = "Slurm job queue full, sleeping and retrying."; slurm_allocation_callbacks_t callbacks; slurm_conf_init(NULL); log_init(xbasename(argv[0]), logopt, 0, NULL); _set_exit_code(); if (spank_init_allocator() < 0) { error("Failed to initialize plugin stack"); exit(error_exit); } /* Be sure to call spank_fini when salloc exits */ if (atexit((void (*) (void)) spank_fini) < 0) error("Failed to register atexit handler for plugins: %m"); if (initialize_and_process_args(argc, argv) < 0) { error("salloc parameter parsing"); exit(error_exit); } /* reinit log with new verbosity (if changed by command line) */ if (opt.verbose || opt.quiet) { logopt.stderr_level += opt.verbose; logopt.stderr_level -= opt.quiet; logopt.prefix_level = 1; log_alter(logopt, 0, NULL); } if (spank_init_post_opt() < 0) { error("Plugin stack post-option processing failed"); exit(error_exit); } _set_spank_env(); _set_submit_dir_env(); if (opt.cwd && chdir(opt.cwd)) { error("chdir(%s): %m", opt.cwd); exit(error_exit); } if (opt.get_user_env_time >= 0) { bool no_env_cache = false; char *sched_params; char *user = uid_to_string(opt.uid); if (xstrcmp(user, "nobody") == 0) { error("Invalid user id %u: %m", (uint32_t)opt.uid); exit(error_exit); } sched_params = slurm_get_sched_params(); no_env_cache = (sched_params && strstr(sched_params, "no_env_cache")); xfree(sched_params); env = env_array_user_default(user, opt.get_user_env_time, opt.get_user_env_mode, no_env_cache); xfree(user); if (env == NULL) exit(error_exit); /* error already logged */ _set_rlimits(env); } /* * Job control for interactive salloc sessions: only if ... * * a) input is from a terminal (stdin has valid termios attributes), * b) controlling terminal exists (non-negative tpgid), * c) salloc is not run in allocation-only (--no-shell) mode, * NOTE: d and e below are configuration dependent * d) salloc runs in its own process group (true in interactive * shells that support job control), * e) salloc has been configured at compile-time to support background * execution and is not currently in the background process group. */ if (tcgetattr(STDIN_FILENO, &saved_tty_attributes) < 0) { /* * Test existence of controlling terminal (tpgid > 0) * after first making sure stdin is not redirected. */ } else if ((tpgid = tcgetpgrp(STDIN_FILENO)) < 0) { #ifdef HAVE_ALPS_CRAY verbose("no controlling terminal"); #else if (!opt.no_shell) { error("no controlling terminal: please set --no-shell"); exit(error_exit); } #endif #ifdef SALLOC_RUN_FOREGROUND } else if ((!opt.no_shell) && (pid == getpgrp())) { if (tpgid == pid) is_interactive = true; while (tcgetpgrp(STDIN_FILENO) != pid) { if (!is_interactive) { error("Waiting for program to be placed in " "the foreground"); is_interactive = true; } killpg(pid, SIGTTIN); } } #else } else if ((!opt.no_shell) && (getpgrp() == tcgetpgrp(STDIN_FILENO))) {
int spawn(char *program, char *argv[], int sin, int sout, int serr, int search, char *envp[], char *pty_name, int wait) { int pid = fork(); int fd; sigset_t sset; if (pid != 0) return pid; /* Put us in our own process group, but only if we need not * share stdin with our parent. In the latter case we claim * control of the terminal. */ if (sin >= 0) { #if defined(LISP_FEATURE_HPUX) || defined(LISP_FEATURE_OPENBSD) setsid(); #elif defined(LISP_FEATURE_DARWIN) setpgid(0, getpid()); #elif defined(SVR4) || defined(__linux__) || defined(__osf__) setpgrp(); #else setpgrp(0, getpid()); #endif } else { tcsetpgrp(0, getpgrp()); } /* unblock signals */ sigemptyset(&sset); sigprocmask(SIG_SETMASK, &sset, NULL); /* If we are supposed to be part of some other pty, go for it. */ if (pty_name) set_pty(pty_name); else { /* Set up stdin, stdout, and stderr */ if (sin >= 0) dup2(sin, 0); if (sout >= 0) dup2(sout, 1); if (serr >= 0) dup2(serr, 2); } /* Close all other fds. */ #ifdef SVR4 for (fd = sysconf(_SC_OPEN_MAX)-1; fd >= 3; fd--) close(fd); #else for (fd = getdtablesize()-1; fd >= 3; fd--) close(fd); #endif environ = envp; /* Exec the program. */ if (search) execvp(program, argv); else execv(program, argv); exit (1); }
/* * Terminal I/O */ void initterm(void) { char buf[TBUFSIZ]; static char clearbuf[TBUFSIZ]; char *clearptr, *padstr; char *term; int tgrp; struct winsize win; retry: if (!(no_tty = tcgetattr(STDOUT_FILENO, &otty))) { docrterase = (otty.c_cc[VERASE] != _POSIX_VDISABLE); docrtkill = (otty.c_cc[VKILL] != _POSIX_VDISABLE); /* * Wait until we're in the foreground before we save the * the terminal modes. */ if ((tgrp = tcgetpgrp(STDOUT_FILENO)) < 0) { perror("tcgetpgrp"); exit(1); } if (tgrp != getpgrp()) { kill(0, SIGTTOU); goto retry; } if ((term = getenv("TERM")) == 0 || tgetent(buf, term) <= 0) { dumb++; ul_opt = 0; } else { if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &win) < 0) { Lpp = tgetnum("li"); Mcol = tgetnum("co"); } else { if ((Lpp = win.ws_row) == 0) Lpp = tgetnum("li"); if ((Mcol = win.ws_col) == 0) Mcol = tgetnum("co"); } if (Lpp <= 0 || tgetflag("hc")) { hard++; /* Hard copy terminal */ Lpp = 24; } if (tgetflag("xn")) { /* Eat newline at last column + 1 */ eatnl++; } if (Mcol <= 0) Mcol = 80; if (strcmp(__progname, "page") == 0 || (!hard && tgetflag("ns"))) noscroll++; Wrap = tgetflag("am"); bad_so = tgetflag ("xs"); clearptr = clearbuf; eraseln = tgetstr("ce", &clearptr); Clear = tgetstr("cl", &clearptr); Senter = tgetstr("so", &clearptr); Sexit = tgetstr("se", &clearptr); if ((soglitch = tgetnum("sg")) < 0) soglitch = 0; /* * Setup for underlining. Some terminals don't need it, * others have start/stop sequences, still others have * an underline char sequence which is assumed to move * the cursor forward one character. If underline seq * isn't available, settle for standout sequence. */ if (tgetflag("ul") || tgetflag("os")) ul_opt = 0; if ((chUL = tgetstr("uc", &clearptr)) == NULL) chUL = ""; if (((ULenter = tgetstr("us", &clearptr)) == NULL || (ULexit = tgetstr("ue", &clearptr)) == NULL) && !*chUL) { if ((ULenter = Senter) == NULL || (ULexit = Sexit) == NULL) { ULenter = ""; ULexit = ""; } else ulglitch = soglitch; } else { if ((ulglitch = tgetnum("ug")) < 0) ulglitch = 0; } if ((padstr = tgetstr("pc", &clearptr))) PC = *padstr; Home = tgetstr("ho", &clearptr); if (Home == 0 || *Home == '\0') { cursorm = tgetstr("cm", &clearptr); if (cursorm != NULL) { strlcpy(cursorhome, tgoto(cursorm, 0, 0), sizeof(cursorhome)); Home = cursorhome; } } EodClr = tgetstr("cd", &clearptr); if ((chBS = tgetstr("bc", &clearptr)) == NULL) chBS = "\b"; if (tgetstr("te", &clearptr) != NULL && tgetstr("ti", &clearptr) != NULL) altscr = 1; } if ((shell = getenv("SHELL")) == NULL) shell = _PATH_BSHELL; } no_intty = !isatty(STDIN_FILENO); tcgetattr(STDERR_FILENO, &otty); slow_tty = cfgetospeed(&otty) < B1200; hardtabs = !(otty.c_oflag & OXTABS); ntty = otty; if (!no_tty) { ntty.c_lflag &= ~(ICANON|ECHO); ntty.c_cc[VMIN] = 1; /* read at least 1 char */ ntty.c_cc[VTIME] = 0; /* no timeout */ } }
int main(int argc, char *argv[], char *envp[]) { extern int mdb_kvm_is_compressed_dump(mdb_io_t *); mdb_tgt_ctor_f *tgt_ctor = NULL; const char **tgt_argv = alloca(argc * sizeof (char *)); int tgt_argc = 0; mdb_tgt_t *tgt; char object[MAXPATHLEN], execname[MAXPATHLEN]; mdb_io_t *in_io, *out_io, *err_io, *null_io; struct termios tios; int status, c; char *p; const char *Iflag = NULL, *Lflag = NULL, *Vflag = NULL, *pidarg = NULL; int fflag = 0, Kflag = 0, Rflag = 0, Sflag = 0, Oflag = 0, Uflag = 0; int ttylike; int longmode = 0; stack_t sigstack; if (realpath(getexecname(), execname) == NULL) { (void) strncpy(execname, argv[0], MAXPATHLEN); execname[MAXPATHLEN - 1] = '\0'; } mdb_create(execname, argv[0]); bzero(tgt_argv, argc * sizeof (char *)); argv[0] = (char *)mdb.m_pname; _mdb_self_fd = open("/proc/self/as", O_RDONLY); mdb.m_env = envp; out_io = mdb_fdio_create(STDOUT_FILENO); mdb.m_out = mdb_iob_create(out_io, MDB_IOB_WRONLY); err_io = mdb_fdio_create(STDERR_FILENO); mdb.m_err = mdb_iob_create(err_io, MDB_IOB_WRONLY); mdb_iob_clrflags(mdb.m_err, MDB_IOB_AUTOWRAP); null_io = mdb_nullio_create(); mdb.m_null = mdb_iob_create(null_io, MDB_IOB_WRONLY); in_io = mdb_fdio_create(STDIN_FILENO); if ((mdb.m_termtype = getenv("TERM")) != NULL) { mdb.m_termtype = strdup(mdb.m_termtype); mdb.m_flags |= MDB_FL_TERMGUESS; } mdb.m_term = NULL; mdb_dmode(mdb_dstr2mode(getenv("MDB_DEBUG"))); mdb.m_pgid = getpgrp(); if (getenv("_MDB_EXEC") != NULL) mdb.m_flags |= MDB_FL_EXEC; /* * Setup an alternate signal stack. When tearing down pipelines in * terminate(), we may have to destroy the stack of the context in * which we are currently executing the signal handler. */ sigstack.ss_sp = mmap(NULL, SIGSTKSZ, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); if (sigstack.ss_sp == MAP_FAILED) die("could not allocate signal stack"); sigstack.ss_size = SIGSTKSZ; sigstack.ss_flags = 0; if (sigaltstack(&sigstack, NULL) != 0) die("could not set signal stack"); (void) mdb_signal_sethandler(SIGPIPE, SIG_IGN, NULL); (void) mdb_signal_sethandler(SIGQUIT, SIG_IGN, NULL); (void) mdb_signal_sethandler(SIGILL, flt_handler, NULL); (void) mdb_signal_sethandler(SIGTRAP, flt_handler, NULL); (void) mdb_signal_sethandler(SIGIOT, flt_handler, NULL); (void) mdb_signal_sethandler(SIGEMT, flt_handler, NULL); (void) mdb_signal_sethandler(SIGFPE, flt_handler, NULL); (void) mdb_signal_sethandler(SIGBUS, flt_handler, NULL); (void) mdb_signal_sethandler(SIGSEGV, flt_handler, NULL); (void) mdb_signal_sethandler(SIGHUP, (mdb_signal_f *)terminate, NULL); (void) mdb_signal_sethandler(SIGTERM, (mdb_signal_f *)terminate, NULL); for (mdb.m_rdvers = RD_VERSION; mdb.m_rdvers > 0; mdb.m_rdvers--) { if (rd_init(mdb.m_rdvers) == RD_OK) break; } for (mdb.m_ctfvers = CTF_VERSION; mdb.m_ctfvers > 0; mdb.m_ctfvers--) { if (ctf_version(mdb.m_ctfvers) != -1) break; } if ((p = getenv("HISTSIZE")) != NULL && strisnum(p)) { mdb.m_histlen = strtoi(p); if (mdb.m_histlen < 1) mdb.m_histlen = 1; } while (optind < argc) { while ((c = getopt(argc, argv, "fkmo:p:s:uwyACD:FI:KL:MOP:R:SUV:W")) != (int)EOF) { switch (c) { case 'f': fflag++; tgt_ctor = mdb_rawfile_tgt_create; break; case 'k': tgt_ctor = mdb_kvm_tgt_create; break; case 'm': mdb.m_tgtflags |= MDB_TGT_F_NOLOAD; mdb.m_tgtflags &= ~MDB_TGT_F_PRELOAD; break; case 'o': if (!mdb_set_options(optarg, TRUE)) terminate(2); break; case 'p': tgt_ctor = mdb_proc_tgt_create; pidarg = optarg; break; case 's': if (!strisnum(optarg)) { warn("expected integer following -s\n"); terminate(2); } mdb.m_symdist = (size_t)(uint_t)strtoi(optarg); break; case 'u': tgt_ctor = mdb_proc_tgt_create; break; case 'w': mdb.m_tgtflags |= MDB_TGT_F_RDWR; break; case 'y': mdb.m_flags |= MDB_FL_USECUP; break; case 'A': (void) mdb_set_options("nomods", TRUE); break; case 'C': (void) mdb_set_options("noctf", TRUE); break; case 'D': mdb_dmode(mdb_dstr2mode(optarg)); break; case 'F': mdb.m_tgtflags |= MDB_TGT_F_FORCE; break; case 'I': Iflag = optarg; break; case 'L': Lflag = optarg; break; case 'K': Kflag++; break; case 'M': mdb.m_tgtflags |= MDB_TGT_F_PRELOAD; mdb.m_tgtflags &= ~MDB_TGT_F_NOLOAD; break; case 'O': Oflag++; break; case 'P': if (!mdb_set_prompt(optarg)) terminate(2); break; case 'R': (void) strncpy(mdb.m_root, optarg, MAXPATHLEN); mdb.m_root[MAXPATHLEN - 1] = '\0'; Rflag++; break; case 'S': Sflag++; break; case 'U': Uflag++; break; case 'V': Vflag = optarg; break; case 'W': mdb.m_tgtflags |= MDB_TGT_F_ALLOWIO; break; case '?': if (optopt == '?') usage(0); /* FALLTHROUGH */ default: usage(2); } } if (optind < argc) { const char *arg = argv[optind++]; if (arg[0] == '+' && strlen(arg) == 2) { if (arg[1] != 'o') { warn("illegal option -- %s\n", arg); terminate(2); } if (optind >= argc) { warn("option requires an argument -- " "%s\n", arg); terminate(2); } if (!mdb_set_options(argv[optind++], FALSE)) terminate(2); } else tgt_argv[tgt_argc++] = arg; } } if (rd_ctl(RD_CTL_SET_HELPPATH, (void *)mdb.m_root) != RD_OK) { warn("cannot set librtld_db helper path to %s\n", mdb.m_root); terminate(2); } if (mdb.m_debug & MDB_DBG_HELP) terminate(0); /* Quit here if we've printed out the tokens */ if (Iflag != NULL && strchr(Iflag, ';') != NULL) { warn("macro path cannot contain semicolons\n"); terminate(2); } if (Lflag != NULL && strchr(Lflag, ';') != NULL) { warn("module path cannot contain semicolons\n"); terminate(2); } if (Kflag || Uflag) { char *nm; if (tgt_ctor != NULL || Iflag != NULL) { warn("neither -f, -k, -p, -u, nor -I " "may be used with -K\n"); usage(2); } if (Lflag != NULL) mdb_set_lpath(Lflag); if ((nm = ttyname(STDIN_FILENO)) == NULL || strcmp(nm, "/dev/console") != 0) { /* * Due to the consequences of typing mdb -K instead of * mdb -k on a tty other than /dev/console, we require * -F when starting kmdb from a tty other than * /dev/console. */ if (!(mdb.m_tgtflags & MDB_TGT_F_FORCE)) { die("-F must also be supplied to start kmdb " "from non-console tty\n"); } if (mdb.m_termtype == NULL || (mdb.m_flags & MDB_FL_TERMGUESS)) { if (mdb.m_termtype != NULL) strfree(mdb.m_termtype); if ((mdb.m_termtype = mdb_scf_console_term()) != NULL) mdb.m_flags |= MDB_FL_TERMGUESS; } } else { /* * When on console, $TERM (if set) takes precedence over * the SMF setting. */ if (mdb.m_termtype == NULL && (mdb.m_termtype = mdb_scf_console_term()) != NULL) mdb.m_flags |= MDB_FL_TERMGUESS; } control_kmdb(Kflag); terminate(0); /*NOTREACHED*/ } /* * If standard input appears to have tty attributes, attempt to * initialize a terminal i/o backend on top of stdin and stdout. */ ttylike = (IOP_CTL(in_io, TCGETS, &tios) == 0); if (ttylike) { if ((mdb.m_term = mdb_termio_create(mdb.m_termtype, in_io, out_io)) == NULL) { if (!(mdb.m_flags & MDB_FL_EXEC)) { warn("term init failed: command-line editing " "and prompt will not be available\n"); } } else { in_io = mdb.m_term; } } mdb.m_in = mdb_iob_create(in_io, MDB_IOB_RDONLY); if (mdb.m_term != NULL) { mdb_iob_setpager(mdb.m_out, mdb.m_term); if (mdb.m_flags & MDB_FL_PAGER) mdb_iob_setflags(mdb.m_out, MDB_IOB_PGENABLE); else mdb_iob_clrflags(mdb.m_out, MDB_IOB_PGENABLE); } else if (ttylike) mdb_iob_setflags(mdb.m_in, MDB_IOB_TTYLIKE); else mdb_iob_setbuf(mdb.m_in, mdb_alloc(1, UM_SLEEP), 1); mdb_pservice_init(); mdb_lex_reset(); if ((mdb.m_shell = getenv("SHELL")) == NULL) mdb.m_shell = "/bin/sh"; /* * If the debugger state is to be inherited from a previous instance, * restore it now prior to path evaluation so that %R is updated. */ if ((p = getenv(MDB_CONFIG_ENV_VAR)) != NULL) { mdb_set_config(p); (void) unsetenv(MDB_CONFIG_ENV_VAR); } /* * Path evaluation part 1: Create the initial module path to allow * the target constructor to load a support module. Then expand * any command-line arguments that modify the paths. */ if (Iflag != NULL) mdb_set_ipath(Iflag); else mdb_set_ipath(MDB_DEF_IPATH); if (Lflag != NULL) mdb_set_lpath(Lflag); else mdb_set_lpath(MDB_DEF_LPATH); if (mdb_get_prompt() == NULL && !(mdb.m_flags & MDB_FL_ADB)) (void) mdb_set_prompt(MDB_DEF_PROMPT); if (tgt_ctor == mdb_kvm_tgt_create) { if (pidarg != NULL) { warn("-p and -k options are mutually exclusive\n"); terminate(2); } if (tgt_argc == 0) tgt_argv[tgt_argc++] = "/dev/ksyms"; if (tgt_argc == 1 && strisnum(tgt_argv[0]) == 0) { if (mdb.m_tgtflags & MDB_TGT_F_ALLOWIO) tgt_argv[tgt_argc++] = "/dev/allkmem"; else tgt_argv[tgt_argc++] = "/dev/kmem"; } } if (pidarg != NULL) { if (tgt_argc != 0) { warn("-p may not be used with other arguments\n"); terminate(2); } if (proc_arg_psinfo(pidarg, PR_ARG_PIDS, NULL, &status) == -1) { die("cannot attach to %s: %s\n", pidarg, Pgrab_error(status)); } if (strchr(pidarg, '/') != NULL) (void) mdb_iob_snprintf(object, MAXPATHLEN, "%s/object/a.out", pidarg); else (void) mdb_iob_snprintf(object, MAXPATHLEN, "/proc/%s/object/a.out", pidarg); tgt_argv[tgt_argc++] = object; tgt_argv[tgt_argc++] = pidarg; } /* * Find the first argument that is not a special "-" token. If one is * found, we will examine this file and make some inferences below. */ for (c = 0; c < tgt_argc && strcmp(tgt_argv[c], "-") == 0; c++) continue; if (c < tgt_argc) { Elf32_Ehdr ehdr; mdb_io_t *io; /* * If special "-" tokens preceded an argument, shift the entire * argument list to the left to remove the leading "-" args. */ if (c > 0) { bcopy(&tgt_argv[c], tgt_argv, sizeof (const char *) * (tgt_argc - c)); tgt_argc -= c; } if (fflag) goto tcreate; /* skip re-exec and just create target */ /* * If we just have an object file name, and that file doesn't * exist, and it's a string of digits, infer it to be a * sequence number referring to a pair of crash dump files. */ if (tgt_argc == 1 && access(tgt_argv[0], F_OK) == -1 && strisnum(tgt_argv[0])) { size_t len = strlen(tgt_argv[0]) + 8; const char *object = tgt_argv[0]; tgt_argv[0] = mdb_alloc(len, UM_SLEEP); tgt_argv[1] = mdb_alloc(len, UM_SLEEP); (void) strcpy((char *)tgt_argv[0], "unix."); (void) strcat((char *)tgt_argv[0], object); (void) strcpy((char *)tgt_argv[1], "vmcore."); (void) strcat((char *)tgt_argv[1], object); if (access(tgt_argv[0], F_OK) == -1 && access(tgt_argv[1], F_OK) == -1) { (void) strcpy((char *)tgt_argv[1], "vmdump."); (void) strcat((char *)tgt_argv[1], object); if (access(tgt_argv[1], F_OK) == 0) { mdb_iob_printf(mdb.m_err, "cannot open compressed dump; " "decompress using savecore -f %s\n", tgt_argv[1]); terminate(0); } } tgt_argc = 2; } /* * We need to open the object file in order to determine its * ELF class and potentially re-exec ourself. */ if ((io = mdb_fdio_create_path(NULL, tgt_argv[0], O_RDONLY, 0)) == NULL) die("failed to open %s", tgt_argv[0]); /* * Check for a single vmdump.N compressed dump file, * and give a helpful message. */ if (tgt_argc == 1) { if (mdb_kvm_is_compressed_dump(io)) { mdb_iob_printf(mdb.m_err, "cannot open compressed dump; " "decompress using savecore -f %s\n", tgt_argv[0]); terminate(0); } } /* * If the target is unknown or is not the rawfile target, do * a gelf_check to determine if the file is an ELF file. If * it is not and the target is unknown, use the rawfile tgt. * Otherwise an ELF-based target is needed, so we must abort. */ if (mdb_gelf_check(io, &ehdr, ET_NONE) == -1) { if (tgt_ctor != NULL) { (void) mdb_gelf_check(io, &ehdr, ET_EXEC); mdb_io_destroy(io); terminate(1); } else tgt_ctor = mdb_rawfile_tgt_create; } mdb_io_destroy(io); if (identify_xvm_file(tgt_argv[0], &longmode) == 1) { #ifdef _LP64 if (!longmode) goto reexec; #else if (longmode) goto reexec; #endif tgt_ctor = mdb_kvm_tgt_create; goto tcreate; } /* * The object file turned out to be a user core file (ET_CORE), * and no other arguments were specified, swap 0 and 1. The * proc target will infer the executable for us. */ if (ehdr.e_type == ET_CORE) { tgt_argv[tgt_argc++] = tgt_argv[0]; tgt_argv[0] = NULL; tgt_ctor = mdb_proc_tgt_create; } /* * If tgt_argv[1] is filled in, open it up and determine if it * is a vmcore file. If it is, gelf_check will fail and we * set tgt_ctor to 'kvm'; otherwise we use the default. */ if (tgt_argc > 1 && strcmp(tgt_argv[1], "-") != 0 && tgt_argv[0] != NULL && pidarg == NULL) { Elf32_Ehdr chdr; if (access(tgt_argv[1], F_OK) == -1) die("failed to access %s", tgt_argv[1]); /* *.N case: drop vmdump.N from the list */ if (tgt_argc == 3) { if ((io = mdb_fdio_create_path(NULL, tgt_argv[2], O_RDONLY, 0)) == NULL) die("failed to open %s", tgt_argv[2]); if (mdb_kvm_is_compressed_dump(io)) tgt_argv[--tgt_argc] = NULL; mdb_io_destroy(io); } if ((io = mdb_fdio_create_path(NULL, tgt_argv[1], O_RDONLY, 0)) == NULL) die("failed to open %s", tgt_argv[1]); if (mdb_gelf_check(io, &chdr, ET_NONE) == -1) tgt_ctor = mdb_kvm_tgt_create; mdb_io_destroy(io); } /* * At this point, we've read the ELF header for either an * object file or core into ehdr. If the class does not match * ours, attempt to exec the mdb of the appropriate class. */ #ifdef _LP64 if (ehdr.e_ident[EI_CLASS] == ELFCLASS32) goto reexec; #else if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) goto reexec; #endif } tcreate: if (tgt_ctor == NULL) tgt_ctor = mdb_proc_tgt_create; tgt = mdb_tgt_create(tgt_ctor, mdb.m_tgtflags, tgt_argc, tgt_argv); if (tgt == NULL) { if (errno == EINVAL) usage(2); /* target can return EINVAL to get usage */ if (errno == EMDB_TGT) terminate(1); /* target already printed error msg */ die("failed to initialize target"); } mdb_tgt_activate(tgt); mdb_create_loadable_disasms(); if (Vflag != NULL && mdb_dis_select(Vflag) == -1) warn("invalid disassembler mode -- %s\n", Vflag); if (Rflag && mdb.m_term != NULL) warn("Using proto area %s\n", mdb.m_root); /* * If the target was successfully constructed and -O was specified, * we now attempt to enter piggy-mode for debugging jurassic problems. */ if (Oflag) { pcinfo_t pci; (void) strcpy(pci.pc_clname, "RT"); if (priocntl(P_LWPID, P_MYID, PC_GETCID, (caddr_t)&pci) != -1) { pcparms_t pcp; rtparms_t *rtp = (rtparms_t *)pcp.pc_clparms; rtp->rt_pri = 35; rtp->rt_tqsecs = 0; rtp->rt_tqnsecs = RT_TQDEF; pcp.pc_cid = pci.pc_cid; if (priocntl(P_LWPID, P_MYID, PC_SETPARMS, (caddr_t)&pcp) == -1) { warn("failed to set RT parameters"); Oflag = 0; } } else { warn("failed to get RT class id"); Oflag = 0; } if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) { warn("failed to lock address space"); Oflag = 0; } if (Oflag) mdb_printf("%s: oink, oink!\n", mdb.m_pname); } /* * Path evaluation part 2: Re-evaluate the path now that the target * is ready (and thus we have access to the real platform string). * Do this before reading ~/.mdbrc to allow path modifications prior * to performing module auto-loading. */ mdb_set_ipath(mdb.m_ipathstr); mdb_set_lpath(mdb.m_lpathstr); if (!Sflag && (p = getenv("HOME")) != NULL) { char rcpath[MAXPATHLEN]; mdb_io_t *rc_io; int fd; (void) mdb_iob_snprintf(rcpath, MAXPATHLEN, "%s/.mdbrc", p); fd = open64(rcpath, O_RDONLY); if (fd >= 0 && (rc_io = mdb_fdio_create_named(fd, rcpath))) { mdb_iob_t *iob = mdb_iob_create(rc_io, MDB_IOB_RDONLY); mdb_iob_t *old = mdb.m_in; mdb.m_in = iob; (void) mdb_run(); mdb.m_in = old; } } if (!(mdb.m_flags & MDB_FL_NOMODS)) mdb_module_load_all(0); (void) mdb_signal_sethandler(SIGINT, int_handler, NULL); while ((status = mdb_run()) == MDB_ERR_ABORT || status == MDB_ERR_OUTPUT) { /* * If a write failed on stdout, give up. A more informative * error message will already have been printed by mdb_run(). */ if (status == MDB_ERR_OUTPUT && mdb_iob_getflags(mdb.m_out) & MDB_IOB_ERR) { mdb_warn("write to stdout failed, exiting\n"); break; } continue; } terminate((status == MDB_ERR_QUIT || status == 0) ? 0 : 1); /*NOTREACHED*/ return (0); reexec: if ((p = strrchr(execname, '/')) == NULL) die("cannot determine absolute pathname\n"); #ifdef _LP64 #ifdef __sparc (void) strcpy(p, "/../sparcv7/"); #else (void) strcpy(p, "/../i86/"); #endif #else #ifdef __sparc (void) strcpy(p, "/../sparcv9/"); #else (void) strcpy(p, "/../amd64/"); #endif #endif (void) strcat(p, mdb.m_pname); if (mdb.m_term != NULL) (void) IOP_CTL(in_io, TCSETSW, &tios); (void) putenv("_MDB_EXEC=1"); (void) execv(execname, argv); /* * If execv fails, suppress ENOEXEC. Experience shows the most common * reason is that the machine is booted under a 32-bit kernel, in which * case it is clearer to only print the message below. */ if (errno != ENOEXEC) warn("failed to exec %s", execname); #ifdef _LP64 die("64-bit %s cannot debug 32-bit program %s\n", mdb.m_pname, tgt_argv[0] ? tgt_argv[0] : tgt_argv[1]); #else die("32-bit %s cannot debug 64-bit program %s\n", mdb.m_pname, tgt_argv[0] ? tgt_argv[0] : tgt_argv[1]); #endif goto tcreate; }
int main(int argc, char **argv) { int i, n; char **origenv; char **newenv; char *cwd; FILE *log = fopen(abs_builddir "/commandhelper.log", "w"); if (!log) goto error; for (i = 1 ; i < argc ; i++) { fprintf(log, "ARG:%s\n", argv[i]); } origenv = environ; n = 0; while (*origenv != NULL) { n++; origenv++; } if (VIR_ALLOC_N(newenv, n) < 0) { exit(EXIT_FAILURE); } origenv = environ; n = i = 0; while (*origenv != NULL) { newenv[i++] = *origenv; n++; origenv++; } qsort(newenv, n, sizeof(newenv[0]), envsort); for (i = 0 ; i < n ; i++) { /* Ignore the variables used to instruct the loader into * behaving differently, as they could throw the tests off. */ if (!STRPREFIX(newenv[i], "LD_")) fprintf(log, "ENV:%s\n", newenv[i]); } for (i = 0 ; i < sysconf(_SC_OPEN_MAX) ; i++) { int f; int closed; if (i == fileno(log)) continue; closed = fcntl(i, F_GETFD, &f) == -1 && errno == EBADF; if (!closed) fprintf(log, "FD:%d\n", i); } fprintf(log, "DAEMON:%s\n", getpgrp() == getsid(0) ? "yes" : "no"); if (!(cwd = getcwd(NULL, 0))) return EXIT_FAILURE; if (strlen(cwd) > strlen(".../commanddata") && STREQ(cwd + strlen(cwd) - strlen("/commanddata"), "/commanddata")) strcpy(cwd, ".../commanddata"); fprintf(log, "CWD:%s\n", cwd); VIR_FREE(cwd); VIR_FORCE_FCLOSE(log); char buf[1024]; ssize_t got; fprintf(stdout, "BEGIN STDOUT\n"); fflush(stdout); fprintf(stderr, "BEGIN STDERR\n"); fflush(stderr); for (;;) { got = read(STDIN_FILENO, buf, sizeof(buf)); if (got < 0) goto error; if (got == 0) break; if (safewrite(STDOUT_FILENO, buf, got) != got) goto error; if (safewrite(STDERR_FILENO, buf, got) != got) goto error; } fprintf(stdout, "END STDOUT\n"); fflush(stdout); fprintf(stderr, "END STDERR\n"); fflush(stderr); return EXIT_SUCCESS; error: return EXIT_FAILURE; }
/* * stress_ptrace() * stress ptracing */ static int stress_ptrace(const args_t *args) { pid_t pid; pid = fork(); if (pid < 0) { pr_fail_dbg("fork"); return EXIT_FAILURE; } else if (pid == 0) { (void)setpgid(0, g_pgrp); stress_parent_died_alarm(); /* * Child to be traced, we abort if we detect * we are already being traced by someone else * as this makes life way too complex */ if (ptrace(PTRACE_TRACEME) != 0) { pr_fail("%s: ptrace child being traced " "already, aborting\n", args->name); _exit(0); } /* Wait for parent to start tracing me */ (void)kill(getpid(), SIGSTOP); /* * A simple mix of system calls */ while (g_keep_stressing_flag) { pid_t pidtmp; gid_t gidtmp; uid_t uidtmp; time_t ttmp; pidtmp = getppid(); (void)pidtmp; #if defined(HAVE_GETPGRP) pidtmp = getpgrp(); (void)pidtmp; #endif gidtmp = getgid(); (void)gidtmp; gidtmp = getegid(); (void)gidtmp; uidtmp = getuid(); (void)uidtmp; uidtmp = geteuid(); (void)uidtmp; ttmp = time(NULL); (void)ttmp; } _exit(0); } else { /* Parent to do the tracing */ int status; (void)setpgid(pid, g_pgrp); if (shim_waitpid(pid, &status, 0) < 0) { if (errno != EINTR) { pr_fail_dbg("waitpid"); return EXIT_FAILURE; } return EXIT_SUCCESS; } if (ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_TRACESYSGOOD) < 0) { pr_fail_dbg("ptrace"); return EXIT_FAILURE; } do { /* * We do two of the following per syscall, * one at the start, and one at the end to catch * the return. In this stressor we don't really * care which is which, we just care about counting * them */ if (stress_syscall_wait(args, pid)) break; inc_counter(args); } while (keep_stressing()); /* Terminate child */ (void)kill(pid, SIGKILL); if (shim_waitpid(pid, &status, 0) < 0) pr_fail_dbg("waitpid"); } return EXIT_SUCCESS; }
int physical2iov(struct physical *p, struct iovec *iov, int *niov, int maxiov, int *auxfd, int *nauxfd) { struct device *h; int sz; h = NULL; if (p) { hdlc_StopTimer(&p->hdlc); lqr_StopTimer(p); timer_Stop(&p->link.lcp.fsm.FsmTimer); timer_Stop(&p->link.ccp.fsm.FsmTimer); timer_Stop(&p->link.lcp.fsm.OpenTimer); timer_Stop(&p->link.ccp.fsm.OpenTimer); timer_Stop(&p->link.lcp.fsm.StoppedTimer); timer_Stop(&p->link.ccp.fsm.StoppedTimer); if (p->handler) { h = p->handler; p->handler = (struct device *)(long)p->handler->type; } if (Enabled(p->dl->bundle, OPT_KEEPSESSION) || tcgetpgrp(p->fd) == getpgrp()) p->session_owner = getpid(); /* So I'll eventually get HUP'd */ else p->session_owner = (pid_t)-1; timer_Stop(&p->link.stats.total.Timer); } if (*niov + 2 >= maxiov) { log_Printf(LogERROR, "physical2iov: No room for physical + throughput" " + device !\n"); if (p) free(p); return -1; } iov[*niov].iov_base = (void *)p; iov[*niov].iov_len = sizeof *p; (*niov)++; iov[*niov].iov_base = p ? (void *)p->link.stats.total.in.SampleOctets : NULL; iov[*niov].iov_len = SAMPLE_PERIOD * sizeof(long long); (*niov)++; iov[*niov].iov_base = p ? (void *)p->link.stats.total.out.SampleOctets : NULL; iov[*niov].iov_len = SAMPLE_PERIOD * sizeof(long long); (*niov)++; sz = physical_MaxDeviceSize(); if (p) { if (h && h->device2iov) (*h->device2iov)(h, iov, niov, maxiov, auxfd, nauxfd); else { iov[*niov].iov_base = malloc(sz); if (h) memcpy(iov[*niov].iov_base, h, sizeof *h); iov[*niov].iov_len = sz; (*niov)++; } } else { iov[*niov].iov_base = NULL; iov[*niov].iov_len = sz; (*niov)++; } return p ? p->fd : 0; }
int os_getpgrp(void) { return getpgrp(); }