static int isctty(proc_t p, struct tty *tp);
static int isctty_sp(proc_t p, struct tty *tp, struct session *sessp);
+__private_extern__ void termios32to64(struct termios32 *in, struct user_termios *out);
+__private_extern__ void termios64to32(struct user_termios *in, struct termios32 *out);
+
/*
* Table with character classes and parity. The 8th bit indicates parity,
* the 7th bit indicates the character is an alphameric or underscore (for
#define I_HIGH_WATER (TTYHOG - 2 * 256) /* XXX */
#define I_LOW_WATER ((TTYHOG - 2 * 256) * 7 / 8) /* XXX */
-static void
+__private_extern__ void
termios32to64(struct termios32 *in, struct user_termios *out)
{
out->c_iflag = (user_tcflag_t)in->c_iflag;
out->c_ospeed = (user_speed_t)in->c_ospeed;
}
-static void
+__private_extern__ void
termios64to32(struct user_termios *in, struct termios32 *out)
{
- out->c_iflag = (tcflag_t)in->c_iflag;
- out->c_oflag = (tcflag_t)in->c_oflag;
- out->c_cflag = (tcflag_t)in->c_cflag;
- out->c_lflag = (tcflag_t)in->c_lflag;
+ out->c_iflag = (uint32_t)in->c_iflag;
+ out->c_oflag = (uint32_t)in->c_oflag;
+ out->c_cflag = (uint32_t)in->c_cflag;
+ out->c_lflag = (uint32_t)in->c_lflag;
/* bcopy is OK, since this type is ILP32/LP64 size invariant */
bcopy(in->c_cc, out->c_cc, sizeof(in->c_cc));
- out->c_ispeed = (speed_t)in->c_ispeed;
- out->c_ospeed = (speed_t)in->c_ospeed;
+ out->c_ispeed = (uint32_t)MIN(in->c_ispeed, UINT32_MAX);
+ out->c_ospeed = (uint32_t)MIN(in->c_ospeed, UINT32_MAX);
}
return -1;
}
-/*
- * Sets the tty state to not allow any more changes of foreground process
- * group. This is required to be done so that a subsequent revoke on a vnode
- * is able to always successfully complete.
- *
- * Locks : Assumes tty_lock held on entry
- */
-void
-ttysetpgrphup(struct tty *tp)
-{
- TTY_LOCK_OWNED(tp); /* debug assert */
- SET(tp->t_state, TS_PGRPHUP);
- /*
- * Also wake up sleeping readers which may or may not belong to the
- * current foreground process group.
- *
- * This forces any non-fg readers (which entered read when
- * that process group was in the fg) to return with EIO (if they're
- * catching SIGTTIN or with SIGTTIN). The ones which do belong to the fg
- * process group will promptly go back to sleep and get a SIGHUP shortly
- * This would normally happen as part of the close in revoke but if
- * there is a sleeping reader from a non-fg process group we never get
- * to the close because the sleeping reader holds an iocount on the
- * vnode of the terminal which is going to get revoked->reclaimed.
- */
- wakeup(TSA_HUP_OR_INPUT(tp));
-}
-
-/*
- * Locks : Assumes tty lock held on entry
- */
-void
-ttyclrpgrphup(struct tty *tp)
-{
- TTY_LOCK_OWNED(tp); /* debug assert */
- CLR(tp->t_state, TS_PGRPHUP);
-}
-
/*
* ttioctl
*
case TIOCSCONS: {
/* Set current console device to this line */
data = (caddr_t) &bogusData;
-
- /* No break - Fall through to BSD code */
}
+ OS_FALLTHROUGH;
case TIOCCONS: { /* become virtual console */
if (*(int *)data) {
if (constty && constty != tp &&
error = EPERM;
goto out;
}
- /*
- * The session leader is going away and is possibly going to revoke
- * the terminal, we can't change the process group when that is the
- * case.
- */
- if (ISSET(tp->t_state, TS_PGRPHUP)) {
- if (sessp != SESSION_NULL) {
- session_rele(sessp);
- }
- pg_rele(pgrp);
- error = EPERM;
- goto out;
- }
+
proc_list_lock();
oldpg = tp->t_pgrp;
tp->t_pgrp = pgrp;
* process group.
*
* ttwakeup() isn't called because the readers aren't getting
- * woken up becuse there is something to read but to force
+ * woken up because there is something to read but to force
* the re-evaluation of their foreground process group status.
*
* Ordinarily leaving these readers waiting wouldn't be an issue
*(int *)data = tp->t_timeout / hz;
break;
case TIOCREVOKE:
- if (ISSET(tp->t_state, TS_PGRPHUP)) {
- tp->t_gen++;
- wakeup(TSA_HUP_OR_INPUT(tp));
- }
+ SET(tp->t_state, TS_REVOKE);
+ tp->t_gen++;
+ /*
+ * At this time, only this wait channel is woken up as only
+ * ttread has been problematic. It is possible we may need
+ * to add wake up other tty wait addresses as well.
+ */
+ wakeup(TSA_HUP_OR_INPUT(tp));
+ break;
+ case TIOCREVOKECLEAR:
+ CLR(tp->t_state, TS_REVOKE);
break;
default:
error = ttcompat(tp, cmd, data, flag, p);
}
/*
- * Signal the process if it's in the background.
+ * Signal the process if it's in the background. If the terminal is
+ * getting revoked, everybody is in the background.
*/
- if (isbackground(p, tp)) {
+ if (isbackground(p, tp) || ISSET(tp->t_state, TS_REVOKE)) {
if ((p->p_sigignore & sigmask(SIGTTIN)) ||
(ut->uu_sigmask & sigmask(SIGTTIN)) ||
p->p_lflag & P_LPPWAIT) {
goto read;
}
microuptime(&timecopy);
- if (!has_etime) {
- /* first character, start timer */
+ if (!has_etime || qp->c_cc > last_cc) {
+ /* first character or got a character, start timer */
has_etime = 1;
etime.tv_sec = t / 1000000;
- etime.tv_usec = (t - (etime.tv_sec * 1000000));
- timeradd(&etime, &timecopy, &etime);
-
- slp = t;
- } else if (qp->c_cc > last_cc) {
- /* got a character, restart timer */
-
- etime.tv_sec = t / 1000000;
- etime.tv_usec = (t - (etime.tv_sec * 1000000));
+ etime.tv_usec =
+ (__darwin_suseconds_t)(t - (etime.tv_sec * 1000000));
timeradd(&etime, &timecopy, &etime);
slp = t;
has_etime = 1;
etime.tv_sec = t / 1000000;
- etime.tv_usec = (t - (etime.tv_sec * 1000000));
+ etime.tv_usec =
+ (__darwin_suseconds_t)(t - (etime.tv_sec * 1000000));
timeradd(&etime, &timecopy, &etime);
slp = t;
for (;;) {
char ibuf[IBUFSIZ];
int icc;
+ ssize_t size = uio_resid(uio);
+ if (size < 0) {
+ error = ERANGE;
+ break;
+ }
- icc = MIN(uio_resid(uio), IBUFSIZ);
+ icc = (int)MIN(size, IBUFSIZ);
icc = q_to_b(qp, (u_char *)ibuf, icc);
if (icc <= 0) {
if (first) {
* leftover from last time.
*/
if (cc == 0) {
- cc = MIN(uio_resid(uio), OBUFSIZ);
+ ssize_t size = uio_resid(uio);
+ if (size < 0) {
+ error = ERANGE;
+ break;
+ }
+ cc = (int)MIN((size_t)size, OBUFSIZ);
cp = obuf;
error = uiomove(cp, cc, uio);
if (error) {
if (!ISSET(tp->t_oflag, OPOST)) {
ce = cc;
} else {
- ce = cc - scanc((u_int)cc, (u_char *)cp,
- char_type, CCLASSMASK);
+ ce = (int)((size_t)cc - scanc((size_t)cc,
+ (u_char *)cp, char_type, CCLASSMASK));
/*
* If ce is zero, then we're processing
* a special character through ttyoutput.
void
ttsetwater(struct tty *tp)
{
- int cps;
+ speed_t cps;
unsigned int x;
TTY_LOCK_OWNED(tp); /* debug assert */
#define CLAMP(x, h, l) ((x) > h ? h : ((x) < l) ? l : (x))
cps = tp->t_ospeed / 10;
- tp->t_lowat = x = CLAMP(cps / 2, TTMAXLOWAT, TTMINLOWAT);
+ static_assert(TTMAXLOWAT <= UINT_MAX, "max low water fits in unsigned int");
+ static_assert(TTMINLOWAT <= UINT_MAX, "min low water fits in unsigned int");
+ tp->t_lowat = x = (unsigned int)CLAMP(cps / 2, TTMAXLOWAT, TTMINLOWAT);
x += cps;
x = CLAMP(x, TTMAXHIWAT, TTMINHIWAT);
tp->t_hiwat = roundup(x, CBSIZE);
TTY_LOCK_OWNED(tp);
+ if (tp->t_state & TS_REVOKE) {
+ return ERESTART;
+ }
+
gen = tp->t_gen;
/* Use of msleep0() avoids conversion timo/timespec/timo */
error = msleep0(chan, &tp->t_lock, pri, wmesg, timo, (int (*)(int))0);
uth = get_bsdthread_info(current_thread());
ctx = vfs_context_current();
- vp = (vnode_t)kn->kn_fp->f_fglob->fg_data;
+ vp = (vnode_t)kn->kn_fp->fp_glob->fg_data;
/*
* Reserve a link element to avoid potential allocation under