/* * 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; }
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; }