/* * Open the specified slave side of the pty, * making sure that we have a clean tty. */ static int cleanopen(char *lyne) { register int t; /* * Make sure that other people can't open the * slave side of the connection. */ chown(lyne, 0, 0); chmod(lyne, 0600); #ifndef NO_REVOKE revoke(lyne); #endif t = open(lyne, O_RDWR|O_NOCTTY); if (t < 0) return(-1); /* * Hangup anybody else using this ttyp, then reopen it for * ourselves. */ # if !defined(__linux__) /* this looks buggy to me, our ctty is really a pty at this point */ signal(SIGHUP, SIG_IGN); vhangup(); signal(SIGHUP, SIG_DFL); t = open(lyne, O_RDWR|O_NOCTTY); if (t < 0) return(-1); # endif return(t); }
int start_session(int vty, int argc, char **argv) { int fd; char *t; close(0); close(1); close(2); revoke(ttys[vty].tty); fd=open(ttys[vty].tty,O_RDWR); dup2(fd,0); dup2(fd,1); dup2(fd,2); if(fd>2) close(fd); login_tty(fd); setpgid(0,getpid()); putenv("TERM=xterm"); putenv("HOME=/"); putenv("PATH=/stand:/bin:/usr/bin:/sbin:."); signal(SIGHUP,SIG_DFL); signal(SIGINT,SIG_DFL); signal(SIGQUIT,SIG_DFL); signal(SIGTERM,SIG_DFL); chdir("/"); t=(char *)(rindex(ttys[vty].tty,'/')+1); printf("\n\n\nStarting session on %s.\n",t); ttys[vty].func(argc,argv); _exit(0); }
/* * Start a session and allocate a controlling terminal. * Only called by children of init after forking. */ static void open_console(void) { int fd; /* * Try to open /dev/console. Open the device with O_NONBLOCK to * prevent potential blocking on a carrier. */ revoke(_PATH_CONSOLE); if ((fd = open(_PATH_CONSOLE, O_RDWR | O_NONBLOCK)) != -1) { (void)fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) & ~O_NONBLOCK); if (login_tty(fd) == 0) return; close(fd); } /* No luck. Log output to file if possible. */ if ((fd = open(_PATH_DEVNULL, O_RDWR)) == -1) { stall("cannot open null device."); _exit(1); } if (fd != STDIN_FILENO) { dup2(fd, STDIN_FILENO); close(fd); } fd = open(_PATH_INITLOG, O_WRONLY | O_APPEND | O_CREAT, 0644); if (fd == -1) dup2(STDIN_FILENO, STDOUT_FILENO); else if (fd != STDOUT_FILENO) { dup2(fd, STDOUT_FILENO); close(fd); } dup2(STDOUT_FILENO, STDERR_FILENO); }
int cleanopen(char *line) { int t; if (ptyslavefd != -1) return ptyslavefd; #ifdef STREAMSPTY if (!really_stream) #endif { /* * Make sure that other people can't open the * slave side of the connection. */ chown(line, 0, 0); chmod(line, 0600); } #ifdef HAVE_REVOKE revoke(line); #endif t = open(line, O_RDWR|O_NOCTTY); if (t < 0) return(-1); /* * Hangup anybody else using this ttyp, then reopen it for * ourselves. */ # if !(defined(_CRAY) || defined(__hpux)) && (BSD <= 43) && !defined(STREAMSPTY) signal(SIGHUP, SIG_IGN); #ifdef HAVE_VHANGUP vhangup(); #else #endif signal(SIGHUP, SIG_DFL); t = open(line, O_RDWR|O_NOCTTY); if (t < 0) return(-1); # endif # if defined(_CRAY) && defined(TCVHUP) { int i; signal(SIGHUP, SIG_IGN); ioctl(t, TCVHUP, (char *)0); signal(SIGHUP, SIG_DFL); i = open(line, O_RDWR); if (i < 0) return(-1); close(t); t = i; } # endif /* defined(CRAY) && defined(TCVHUP) */ return(t); }
void BiasedLocking::revoke(GrowableArray<Handle>* objs) { assert(!SafepointSynchronize::is_at_safepoint(), "must not be called while at safepoint"); if (objs->length() == 0) { return; } VM_RevokeBias revoke(objs, JavaThread::current()); VMThread::execute(&revoke); }
/* Unlock the slave pseudo terminal associated with the master pseudo terminal specified by FD. */ int unlockpt (int fd) { char buf[sizeof (_PATH_TTY) + 2]; /* BSD doesn't have a lock, but it does have `revoke'. */ if (__ptsname_r (fd, buf, sizeof (buf))) return -1; return revoke (buf); }
Boolean ssh_pty_internal_allocate(int *ptyfd, int *ttyfd, char *namebuf) { char buf[64]; int i; #ifdef __FreeBSD__ const char *ptymajors = "pqrsPQRS"; const char *ptyminors = "0123456789abcdefghijklmnopqrstuv"; #else const char *ptymajors = "pqrstuvwxyzabcdefghijklmnoABCDEFGHIJKLMNOPQRSTUVWXYZ"; const char *ptyminors = "0123456789abcdef"; #endif int num_minors = strlen(ptyminors); int num_ptys = strlen(ptymajors) * num_minors; for (i = 0; i < num_ptys; i++) { snprintf(buf, sizeof(buf), "/dev/pty%c%c", ptymajors[i / num_minors], ptyminors[i % num_minors]); *ptyfd = open(buf, O_RDWR|O_NOCTTY); if (*ptyfd < 0) continue; snprintf(namebuf, SSH_PTY_NAME_SIZE, "/dev/tty%c%c", ptymajors[i / num_minors], ptyminors[i % num_minors]); #ifdef HAVE_REVOKE if (revoke(namebuf) == -1) ssh_warning("pty_allocate: revoke failed for %.100s", namebuf); #endif /* Open the slave side. */ *ttyfd = open(namebuf, O_RDWR|O_NOCTTY); if (*ttyfd < 0) { ssh_warning("%.100s: %.100s", namebuf, strerror(errno)); close(*ptyfd); /* Try with another pty. */ continue; } #if defined(ultrix) || defined(NeXT) (void) signal(SIGTTOU, SIG_IGN); /* corey via nancy */ #endif /* ultrix or NeXT */ return TRUE; } ssh_warning("Failed to allocate pty."); return FALSE; }
/* * Start a session and allocate a controlling terminal. * Only called by children of init after forking. */ static void setctty(const char *name) { int fd; revoke(name); if ((fd = open(name, O_RDWR)) == -1) { stall("can't open %s: %m", name); _exit(1); } if (login_tty(fd) == -1) { stall("can't get %s for controlling terminal: %m", name); _exit(1); } }
static int setctty(const char *name) { int fd; revoke(name); if ((fd = open(name, O_RDWR)) == -1) { exit(1); } if (login_tty(fd) == -1) { exit(1); } return fd; }
int main(int argc, char *argv[]) { char **d; int error = 0; if (argc == 1) usage(); for (d = &argv[1]; *d != NULL; d++) { if (revoke(*d) != 0) { perror(*d); error = 1; } } return (error); }
int unlockpt (int fd) { /* Platforms which have the TIOCSPTLCK ioctl (Linux) already have the unlockpt function. */ #if HAVE_REVOKE /* Mac OS X 10.3, OpenBSD 3.8 do not have the unlockpt function, but they have revoke(). */ char *name = ptsname (fd); if (name == NULL) return -1; return revoke (name); #else /* Assume that the slave side of a pseudo-terminal is already unlocked by default. */ if (fcntl (fd, F_GETFD) < 0) return -1; return 0; #endif }
bool get_pty(int *master, int *slave, char *name, size_t namesz, uid_t ttyuid) { char *bank, *cp; struct group *gr; gid_t ttygid = -1; bool rval = false; debug_decl(get_pty, SUDO_DEBUG_PTY) if ((gr = getgrnam("tty")) != NULL) ttygid = gr->gr_gid; for (bank = "pqrs"; *bank != '\0'; bank++) { line[sizeof("/dev/ptyX") - 2] = *bank; for (cp = "0123456789abcdef"; *cp != '\0'; cp++) { line[sizeof("/dev/ptyXX") - 2] = *cp; *master = open(line, O_RDWR|O_NOCTTY, 0); if (*master == -1) { if (errno == ENOENT) goto done; /* out of ptys */ continue; /* already in use */ } line[sizeof("/dev/p") - 2] = 't'; (void) chown(line, ttyuid, ttygid); (void) chmod(line, S_IRUSR|S_IWUSR|S_IWGRP); # ifdef HAVE_REVOKE (void) revoke(line); # endif *slave = open(line, O_RDWR|O_NOCTTY, 0); if (*slave != -1) { strlcpy(name, line, namesz); rval = true; /* success */ goto done; } (void) close(*master); } } done: debug_return_bool(rval); }
int main(int argc, char *argv[]) { extern char **environ; int first_sleep = 1, first_time = 1; struct rlimit limit; int rval; signal(SIGINT, SIG_IGN); signal(SIGQUIT, SIG_IGN); openlog("getty", LOG_ODELAY|LOG_CONS|LOG_PID, LOG_AUTH); gethostname(hostname, sizeof(hostname) - 1); hostname[sizeof(hostname) - 1] = '\0'; if (hostname[0] == '\0') strcpy(hostname, "Amnesiac"); /* * Limit running time to deal with broken or dead lines. */ (void)signal(SIGXCPU, timeoverrun); limit.rlim_max = RLIM_INFINITY; limit.rlim_cur = GETTY_TIMEOUT; (void)setrlimit(RLIMIT_CPU, &limit); gettable("default", defent); gendefaults(); tname = "default"; if (argc > 1) tname = argv[1]; /* * The following is a work around for vhangup interactions * which cause great problems getting window systems started. * If the tty line is "-", we do the old style getty presuming * that the file descriptors are already set up for us. * J. Gettys - MIT Project Athena. */ if (argc <= 2 || strcmp(argv[2], "-") == 0) strcpy(ttyn, ttyname(STDIN_FILENO)); else { strcpy(ttyn, dev); strncat(ttyn, argv[2], sizeof(ttyn)-sizeof(dev)); if (strcmp(argv[0], "+") != 0) { chown(ttyn, 0, 0); chmod(ttyn, 0600); revoke(ttyn); /* * Do the first scan through gettytab. * Terminal mode parameters will be wrong until * defttymode() called, but they're irrelevant for * the initial setup of the terminal device. */ dogettytab(); /* * Init or answer modem sequence has been specified. */ if (IC || AC) { if (!opentty(ttyn, O_RDWR|O_NONBLOCK)) exit(1); defttymode(); setttymode(1); } if (IC) { if (getty_chat(IC, CT, DC) > 0) { syslog(LOG_ERR, "modem init problem on %s", ttyn); (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode); exit(1); } } if (AC) { int i, rfds; struct timeval to; rfds = 1 << 0; /* FD_SET */ to.tv_sec = RT; to.tv_usec = 0; i = select(32, (fd_set*)&rfds, (fd_set*)NULL, (fd_set*)NULL, RT ? &to : NULL); if (i < 0) { syslog(LOG_ERR, "select %s: %m", ttyn); } else if (i == 0) { syslog(LOG_NOTICE, "recycle tty %s", ttyn); (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode); exit(0); /* recycle for init */ } i = getty_chat(AC, CT, DC); if (i > 0) { syslog(LOG_ERR, "modem answer problem on %s", ttyn); (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode); exit(1); } } else { /* maybe blocking open */ if (!opentty(ttyn, O_RDWR | (NC ? O_NONBLOCK : 0 ))) exit(1); } } } defttymode(); for (;;) { /* * if a delay was specified then sleep for that * number of seconds before writing the initial prompt */ if (first_sleep && DE) { sleep(DE); /* remove any noise */ (void)tcflush(STDIN_FILENO, TCIOFLUSH); } first_sleep = 0; setttymode(0); if (AB) { tname = autobaud(); dogettytab(); continue; } if (PS) { tname = portselector(); dogettytab(); continue; } if (CL && *CL) putpad(CL); edithost(HE); /* if this is the first time through this, and an issue file has been given, then send it */ if (first_time && IF) { int fd; if ((fd = open(IF, O_RDONLY)) != -1) { char * cp; while ((cp = getline(fd)) != NULL) { putf(cp); } close(fd); } } first_time = 0; if (IM && *IM && !(PL && PP)) putf(IM); if (setjmp(timeout)) { cfsetispeed(&tmode, B0); cfsetospeed(&tmode, B0); (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode); exit(1); } if (TO) { signal(SIGALRM, dingdong); alarm(TO); } rval = 0; if (AL) { const char *p = AL; char *q = name; while (*p && q < &name[sizeof name - 1]) { if (isupper(*p)) upper = 1; else if (islower(*p)) lower = 1; else if (isdigit(*p)) digit = 1; *q++ = *p++; } } else if (!(PL && PP)) rval = getname(); if (rval == 2 || (PL && PP)) { oflush(); alarm(0); limit.rlim_max = RLIM_INFINITY; limit.rlim_cur = RLIM_INFINITY; (void)setrlimit(RLIMIT_CPU, &limit); execle(PP, "ppplogin", ttyn, (char *) 0, env); syslog(LOG_ERR, "%s: %m", PP); exit(1); } else if (rval || AL) { int i; oflush(); alarm(0); signal(SIGALRM, SIG_DFL); if (name[0] == '\0') continue; if (name[0] == '-') { puts("user names may not start with '-'."); continue; } if (!(upper || lower || digit)) { if (AL) { syslog(LOG_ERR, "invalid auto-login name: %s", AL); exit(1); } else continue; } set_flags(2); if (crmod) { tmode.c_iflag |= ICRNL; tmode.c_oflag |= ONLCR; } #if REALLY_OLD_TTYS if (upper || UC) tmode.sg_flags |= LCASE; if (lower || LC) tmode.sg_flags &= ~LCASE; #endif if (tcsetattr(STDIN_FILENO, TCSANOW, &tmode) < 0) { syslog(LOG_ERR, "tcsetattr %s: %m", ttyn); exit(1); } signal(SIGINT, SIG_DFL); for (i = 0; environ[i] != (char *)0; i++) env[i] = environ[i]; makeenv(&env[i]); limit.rlim_max = RLIM_INFINITY; limit.rlim_cur = RLIM_INFINITY; (void)setrlimit(RLIMIT_CPU, &limit); execle(LO, "login", AL ? "-fp" : "-p", name, (char *) 0, env); syslog(LOG_ERR, "%s: %m", LO); exit(1); } alarm(0); signal(SIGALRM, SIG_DFL); signal(SIGINT, SIG_IGN); if (NX && *NX) { tname = NX; dogettytab(); } } }
/* * Threaded process initialization. * * This is only called under two conditions: * * 1) Some thread routines have detected that the library hasn't yet * been initialized (_thr_initial == NULL && curthread == NULL), or * * 2) An explicit call to reinitialize after a fork (indicated * by curthread != NULL) */ void _libpthread_init(struct pthread *curthread) { int fd, first = 0; sigset_t sigset, oldset; /* Check if this function has already been called: */ if ((_thr_initial != NULL) && (curthread == NULL)) /* Only initialize the threaded application once. */ return; /* * Check for the special case of this process running as * or in place of init as pid = 1: */ if ((_thr_pid = getpid()) == 1) { /* * Setup a new session for this process which is * assumed to be running as root. */ if (setsid() == -1) PANIC("Can't set session ID"); if (revoke(_PATH_CONSOLE) != 0) PANIC("Can't revoke console"); if ((fd = __sys_open(_PATH_CONSOLE, O_RDWR)) < 0) PANIC("Can't open console"); if (setlogin("root") == -1) PANIC("Can't set login to root"); if (__sys_ioctl(fd, TIOCSCTTY, NULL) == -1) PANIC("Can't set controlling terminal"); } /* Initialize pthread private data. */ init_private(); /* Set the initial thread. */ if (curthread == NULL) { first = 1; /* Create and initialize the initial thread. */ curthread = _thr_alloc(NULL); if (curthread == NULL) PANIC("Can't allocate initial thread"); init_main_thread(curthread); } /* * Add the thread to the thread list queue. */ THR_LIST_ADD(curthread); _thread_active_threads = 1; /* Setup the thread specific data */ tls_set_tcb(curthread->tcb); if (first) { SIGFILLSET(sigset); __sys_sigprocmask(SIG_SETMASK, &sigset, &oldset); _thr_signal_init(); _thr_initial = curthread; SIGDELSET(oldset, SIGCANCEL); __sys_sigprocmask(SIG_SETMASK, &oldset, NULL); if (td_eventismember(&_thread_event_mask, TD_CREATE)) _thr_report_creation(curthread, curthread); } }
int openpty(int *amaster, int *aslave, char *name, struct termios *term, struct winsize *winp) { char line[] = "/dev/XtyXX"; const char *cp1, *cp2, *cp, *linep; int master, slave; gid_t ttygid; mode_t mode; struct group grs, *grp; char grbuf[1024]; _DIAGASSERT(amaster != NULL); _DIAGASSERT(aslave != NULL); /* name may be NULL */ /* term may be NULL */ /* winp may be NULL */ #if !defined(__minix) if ((master = open("/dev/ptm", O_RDWR)) != -1) { struct ptmget pt; if (ioctl(master, TIOCPTMGET, &pt) != -1) { (void)close(master); master = pt.cfd; slave = pt.sfd; linep = pt.sn; goto gotit; } (void)close(master); } #endif /* !defined(__minix) */ (void)getgrnam_r("tty", &grs, grbuf, sizeof(grbuf), &grp); if (grp != NULL) { ttygid = grp->gr_gid; mode = S_IRUSR|S_IWUSR|S_IWGRP; } else { ttygid = getgid(); mode = S_IRUSR|S_IWUSR; } for (cp1 = TTY_LETTERS; *cp1; cp1++) { line[8] = *cp1; for (cp = cp2 = TTY_OLD_SUFFIX TTY_NEW_SUFFIX; *cp2; cp2++) { line[5] = 'p'; line[9] = *cp2; #ifdef __minix if ((master = open(line, O_RDWR | O_NOCTTY, 0)) == -1) { #else if ((master = open(line, O_RDWR, 0)) == -1) { #endif if (errno != ENOENT) continue; /* busy */ if ((size_t)(cp2 - cp + 1) < sizeof(TTY_OLD_SUFFIX)) return -1; /* out of ptys */ else break; /* out of ptys in this group */ } line[5] = 't'; linep = line; if (chown(line, getuid(), ttygid) == 0 && chmod(line, mode) == 0 && #if !defined(__minix) revoke(line) == 0 && #endif /* !defined(__minix) */ #ifdef __minix (slave = open(line, O_RDWR | O_NOCTTY, 0)) != -1) { #else (slave = open(line, O_RDWR, 0)) != -1) { #endif #if !defined(__minix) gotit: #endif /* !defined(__minix) */ *amaster = master; *aslave = slave; if (name) (void)strcpy(name, linep); if (term) (void)tcsetattr(slave, TCSAFLUSH, term); if (winp) (void)ioctl(slave, TIOCSWINSZ, winp); return 0; } (void)close(master); } } errno = ENOENT; /* out of ptys */ return -1; } pid_t forkpty(int *amaster, char *name, struct termios *term, struct winsize *winp) { int master, slave; pid_t pid; _DIAGASSERT(amaster != NULL); /* name may be NULL */ /* term may be NULL */ /* winp may be NULL */ if (openpty(&master, &slave, name, term, winp) == -1) return -1; switch (pid = fork()) { case -1: return -1; case 0: /* * child */ (void)close(master); login_tty(slave); return 0; } /* * parent */ *amaster = master; (void)close(slave); return pid; }
SubRegionMemory::~SubRegionMemory() { revoke(); }
bool KPty::open() { Q_D(KPty); if (d->masterFd >= 0) return true; d->ownMaster = true; QByteArray ptyName; // Find a master pty that we can open //////////////////////////////// // Because not all the pty animals are created equal, they want to // be opened by several different methods. // We try, as we know them, one by one. #ifdef HAVE_OPENPTY char ptsn[PATH_MAX]; if (::openpty( &d->masterFd, &d->slaveFd, ptsn, 0, 0)) { d->masterFd = -1; d->slaveFd = -1; qWarning(175) << "Can't open a pseudo teletype"; return false; } d->ttyName = ptsn; #else #ifdef HAVE__GETPTY // irix char *ptsn = _getpty(&d->masterFd, O_RDWR|O_NOCTTY, S_IRUSR|S_IWUSR, 0); if (ptsn) { d->ttyName = ptsn; goto grantedpt; } #elif defined(HAVE_PTSNAME) || defined(TIOCGPTN) #ifdef HAVE_POSIX_OPENPT d->masterFd = ::posix_openpt(O_RDWR|O_NOCTTY); #elif defined(HAVE_GETPT) d->masterFd = ::getpt(); #elif defined(PTM_DEVICE) d->masterFd = ::open(PTM_DEVICE, O_RDWR|O_NOCTTY); #else # error No method to open a PTY master detected. #endif if (d->masterFd >= 0) { #ifdef HAVE_PTSNAME char *ptsn = ptsname(d->masterFd); if (ptsn) { d->ttyName = ptsn; #else int ptyno; if (!ioctl(d->masterFd, TIOCGPTN, &ptyno)) { d->ttyName = QByteArray("/dev/pts/") + QByteArray::number(ptyno); #endif #ifdef HAVE_GRANTPT if (!grantpt(d->masterFd)) { goto grantedpt; } #else goto gotpty; #endif } ::close(d->masterFd); d->masterFd = -1; } #endif // HAVE_PTSNAME || TIOCGPTN // Linux device names, FIXME: Trouble on other systems? for (const char * s3 = "pqrstuvwxyzabcde"; *s3; s3++) { for (const char * s4 = "0123456789abcdef"; *s4; s4++) { ptyName = QString().sprintf("/dev/pty%c%c", *s3, *s4).toLatin1(); d->ttyName = QString().sprintf("/dev/tty%c%c", *s3, *s4).toLatin1(); d->masterFd = ::open(ptyName.data(), O_RDWR); if (d->masterFd >= 0) { #ifdef Q_OS_SOLARIS /* Need to check the process group of the pty. * If it exists, then the slave pty is in use, * and we need to get another one. */ int pgrp_rtn; if (ioctl(d->masterFd, TIOCGPGRP, &pgrp_rtn) == 0 || errno != EIO) { ::close(d->masterFd); d->masterFd = -1; continue; } #endif /* Q_OS_SOLARIS */ if (!access(d->ttyName.data(),R_OK|W_OK)) { // checks availability based on permission bits if (!geteuid()) { struct group * p = getgrnam(TTY_GROUP); if (!p) { p = getgrnam("wheel"); } gid_t gid = p ? p->gr_gid : getgid (); if (!chown(d->ttyName.data(), getuid(), gid)) { chmod(d->ttyName.data(), S_IRUSR|S_IWUSR|S_IWGRP); } } goto gotpty; } ::close(d->masterFd); d->masterFd = -1; } } } qWarning() << "Can't open a pseudo teletype"; return false; gotpty: struct stat st; if (stat(d->ttyName.data(), &st)) { return false; // this just cannot happen ... *cough* Yeah right, I just // had it happen when pty #349 was allocated. I guess // there was some sort of leak? I only had a few open. } if (((st.st_uid != getuid()) || (st.st_mode & (S_IRGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH))) && !d->chownpty(true)) { qWarning() << "chownpty failed for device " << ptyName << "::" << d->ttyName << "\nThis means the communication can be eavesdropped." << endl; } #if defined (HAVE__GETPTY) || defined (HAVE_GRANTPT) grantedpt: #endif #ifdef HAVE_REVOKE revoke(d->ttyName.data()); #endif #ifdef HAVE_UNLOCKPT unlockpt(d->masterFd); #elif defined(TIOCSPTLCK) int flag = 0; ioctl(d->masterFd, TIOCSPTLCK, &flag); #endif d->slaveFd = ::open(d->ttyName.data(), O_RDWR | O_NOCTTY); if (d->slaveFd < 0) { qWarning() << "Can't open slave pseudo teletype"; ::close(d->masterFd); d->masterFd = -1; return false; } #if (defined(__svr4__) || defined(__sgi__)) // Solaris ioctl(d->slaveFd, I_PUSH, "ptem"); ioctl(d->slaveFd, I_PUSH, "ldterm"); #endif #endif /* HAVE_OPENPTY */ fcntl(d->masterFd, F_SETFD, FD_CLOEXEC); fcntl(d->slaveFd, F_SETFD, FD_CLOEXEC); return true; } bool KPty::open(int fd) { #if !defined(HAVE_PTSNAME) && !defined(TIOCGPTN) qWarning() << "Unsupported attempt to open pty with fd" << fd; return false; #else Q_D(KPty); if (d->masterFd >= 0) { qWarning() << "Attempting to open an already open pty"; return false; } d->ownMaster = false; # ifdef HAVE_PTSNAME char *ptsn = ptsname(fd); if (ptsn) { d->ttyName = ptsn; # else int ptyno; if (!ioctl(fd, TIOCGPTN, &ptyno)) { char buf[32]; sprintf(buf, "/dev/pts/%d", ptyno); d->ttyName = buf; # endif } else { qWarning() << "Failed to determine pty slave device for fd" << fd; return false; } d->masterFd = fd; if (!openSlave()) { d->masterFd = -1; return false; } return true; #endif } void KPty::closeSlave() { Q_D(KPty); if (d->slaveFd < 0) { return; } ::close(d->slaveFd); d->slaveFd = -1; }
int main(int argc, char *argv[]) { extern char **environ; char *tname; int repcnt = 0, failopenlogged = 0; struct rlimit limit; int rval; signal(SIGINT, SIG_IGN); /* signal(SIGQUIT, SIG_DFL); */ openlog("getty", LOG_ODELAY|LOG_CONS|LOG_PID, LOG_AUTH); gethostname(hostname, sizeof(hostname)); if (hostname[0] == '\0') strlcpy(hostname, "Amnesiac", sizeof hostname); uname(&kerninfo); /* * Limit running time to deal with broken or dead lines. */ (void)signal(SIGXCPU, timeoverrun); limit.rlim_max = RLIM_INFINITY; limit.rlim_cur = GETTY_TIMEOUT; (void)setrlimit(RLIMIT_CPU, &limit); /* * The following is a work around for vhangup interactions * which cause great problems getting window systems started. * If the tty line is "-", we do the old style getty presuming * that the file descriptors are already set up for us. * J. Gettys - MIT Project Athena. */ if (argc <= 2 || strcmp(argv[2], "-") == 0) { snprintf(ttyn, sizeof ttyn, "%s", ttyname(0)); } else { int i; snprintf(ttyn, sizeof ttyn, "%s%s", dev, argv[2]); if (strcmp(argv[0], "+") != 0) { chown(ttyn, 0, 0); chmod(ttyn, 0600); revoke(ttyn); /* * Delay the open so DTR stays down long enough to be detected. */ sleep(2); while ((i = open(ttyn, O_RDWR)) == -1) { if ((repcnt % 10 == 0) && (errno != ENXIO || !failopenlogged)) { syslog(LOG_ERR, "%s: %m", ttyn); closelog(); failopenlogged = 1; } repcnt++; sleep(60); } login_tty(i); } } /* Start with default tty settings */ if (tcgetattr(0, &tmode) < 0) { syslog(LOG_ERR, "%s: %m", ttyn); exit(1); } omode = tmode; gettable("default", defent); gendefaults(); tname = "default"; if (argc > 1) tname = argv[1]; for (;;) { int off; gettable(tname, tabent); if (OPset || EPset || APset) APset++, OPset++, EPset++; setdefaults(); off = 0; (void)tcflush(0, TCIOFLUSH); /* clear out the crap */ ioctl(0, FIONBIO, &off); /* turn off non-blocking mode */ ioctl(0, FIOASYNC, &off); /* ditto for async mode */ if (IS) cfsetispeed(&tmode, IS); else if (SP) cfsetispeed(&tmode, SP); if (OS) cfsetospeed(&tmode, OS); else if (SP) cfsetospeed(&tmode, SP); setflags(0); setchars(); if (tcsetattr(0, TCSANOW, &tmode) < 0) { syslog(LOG_ERR, "%s: %m", ttyn); exit(1); } if (AB) { tname = autobaud(); continue; } if (PS) { tname = portselector(); continue; } if (CL && *CL) putpad(CL); edithost(HE); if (IM && *IM) putf(IM); if (TO) { signal(SIGALRM, dingdong); alarm(TO); } if ((rval = getname()) == 2) { oflush(); alarm(0); signal(SIGALRM, SIG_DFL); execle(PP, "ppplogin", ttyn, (char *) 0, env); syslog(LOG_ERR, "%s: %m", PP); exit(1); } else if (rval) { int i; oflush(); alarm(0); signal(SIGALRM, SIG_DFL); if (name[0] == '-') { xputs("user names may not start with '-'."); continue; } if (!(upper || lower || digit)) continue; setflags(2); if (crmod) { tmode.c_iflag |= ICRNL; tmode.c_oflag |= ONLCR; } if (upper || UC) { tmode.c_iflag |= IUCLC; tmode.c_oflag |= OLCUC; tmode.c_lflag |= XCASE; } if (lower || LC) { tmode.c_iflag &= ~IUCLC; tmode.c_oflag &= ~OLCUC; tmode.c_lflag &= ~XCASE; } if (tcsetattr(0, TCSANOW, &tmode) < 0) { syslog(LOG_ERR, "%s: %m", ttyn); exit(1); } signal(SIGINT, SIG_DFL); for (i = 0; environ[i] != (char *)0; i++) env[i] = environ[i]; makeenv(&env[i]); limit.rlim_max = RLIM_INFINITY; limit.rlim_cur = RLIM_INFINITY; (void)setrlimit(RLIMIT_CPU, &limit); execle(LO, "login", "-p", "--", name, (char *)0, env); syslog(LOG_ERR, "%s: %m", LO); exit(1); } alarm(0); signal(SIGALRM, SIG_DFL); signal(SIGINT, SIG_IGN); if (NX && *NX) tname = NX; } }
int main(int argc, char *argv[]) { long retval; int status; char buf[4]; int n; prog = argv[0]; printf("parent: pid=%ld\n", (long)getpid()); retval = ptyint_getpty_ext(&masterfd, slave, sizeof(slave), 0); if (retval) { com_err(prog, retval, "open master"); exit(1); } #if 0 chown(slave, 1, -1); #endif printf("parent: master opened; slave=%s\n", slave); fflush(stdout); #if defined(HAVE_GRANTPT) && defined(HAVE_STREAMS) #ifdef O_NOCTTY printf("parent: attempting to open slave before unlockpt\n"); fflush(stdout); slavefd = open(slave, O_RDWR|O_NONBLOCK|O_NOCTTY); if (slavefd < 0) { printf("parent: failed slave open before unlockpt errno=%ld (%s)\n", (long)errno, strerror(errno)); } else { printf("parent: WARNING: " "succeeded in opening slave before unlockpt\n"); } close(slavefd); #endif if (grantpt(masterfd) < 0) { perror("parent: grantpt"); exit(1); } if (unlockpt(masterfd) < 0) { perror("parent: unlockpt"); exit(1); } #endif /* HAVE_GRANTPT && HAVE_STREAMS */ if (pipe(pp1) < 0) { perror("pipe parent->child1"); exit(1); } if (pipe(p1p) < 0) { perror("pipe child1->parent"); exit(1); } pid1 = fork(); if (!pid1) { child1(); } else if (pid1 == -1) { perror("fork of child1"); exit(1); } printf("parent: forked child1=%ld\n", (long)pid1); fflush(stdout); if (waitpid(pid1, &status1, 0) < 0) { perror("waitpid for child1"); exit(1); } printf("parent: child1 exited, status=%d\n", status1); if (status1) exit(status1); wrsync(pp1[1], 0, "[01] parent->child2"); rdsync(p1p[0], &status, "[02] child3->parent"); if (status) { fprintf(stderr, "child2 or child3 got an error\n"); exit(1); } printf("parent: closing master\n"); fflush(stdout); close(masterfd); chmod(slave, 0666); printf("parent: closed master\n"); wrsync(pp1[1], 0, "[03] parent->child3"); rdsync(p1p[0], &status, "[04] child3->parent"); switch (status) { case 1: break; case 0: exit(0); default: fprintf(stderr, "child3 got an error\n"); fflush(stdout); exit(1); } retval = pty_getpty(&masterfd, slave2, sizeof(slave2)); printf("parent: new master opened; slave=%s\n", slave2); #if 0 #ifdef HAVE_REVOKE printf("parent: revoking\n"); revoke(slave2); #endif #endif fflush(stdout); wrsync(pp1[1], 0, "[05] parent->child3"); rdsync(p1p[0], NULL, "[06] child3->parent"); n = read(masterfd, buf, 4); if (n < 0) { perror("parent: reading from master"); } else { printf("parent: read %d bytes (%.*s) from master\n", n, n, buf); fflush(stdout); } chmod(slave2, 0666); close(masterfd); wrsync(pp1[1], 0, "[07] parent->child3"); rdsync(p1p[0], NULL, "[08] child3->parent"); fflush(stdout); exit(0); }
/* * Threaded process initialization. * * This is only called under two conditions: * * 1) Some thread routines have detected that the library hasn't yet * been initialized (_thr_initial == NULL && curthread == NULL), or * * 2) An explicit call to reinitialize after a fork (indicated * by curthread != NULL) */ void _libpthread_init(struct pthread *curthread) { int fd, first = 0; /* Check if this function has already been called: */ if ((_thr_initial != NULL) && (curthread == NULL)) /* Only initialize the threaded application once. */ return; /* * Check the size of the jump table to make sure it is preset * with the correct number of entries. */ if (sizeof(jmp_table) != (sizeof(pthread_func_t) * PJT_MAX * 2)) PANIC("Thread jump table not properly initialized"); memcpy(__thr_jtable, jmp_table, sizeof(jmp_table)); /* * Check for the special case of this process running as * or in place of init as pid = 1: */ if ((_thr_pid = getpid()) == 1) { /* * Setup a new session for this process which is * assumed to be running as root. */ if (setsid() == -1) PANIC("Can't set session ID"); if (revoke(_PATH_CONSOLE) != 0) PANIC("Can't revoke console"); if ((fd = __sys_open(_PATH_CONSOLE, O_RDWR)) < 0) PANIC("Can't open console"); if (setlogin("root") == -1) PANIC("Can't set login to root"); if (_ioctl(fd, TIOCSCTTY, (char *) NULL) == -1) PANIC("Can't set controlling terminal"); } /* Initialize pthread private data. */ init_private(); /* Set the initial thread. */ if (curthread == NULL) { first = 1; /* Create and initialize the initial thread. */ curthread = _thr_alloc(NULL); if (curthread == NULL) PANIC("Can't allocate initial thread"); init_main_thread(curthread); } /* * Add the thread to the thread list queue. */ THR_LIST_ADD(curthread); _thread_active_threads = 1; /* Setup the thread specific data */ _tcb_set(curthread->tcb); if (first) { _thr_initial = curthread; _thr_signal_init(); if (_thread_event_mask & TD_CREATE) _thr_report_creation(curthread, curthread); } }
static void chvt(const char *fn) { char dv[20]; struct stat sb; int fd; /* for entropy */ kshstate_f.h = evilhash(fn); if (*fn == '-') { memcpy(dv, "-/dev/null", sizeof("-/dev/null")); fn = dv + 1; } else { if (stat(fn, &sb)) { memcpy(dv, "/dev/ttyC", 9); strlcpy(dv + 9, fn, sizeof(dv) - 9); if (stat(dv, &sb)) { strlcpy(dv + 8, fn, sizeof(dv) - 8); if (stat(dv, &sb)) errorf("chvt: can't find tty %s", fn); } fn = dv; } if (!(sb.st_mode & S_IFCHR)) errorf("chvt: not a char device: %s", fn); if ((sb.st_uid != 0) && chown(fn, 0, 0)) warningf(false, "chvt: cannot chown root %s", fn); if (((sb.st_mode & 07777) != 0600) && chmod(fn, (mode_t)0600)) warningf(false, "chvt: cannot chmod 0600 %s", fn); #if HAVE_REVOKE if (revoke(fn)) #endif warningf(false, "chvt: cannot revoke %s, new shell is" " potentially insecure", fn); } if ((fd = open(fn, O_RDWR)) == -1) { sleep(1); if ((fd = open(fn, O_RDWR)) == -1) errorf("chvt: cannot open %s", fn); } switch (fork()) { case -1: errorf("chvt: %s failed", "fork"); case 0: break; default: exit(0); } if (setsid() == -1) errorf("chvt: %s failed", "setsid"); if (fn != dv + 1) { if (ioctl(fd, TIOCSCTTY, NULL) == -1) errorf("chvt: %s failed", "TIOCSCTTY"); if (tcflush(fd, TCIOFLUSH)) errorf("chvt: %s failed", "TCIOFLUSH"); } ksh_dup2(fd, 0, false); ksh_dup2(fd, 1, false); ksh_dup2(fd, 2, false); if (fd > 2) close(fd); chvt_reinit(); }
/* * Threaded process initialization. * * This is only called under two conditions: * * 1) Some thread routines have detected that the library hasn't yet * been initialized (_thr_initial == NULL && curthread == NULL), or * * 2) An explicit call to reinitialize after a fork (indicated * by curthread != NULL) */ void _libpthread_init(struct pthread *curthread) { int fd; /* Check if this function has already been called: */ if ((_thr_initial != NULL) && (curthread == NULL)) /* Only initialize the threaded application once. */ return; /* * Make gcc quiescent about {,libgcc_}references not being * referenced: */ if ((references[0] == NULL) || (libgcc_references[0] == NULL)) PANIC("Failed loading mandatory references in _thread_init"); /* Pull debug symbols in for static binary */ _thread_state_running = PS_RUNNING; /* * Check the size of the jump table to make sure it is preset * with the correct number of entries. */ if (sizeof(jmp_table) != (sizeof(pthread_func_t) * PJT_MAX * 2)) PANIC("Thread jump table not properly initialized"); memcpy(__thr_jtable, jmp_table, sizeof(jmp_table)); /* * Check for the special case of this process running as * or in place of init as pid = 1: */ if ((_thr_pid = getpid()) == 1) { /* * Setup a new session for this process which is * assumed to be running as root. */ if (setsid() == -1) PANIC("Can't set session ID"); if (revoke(_PATH_CONSOLE) != 0) PANIC("Can't revoke console"); if ((fd = __sys_open(_PATH_CONSOLE, O_RDWR)) < 0) PANIC("Can't open console"); if (setlogin("root") == -1) PANIC("Can't set login to root"); if (__sys_ioctl(fd, TIOCSCTTY, (char *) NULL) == -1) PANIC("Can't set controlling terminal"); } /* Initialize pthread private data. */ init_private(); _kse_init(); /* Initialize the initial kse and kseg. */ _kse_initial = _kse_alloc(NULL, _thread_scope_system > 0); if (_kse_initial == NULL) PANIC("Can't allocate initial kse."); _kse_initial->k_kseg = _kseg_alloc(NULL); if (_kse_initial->k_kseg == NULL) PANIC("Can't allocate initial kseg."); _kse_initial->k_kseg->kg_flags |= KGF_SINGLE_THREAD; _kse_initial->k_schedq = &_kse_initial->k_kseg->kg_schedq; TAILQ_INSERT_TAIL(&_kse_initial->k_kseg->kg_kseq, _kse_initial, k_kgqe); _kse_initial->k_kseg->kg_ksecount = 1; /* Set the initial thread. */ if (curthread == NULL) { /* Create and initialize the initial thread. */ curthread = _thr_alloc(NULL); if (curthread == NULL) PANIC("Can't allocate initial thread"); _thr_initial = curthread; init_main_thread(curthread); } else { /* * The initial thread is the current thread. It is * assumed that the current thread is already initialized * because it is left over from a fork(). */ _thr_initial = curthread; } _kse_initial->k_kseg->kg_threadcount = 0; _thr_initial->kse = _kse_initial; _thr_initial->kseg = _kse_initial->k_kseg; _thr_initial->active = 1; /* * Add the thread to the thread list and to the KSEG's thread * queue. */ THR_LIST_ADD(_thr_initial); KSEG_THRQ_ADD(_kse_initial->k_kseg, _thr_initial); /* Setup the KSE/thread specific data for the current KSE/thread. */ _thr_initial->kse->k_curthread = _thr_initial; _kcb_set(_thr_initial->kse->k_kcb); _tcb_set(_thr_initial->kse->k_kcb, _thr_initial->tcb); _thr_initial->kse->k_flags |= KF_INITIALIZED; _thr_signal_init(); _kse_critical_leave(&_thr_initial->tcb->tcb_tmbx); /* * activate threaded mode as soon as possible if we are * being debugged */ if (_libkse_debug) _kse_setthreaded(1); }
static void chvt(const Getopt *go) { const char *dv = go->optarg; char *cp = NULL; int fd; switch (*dv) { case '-': dv = "/dev/null"; break; case '!': ++dv; /* FALLTHROUGH */ default: { struct stat sb; if (stat(dv, &sb)) { cp = shf_smprintf("/dev/ttyC%s", dv); dv = cp; if (stat(dv, &sb)) { memmove(cp + 1, cp, /* /dev/tty */ 8); dv = cp + 1; if (stat(dv, &sb)) { errorf("%s: %s: %s", "chvt", "can't find tty", go->optarg); } } } if (!(sb.st_mode & S_IFCHR)) errorf("%s: %s: %s", "chvt", "not a char device", dv); #ifndef MKSH_DISABLE_REVOKE_WARNING #if HAVE_REVOKE if (revoke(dv)) #endif warningf(false, "%s: %s %s", "chvt", "new shell is potentially insecure, can't revoke", dv); #endif } } if ((fd = binopen2(dv, O_RDWR)) < 0) { sleep(1); if ((fd = binopen2(dv, O_RDWR)) < 0) { errorf("%s: %s %s", "chvt", "can't open", dv); } } if (go->optarg[0] != '!') { switch (fork()) { case -1: errorf("%s: %s %s", "chvt", "fork", "failed"); case 0: break; default: exit(0); } } if (setsid() == -1) errorf("%s: %s %s", "chvt", "setsid", "failed"); if (go->optarg[0] != '-') { if (ioctl(fd, TIOCSCTTY, NULL) == -1) errorf("%s: %s %s", "chvt", "TIOCSCTTY", "failed"); if (tcflush(fd, TCIOFLUSH)) errorf("%s: %s %s", "chvt", "TCIOFLUSH", "failed"); } ksh_dup2(fd, 0, false); ksh_dup2(fd, 1, false); ksh_dup2(fd, 2, false); if (fd > 2) close(fd); rndset((unsigned long)chvt_rndsetup(go, sizeof(Getopt))); chvt_reinit(); }
int slirp_openpty(int *amaster, int *aslave) { register int master, slave; #ifdef HAVE_GRANTPT char *ptr; if ((master = open("/dev/ptmx", O_RDWR)) < 0 || grantpt(master) < 0 || unlockpt(master) < 0 || (ptr = ptsname(master)) == NULL) { close(master); return -1; } if ((slave = open(ptr, O_RDWR)) < 0 || ioctl(slave, I_PUSH, "ptem") < 0 || ioctl(slave, I_PUSH, "ldterm") < 0 || ioctl(slave, I_PUSH, "ttcompat") < 0) { close(master); close(slave); return -1; } *amaster = master; *aslave = slave; return 0; #else static char line[] = "/dev/ptyXX"; register const char *cp1, *cp2; for (cp1 = "pqrsPQRS"; *cp1; cp1++) { line[8] = *cp1; for (cp2 = "0123456789abcdefghijklmnopqrstuv"; *cp2; cp2++) { line[9] = *cp2; if ((master = open(line, O_RDWR, 0)) == -1) { if (errno == ENOENT) return (-1); /* out of ptys */ } else { line[5] = 't'; /* These will fail */ (void) chown(line, getuid(), 0); (void) chmod(line, S_IRUSR|S_IWUSR|S_IWGRP); #ifdef HAVE_REVOKE (void) revoke(line); #endif if ((slave = open(line, O_RDWR, 0)) != -1) { *amaster = master; *aslave = slave; return 0; } (void) close(master); line[5] = 'p'; } } } errno = ENOENT; /* out of ptys */ return (-1); #endif }
BiasedLocking::Condition BiasedLocking::revoke_and_rebias(Handle obj, bool attempt_rebias, TRAPS) { assert(!SafepointSynchronize::is_at_safepoint(), "must not be called while at safepoint"); // We can revoke the biases of anonymously-biased objects // efficiently enough that we should not cause these revocations to // update the heuristics because doing so may cause unwanted bulk // revocations (which are expensive) to occur. markOop mark = obj->mark(); if (mark->is_biased_anonymously() && !attempt_rebias) { // We are probably trying to revoke the bias of this object due to // an identity hash code computation. Try to revoke the bias // without a safepoint. This is possible if we can successfully // compare-and-exchange an unbiased header into the mark word of // the object, meaning that no other thread has raced to acquire // the bias of the object. markOop biased_value = mark; markOop unbiased_prototype = markOopDesc::prototype()->set_age(mark->age()); markOop res_mark = (markOop) Atomic::cmpxchg_ptr(unbiased_prototype, obj->mark_addr(), mark); if (res_mark == biased_value) { return BIAS_REVOKED; } } else if (mark->has_bias_pattern()) { Klass* k = obj->klass(); markOop prototype_header = k->prototype_header(); if (!prototype_header->has_bias_pattern()) { // This object has a stale bias from before the bulk revocation // for this data type occurred. It's pointless to update the // heuristics at this point so simply update the header with a // CAS. If we fail this race, the object's bias has been revoked // by another thread so we simply return and let the caller deal // with it. markOop biased_value = mark; markOop res_mark = (markOop) Atomic::cmpxchg_ptr(prototype_header, obj->mark_addr(), mark); assert(!(*(obj->mark_addr()))->has_bias_pattern(), "even if we raced, should still be revoked"); return BIAS_REVOKED; } else if (prototype_header->bias_epoch() != mark->bias_epoch()) { // The epoch of this biasing has expired indicating that the // object is effectively unbiased. Depending on whether we need // to rebias or revoke the bias of this object we can do it // efficiently enough with a CAS that we shouldn't update the // heuristics. This is normally done in the assembly code but we // can reach this point due to various points in the runtime // needing to revoke biases. if (attempt_rebias) { assert(THREAD->is_Java_thread(), ""); markOop biased_value = mark; markOop rebiased_prototype = markOopDesc::encode((JavaThread*) THREAD, mark->age(), prototype_header->bias_epoch()); markOop res_mark = (markOop) Atomic::cmpxchg_ptr(rebiased_prototype, obj->mark_addr(), mark); if (res_mark == biased_value) { return BIAS_REVOKED_AND_REBIASED; } } else { markOop biased_value = mark; markOop unbiased_prototype = markOopDesc::prototype()->set_age(mark->age()); markOop res_mark = (markOop) Atomic::cmpxchg_ptr(unbiased_prototype, obj->mark_addr(), mark); if (res_mark == biased_value) { return BIAS_REVOKED; } } } } HeuristicsResult heuristics = update_heuristics(obj(), attempt_rebias); if (heuristics == HR_NOT_BIASED) { return NOT_BIASED; } else if (heuristics == HR_SINGLE_REVOKE) { Klass *k = obj->klass(); markOop prototype_header = k->prototype_header(); if (mark->biased_locker() == THREAD && prototype_header->bias_epoch() == mark->bias_epoch()) { // A thread is trying to revoke the bias of an object biased // toward it, again likely due to an identity hash code // computation. We can again avoid a safepoint in this case // since we are only going to walk our own stack. There are no // races with revocations occurring in other threads because we // reach no safepoints in the revocation path. // Also check the epoch because even if threads match, another thread // can come in with a CAS to steal the bias of an object that has a // stale epoch. ResourceMark rm; if (TraceBiasedLocking) { tty->print_cr("Revoking bias by walking my own stack:"); } BiasedLocking::Condition cond = revoke_bias(obj(), false, false, (JavaThread*) THREAD); ((JavaThread*) THREAD)->set_cached_monitor_info(NULL); assert(cond == BIAS_REVOKED, "why not?"); return cond; } else { VM_RevokeBias revoke(&obj, (JavaThread*) THREAD); VMThread::execute(&revoke); return revoke.status_code(); } } assert((heuristics == HR_BULK_REVOKE) || (heuristics == HR_BULK_REBIAS), "?"); VM_BulkRevokeBias bulk_revoke(&obj, (JavaThread*) THREAD, (heuristics == HR_BULK_REBIAS), attempt_rebias); VMThread::execute(&bulk_revoke); return bulk_revoke.status_code(); }
int main () { return revoke("/") ; }
void die_you_gravy_sucking_pig_dog(void) { syslog(LOG_NOTICE, "%s by %s: %s", doreboot ? "reboot" : dohalt ? "halt" : "shutdown", whom, mbuf); (void)sleep(2); (void)printf("\r\nSystem shutdown time has arrived\007\007\r\n"); if (killflg) { (void)printf("\rbut you'll have to do it yourself\r\n"); finish(0); } if (dofast) doitfast(); #ifdef DEBUG if (doreboot) (void)printf("reboot"); else if (dohalt) (void)printf("halt"); if (nosync) (void)printf(" no sync"); if (dofast) (void)printf(" no fsck"); if (dodump) (void)printf(" with dump"); (void)printf("\nkill -HUP 1\n"); #else if (doreboot) { execle(_PATH_REBOOT, "reboot", "-l", (nosync ? "-n" : (dodump ? "-d" : NULL)), (dodump ? "-d" : NULL), (char *)NULL, (char *)NULL); syslog(LOG_ERR, "shutdown: can't exec %s: %m.", _PATH_REBOOT); warn(_PATH_REBOOT); } else if (dohalt) { execle(_PATH_HALT, "halt", "-l", (dopower ? "-p" : (nosync ? "-n" : (dodump ? "-d" : NULL))), (nosync ? "-n" : (dodump ? "-d" : NULL)), (dodump ? "-d" : NULL), (char *)NULL, (char *)NULL); syslog(LOG_ERR, "shutdown: can't exec %s: %m.", _PATH_HALT); warn(_PATH_HALT); } if (access(_PATH_RC, R_OK) != -1) { pid_t pid; struct termios t; int fd; switch ((pid = fork())) { case -1: break; case 0: if (revoke(_PATH_CONSOLE) == -1) perror("revoke"); if (setsid() == -1) perror("setsid"); fd = open(_PATH_CONSOLE, O_RDWR); if (fd == -1) perror("open"); dup2(fd, 0); dup2(fd, 1); dup2(fd, 2); if (fd > 2) close(fd); /* At a minimum... */ tcgetattr(0, &t); t.c_oflag |= (ONLCR | OPOST); tcsetattr(0, TCSANOW, &t); execl(_PATH_BSHELL, "sh", _PATH_RC, "shutdown", (char *)NULL); _exit(1); default: waitpid(pid, NULL, 0); } } (void)kill(1, SIGTERM); /* to single user */ #endif finish(0); }