/*ARGSUSED*/ __private_extern__ int ttcompat(struct tty *tp, u_long com, caddr_t data, int flag, struct proc *p) { switch (com) { case TIOCSETP: case TIOCSETN: case TIOCSETC: case TIOCSLTC: case TIOCLBIS: case TIOCLBIC: case TIOCLSET: /* * See ttsetcompat() for a full description of these command * values and their meanings. */ { struct termios term; int error; term = tp->t_termios; if ((error = ttsetcompat(tp, &com, data, &term)) != 0) return error; return ttioctl_locked(tp, com, (caddr_t) &term, flag, p); } case TIOCGETP: /* * Get the current input and output speeds, and device * flags, into the structure pointed to by 'data'. */ { register struct sgttyb *sg = (struct sgttyb *)data; register cc_t *cc = tp->t_cc; sg->sg_ospeed = ttcompatspeedtab(tp->t_ospeed, compatspeeds); if (tp->t_ispeed == 0) sg->sg_ispeed = sg->sg_ospeed; else sg->sg_ispeed = ttcompatspeedtab(tp->t_ispeed, compatspeeds); sg->sg_erase = cc[VERASE]; sg->sg_kill = cc[VKILL]; sg->sg_flags = tp->t_flags = ttcompatgetflags(tp); break; } case TIOCGETC: /* * Get the terminal control characters into the struct * tchars that 'data' points to. */ { struct tchars *tc = (struct tchars *)data; register cc_t *cc = tp->t_cc; tc->t_intrc = cc[VINTR]; tc->t_quitc = cc[VQUIT]; tc->t_startc = cc[VSTART]; tc->t_stopc = cc[VSTOP]; tc->t_eofc = cc[VEOF]; tc->t_brkc = cc[VEOL]; break; } case TIOCGLTC: /* * Get the terminal control characters into the struct * ltchars that 'data' points to. */ { struct ltchars *ltc = (struct ltchars *)data; register cc_t *cc = tp->t_cc; ltc->t_suspc = cc[VSUSP]; ltc->t_dsuspc = cc[VDSUSP]; ltc->t_rprntc = cc[VREPRINT]; ltc->t_flushc = cc[VDISCARD]; ltc->t_werasc = cc[VWERASE]; ltc->t_lnextc = cc[VLNEXT]; break; } case TIOCLGET: /* * Get the terminal state local flags word into the 16 bit * value pointed to by 'data'. */ tp->t_flags = (ttcompatgetflags(tp) & 0xffff0000UL) | (tp->t_flags & 0xffff); *(int *)data = tp->t_flags>>16; break; case OTIOCGETD: /* * Get the current line discipline into the int pointed to * by 'data'. */ *(int *)data = tp->t_line ? tp->t_line : 2; break; case OTIOCSETD: /* * Set the current line discipline based on the value of the * int pointed to by 'data'. */ { int ldisczero = 0; return (ttioctl_locked(tp, TIOCSETD, *(int *)data == 2 ? (caddr_t)&ldisczero : data, flag, p)); } case OTIOCCONS: /* * Become the console device. */ *(int *)data = 1; return (ttioctl_locked(tp, TIOCCONS, data, flag, p)); case TIOCGSID: /* * Get the current session ID (controlling process' PID). */ if (tp->t_session == NULL) return ENOTTY; if (tp->t_session->s_leader == NULL) return ENOTTY; *(int *) data = tp->t_session->s_leader->p_pid; break; default: /* * This ioctl is not handled at this layer. */ return (ENOTTY); } /* * Successful 'get' operation. */ return (0); }
int ttsetcompat(struct tty *tp, u_long *com, caddr_t data, struct termios *term) { switch (*com) { case TIOCSETP: case TIOCSETN: { struct sgttyb *sg = (struct sgttyb *)data; int speed; if ((speed = sg->sg_ispeed) > MAX_SPEED || speed < 0) return(EINVAL); else if (speed != ttcompatspeedtab(tp->t_ispeed, compatspeeds)) term->c_ispeed = compatspcodes[speed]; else term->c_ispeed = tp->t_ispeed; if ((speed = sg->sg_ospeed) > MAX_SPEED || speed < 0) return(EINVAL); else if (speed != ttcompatspeedtab(tp->t_ospeed, compatspeeds)) term->c_ospeed = compatspcodes[speed]; else term->c_ospeed = tp->t_ospeed; term->c_cc[VERASE] = sg->sg_erase; term->c_cc[VKILL] = sg->sg_kill; tp->t_flags = (tp->t_flags&0xffff0000) | (sg->sg_flags&0xffff); ttcompatsetflags(tp, term); *com = (*com == TIOCSETP) ? TIOCSETAF : TIOCSETA; break; } case TIOCSETC: { struct tchars *tc = (struct tchars *)data; cc_t *cc; cc = term->c_cc; cc[VINTR] = tc->t_intrc; cc[VQUIT] = tc->t_quitc; cc[VSTART] = tc->t_startc; cc[VSTOP] = tc->t_stopc; cc[VEOF] = tc->t_eofc; cc[VEOL] = tc->t_brkc; if (tc->t_brkc == -1) cc[VEOL2] = _POSIX_VDISABLE; *com = TIOCSETA; break; } case TIOCSLTC: { struct ltchars *ltc = (struct ltchars *)data; cc_t *cc; cc = term->c_cc; cc[VSUSP] = ltc->t_suspc; cc[VDSUSP] = ltc->t_dsuspc; cc[VREPRINT] = ltc->t_rprntc; cc[VDISCARD] = ltc->t_flushc; cc[VWERASE] = ltc->t_werasc; cc[VLNEXT] = ltc->t_lnextc; *com = TIOCSETA; break; } case TIOCLBIS: case TIOCLBIC: case TIOCLSET: if (*com == TIOCLSET) tp->t_flags = (tp->t_flags&0xffff) | *(int *)data<<16; else { tp->t_flags = (ttcompatgetflags(tp)&0xffff0000)|(tp->t_flags&0xffff); if (*com == TIOCLBIS) tp->t_flags |= *(int *)data<<16; else tp->t_flags &= ~(*(int *)data<<16); } ttcompatsetlflags(tp, term); *com = TIOCSETA; break; } return 0; }
/* * ttsetcompat * * Description: Convert backward compatability set command arguments as * follows: * * TIOCSETP -> TIOSETAF * TIOCSETN -> TIOCSETA * TIOCSETC -> TIOCSETA * TIOCSLTC -> TIOCSETA * TIOCLBIS -> TIOCSETA * TIOCLBIC -> TIOCSETA * TIOCLSET -> TIOCSETA * * The converted command argument and potentially modified 'term' * argument are returned to ttcompat(), which will then call * ttioctl_locked(), if this function returns successfully. * * Parameters struct tty *tp The tty on which the operation is * being performed. * u_long *com A pointer to the terminal input/output * command being requested; its contents * will be modified per the table above, * on a non-error return. * caddr_t data Command specific parameter data; this * data is read but not modified. * struct termios *term A local stack termios structure from * ttcompat(), whose contents are to be * modified based on *com and *data. * * Returns: EINVAL An input speed or output speed is * outside the allowable range for a * TIOCSETP or TIOCSETN command. * 0 All other cases return 0. * * Notes: This function may modify the contents of the tp->t_flags * field in a successful call to TIOCSETP, TIOCSETN, TIOCLBIS, * TIOCLBIC, or TIOCLSET. * * All other tp fields will remain unmodifed, since the struct * termios is a local stack copy from ttcompat(), and not the * real thing. A subsequent call to ttioctl_locked() in * ttcompat(), however, may result in subsequent changes. * * WARNING: This compatibility code is not 6/432 clean; it will only * work for 32 bit processes on 32 bit kernels or 64 bit * processes on 64 bit kernels. We are not addressing this * due to <rdar://6904053>. */ static int ttsetcompat(struct tty *tp, u_long *com, caddr_t data, struct termios *term) { switch (*com) { case TIOCSETP: /* * Wait for all characters queued for output to drain, then * Discard all characters queued for input, and then set * the input and output speeds and device flags, per the * contents of the struct sgttyb that 'data' points to. */ case TIOCSETN: /* * Same as TIOCSETP, but the output is not drained, and any * pending input is not discarded. */ { register struct sgttyb *sg = (struct sgttyb *)data; int speed; if ((speed = sg->sg_ispeed) > MAX_SPEED || speed < 0) return(EINVAL); else if (speed != ttcompatspeedtab(tp->t_ispeed, compatspeeds)) term->c_ispeed = compatspcodes[speed]; else term->c_ispeed = tp->t_ispeed; if ((speed = sg->sg_ospeed) > MAX_SPEED || speed < 0) return(EINVAL); else if (speed != ttcompatspeedtab(tp->t_ospeed, compatspeeds)) term->c_ospeed = compatspcodes[speed]; else term->c_ospeed = tp->t_ospeed; term->c_cc[VERASE] = sg->sg_erase; term->c_cc[VKILL] = sg->sg_kill; tp->t_flags = (tp->t_flags&0xffff0000) | (sg->sg_flags&0xffff); ttcompatsetflags(tp, term); *com = (*com == TIOCSETP) ? TIOCSETAF : TIOCSETA; break; } case TIOCSETC: /* * Set the terminal control characters per the contents of * the struct tchars that 'data' points to. */ { struct tchars *tc = (struct tchars *)data; register cc_t *cc; cc = term->c_cc; cc[VINTR] = tc->t_intrc; cc[VQUIT] = tc->t_quitc; cc[VSTART] = tc->t_startc; cc[VSTOP] = tc->t_stopc; cc[VEOF] = tc->t_eofc; cc[VEOL] = tc->t_brkc; if (tc->t_brkc == -1) cc[VEOL2] = _POSIX_VDISABLE; *com = TIOCSETA; break; } case TIOCSLTC: /* * Set the terminal control characters per the contents of * the struct ltchars that 'data' points to. */ { struct ltchars *ltc = (struct ltchars *)data; register cc_t *cc; cc = term->c_cc; cc[VSUSP] = ltc->t_suspc; cc[VDSUSP] = ltc->t_dsuspc; cc[VREPRINT] = ltc->t_rprntc; cc[VDISCARD] = ltc->t_flushc; cc[VWERASE] = ltc->t_werasc; cc[VLNEXT] = ltc->t_lnextc; *com = TIOCSETA; break; } case TIOCLBIS: /* * Set the bits in the terminal state local flags word * (16 bits) for the terminal to the current bits OR * those in the 16 bit value pointed to by 'data'. */ case TIOCLBIC: /* * Clear the bits in the terminal state local flags word * for the terminal to the current bits AND those bits NOT * in the 16 bit value pointed to by 'data'. */ case TIOCLSET: /* * Set the terminal state local flags word to exactly those * bits that correspond to the 16 bit value pointed to by * 'data'. */ if (*com == TIOCLSET) tp->t_flags = (tp->t_flags&0xffff) | *(int *)data<<16; else { tp->t_flags = (ttcompatgetflags(tp)&0xffff0000)|(tp->t_flags&0xffff); if (*com == TIOCLBIS) tp->t_flags |= *(int *)data<<16; else tp->t_flags &= ~(*(int *)data<<16); } ttcompatsetlflags(tp, term); *com = TIOCSETA; break; } return 0; }
/*ARGSUSED*/ int ttcompat(struct tty *tp, u_long com, caddr_t data, int flag) { switch (com) { case TIOCSETP: case TIOCSETN: case TIOCSETC: case TIOCSLTC: case TIOCLBIS: case TIOCLBIC: case TIOCLSET: { struct termios term; int error; term = tp->t_termios; if ((error = ttsetcompat(tp, &com, data, &term)) != 0) return error; return ttioctl(tp, com, &term, flag); } case TIOCGETP: { struct sgttyb *sg = (struct sgttyb *)data; cc_t *cc = tp->t_cc; sg->sg_ospeed = ttcompatspeedtab(tp->t_ospeed, compatspeeds); if (tp->t_ispeed == 0) sg->sg_ispeed = sg->sg_ospeed; else sg->sg_ispeed = ttcompatspeedtab(tp->t_ispeed, compatspeeds); sg->sg_erase = cc[VERASE]; sg->sg_kill = cc[VKILL]; sg->sg_flags = tp->t_flags = ttcompatgetflags(tp); break; } case TIOCGETC: { struct tchars *tc = (struct tchars *)data; cc_t *cc = tp->t_cc; tc->t_intrc = cc[VINTR]; tc->t_quitc = cc[VQUIT]; tc->t_startc = cc[VSTART]; tc->t_stopc = cc[VSTOP]; tc->t_eofc = cc[VEOF]; tc->t_brkc = cc[VEOL]; break; } case TIOCGLTC: { struct ltchars *ltc = (struct ltchars *)data; cc_t *cc = tp->t_cc; ltc->t_suspc = cc[VSUSP]; ltc->t_dsuspc = cc[VDSUSP]; ltc->t_rprntc = cc[VREPRINT]; ltc->t_flushc = cc[VDISCARD]; ltc->t_werasc = cc[VWERASE]; ltc->t_lnextc = cc[VLNEXT]; break; } case TIOCLGET: tp->t_flags = (ttcompatgetflags(tp) & 0xffff0000UL) | (tp->t_flags & 0xffff); *(int *)data = tp->t_flags>>16; if (ttydebug) kprintf("CLGET: returning %x\n", *(int *)data); break; case OTIOCGETD: *(int *)data = tp->t_line ? tp->t_line : 2; break; case OTIOCSETD: { int ldisczero = 0; return (ttioctl(tp, TIOCSETD, *(int *)data == 2 ? (caddr_t)&ldisczero : data, flag)); } case OTIOCCONS: *(int *)data = 1; return (ttioctl(tp, TIOCCONS, data, flag)); default: return (ENOIOCTL); } return (0); }