X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/43866e378188c25dd1e2208016ab3cbeb086ae6c..527f99514973766e9c0382a4d8550dfb00f54939:/bsd/kern/tty_compat.c diff --git a/bsd/kern/tty_compat.c b/bsd/kern/tty_compat.c index e8cfe55a2..4348bd133 100644 --- a/bsd/kern/tty_compat.c +++ b/bsd/kern/tty_compat.c @@ -1,16 +1,19 @@ /* * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ - * - * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. + * + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER @@ -20,7 +23,7 @@ * Please see the License for the specific language governing rights and * limitations under the License. * - * @APPLE_LICENSE_HEADER_END@ + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ /* Copyright (c) 1997 Apple Computer, Inc. All Rights Reserved */ /*- @@ -59,36 +62,41 @@ */ /* - * mapping routines for old line discipline (yuck) + * Compatibility routines for BSD 4.3 tty ioctl() commands + * + * The only function externalized from this file is ttcompat() and it is + * externalized as private extern to prevent exporting of the symbol when + * KEXTs link against the kernel. + * + * Locks: All functions in this file assume that the tty_lock() + * is held on the tty structure before these functions are + * called. */ #include #include #include -#include +#include #include #include -#include +#include #include #include #include #include -/* NeXT Move define down here cause COMPAT_43 not valid earlier */ -#if COMPAT_43 || defined(COMPAT_SUNOS) - -static int ttcompatgetflags __P((struct tty *tp)); -static void ttcompatsetflags __P((struct tty *tp, struct termios *t)); -static void ttcompatsetlflags __P((struct tty *tp, struct termios *t)); -static int ttcompatspeedtab __P((int speed, struct speedtab *table)); - - -static int ttydebug = 0; - -#ifndef NeXT -SYSCTL_INT(_debug, OID_AUTO, ttydebug, CTLFLAG_RW, &ttydebug, 0, ""); -#endif +static int ttcompatgetflags(struct tty *tp); +static void ttcompatsetflags(struct tty *tp, struct termios *t); +static void ttcompatsetlflags(struct tty *tp, struct termios *t); +static int ttcompatspeedtab(int speed, struct speedtab *table); +/* + * These two tables encode baud rate to speed code and speed code to + * baud rate information. They are a mapping between the + * baud rate constants and the baud rate constants. We + * cannot use those constants directly here because they occupy the same + * name space. + */ static struct speedtab compatspeeds[] = { #define MAX_SPEED 17 { 115200, 17 }, @@ -116,10 +124,30 @@ static int compatspcodes[] = { 1800, 2400, 4800, 9600, 19200, 38400, 57600, 115200, }; +/* + * ttcompatspeedtab + * + * Description: Given a baud rate value as an integer, and a speed table, + * convert the baud rate to a speed code, according to the + * contents of the table. This effectively changes termios.h + * baud rate values into ttydev.h baud rate codes. + * + * Parameters: int speed Baud rate, as an integer + * struct speedtab *table Baud rate table to speed code table + * + * Returns: 1 B50 speed code; returned if we can + * not find an answer in the table. + * 0 If a 0 was requested in order to + * trigger a hangup (250ms of line + * silence, per Bell 103C standard). + * * A speed code matching the requested + * baud rate (potentially rounded down, + * if there is no exact match). + * + * Notes: This function is used for TIOCGETP, TIOCSETP, and TIOCSETN. + */ static int -ttcompatspeedtab(speed, table) - int speed; - register struct speedtab *table; +ttcompatspeedtab(int speed, struct speedtab *table) { if (speed == 0) return (0); /* hangup */ @@ -129,26 +157,74 @@ ttcompatspeedtab(speed, table) return (1); /* 50, min and not hangup */ } -#ifndef NeXT -int -ttsetcompat(tp, com, data, term) - register struct tty *tp; - int *com; - caddr_t data; - struct termios *term; -#else -__private_extern__ int -ttsetcompat(tp, com, data, term) - register struct tty *tp; - u_long *com; - caddr_t data; - struct termios *term; -#endif /* !NeXT */ + +/* + * 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 . + */ +static int +ttsetcompat(struct tty *tp, u_long *com, caddr_t data, struct termios *term) { switch (*com) { case TIOCSETP: - case TIOCSETN: { - register struct sgttyb *sg = (struct sgttyb *)data; + /* + * 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. + */ + { + struct sgttyb *sg = (struct sgttyb *)data; int speed; if ((speed = sg->sg_ispeed) > MAX_SPEED || speed < 0) @@ -170,9 +246,14 @@ ttsetcompat(tp, com, data, term) *com = (*com == TIOCSETP) ? TIOCSETAF : TIOCSETA; break; } - case TIOCSETC: { + 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_t *cc; cc = term->c_cc; cc[VINTR] = tc->t_intrc; @@ -186,9 +267,14 @@ ttsetcompat(tp, com, data, term) *com = TIOCSETA; break; } - case TIOCSLTC: { + 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_t *cc; cc = term->c_cc; cc[VSUSP] = ltc->t_suspc; @@ -201,8 +287,23 @@ ttsetcompat(tp, com, data, term) 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 { @@ -220,23 +321,44 @@ ttsetcompat(tp, com, data, term) return 0; } +/* + * ttcompat + * + * Description: For 'set' commands, convert the command and arguments as + * necessary, and call ttioctl_locked(), returning the result + * as our result; for 'get' commands, obtain the requested data + * from the appropriate source, and return it in the expected + * format. If the command is not recognized, return EINVAL. + * + * Parameters struct tty *tp The tty on which the operation is + * being performed. + * u_long com The terminal input/output command + * being requested. + * caddr_t data The pointer to the user data argument + * provided with the command. + * int flag The file open flags (e.g. FREAD). + * struct proc *p The current process pointer for the + * operation. + * + * Returns: 0 Most 'get' operations can't fail, and + * therefore return this. + * ENOTTY TIOCGSID may return this when you + * attempt to get the session ID for a + * terminal with no associated session, + * or for which there is a session, but + * no session leader. + * ENOTTY If the command cannot be handled at + * this layer, this will be returned. + * * Any value returned by ttioctl_locked(), + * if a set command is requested. + * + * Notes: The process pointer may be a proxy on whose behalf we are + * operating, so it is not safe to simply use current_process() + * instead. + */ /*ARGSUSED*/ -#ifndef NeXT -int -ttcompat(tp, com, data, flag) - register struct tty *tp; - int com; - caddr_t data; - int flag; -#else __private_extern__ int -ttcompat(tp, com, data, flag, p) - register struct tty *tp; - u_long com; - caddr_t data; - int flag; - struct proc *p; -#endif /* !NeXT */ +ttcompat(struct tty *tp, u_long com, caddr_t data, int flag, struct proc *p) { switch (com) { case TIOCSETP: @@ -245,22 +367,28 @@ ttcompat(tp, com, data, flag, p) case TIOCSLTC: case TIOCLBIS: case TIOCLBIC: - case TIOCLSET: { + 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; -#ifdef NeXT - return ttioctl(tp, com, (caddr_t) &term, flag, p); -#else - return ttioctl(tp, com, &term, flag); -#endif + return ttioctl_locked(tp, com, (caddr_t) &term, flag, p); } - case TIOCGETP: { - register struct sgttyb *sg = (struct sgttyb *)data; - register cc_t *cc = tp->t_cc; + case TIOCGETP: + /* + * Get the current input and output speeds, and device + * flags, into the structure pointed to by 'data'. + */ + { + 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) @@ -272,9 +400,14 @@ ttcompat(tp, com, data, flag, p) sg->sg_flags = tp->t_flags = ttcompatgetflags(tp); break; } - case TIOCGETC: { + 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; + cc_t *cc = tp->t_cc; tc->t_intrc = cc[VINTR]; tc->t_quitc = cc[VQUIT]; @@ -284,9 +417,14 @@ ttcompat(tp, com, data, flag, p) tc->t_brkc = cc[VEOL]; break; } - case TIOCGLTC: { + 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; + cc_t *cc = tp->t_cc; ltc->t_suspc = cc[VSUSP]; ltc->t_dsuspc = cc[VDSUSP]; @@ -297,44 +435,47 @@ ttcompat(tp, com, data, flag, p) 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; -#ifndef NeXT - if (ttydebug) - printf("CLGET: returning %x\n", *(int *)data); -#endif 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; -#ifndef NeXT - 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)); -#else - case OTIOCSETD: { + case OTIOCSETD: + /* + * Set the current line discipline based on the value of the + * int pointed to by 'data'. + */ + { int ldisczero = 0; - return (ttioctl(tp, TIOCSETD, + 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(tp, TIOCCONS, data, flag, p)); + 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; @@ -343,23 +484,44 @@ ttcompat(tp, com, data, flag, p) *(int *) data = tp->t_session->s_leader->p_pid; break; -#endif /* NeXT */ default: - return (-1); + /* + * This ioctl is not handled at this layer. + */ + return (ENOTTY); } + + /* + * Successful 'get' operation. + */ return (0); } +/* + * ttcompatgetflags + * + * Description: Get the terminal state local flags, device flags, and current + * speed code for the device (all 32 bits are returned). + * + * Parameters struct tty *tp The tty on which the operation is + * being performed. + * + * Returns: * Integer value corresponding to the + * current terminal state local flags + * word. + * + * Notes: Caller is responsible for breaking these bits back out into + * separate 16 bit filelds, if that's what was actually desired. + */ static int -ttcompatgetflags(tp) - register struct tty *tp; +ttcompatgetflags(struct tty *tp) { - register tcflag_t iflag = tp->t_iflag; - register tcflag_t lflag = tp->t_lflag; - register tcflag_t oflag = tp->t_oflag; - register tcflag_t cflag = tp->t_cflag; - register flags = 0; + tcflag_t iflag = tp->t_iflag; + tcflag_t lflag = tp->t_lflag; + tcflag_t oflag = tp->t_oflag; + tcflag_t cflag = tp->t_cflag; + int flags = 0; if (iflag&IXOFF) flags |= TANDEM; @@ -383,12 +545,12 @@ ttcompatgetflags(tp) if ((lflag&ICANON) == 0) { /* fudge */ if (iflag&(INPCK|ISTRIP|IXON) || lflag&(IEXTEN|ISIG) - || cflag&(CSIZE|PARENB) != CS8) + || (cflag&(CSIZE|PARENB)) != CS8) flags |= CBREAK; else flags |= RAW; } - if (!(flags&RAW) && !(oflag&OPOST) && cflag&(CSIZE|PARENB) == CS8) + if (!(flags&RAW) && !(oflag&OPOST) && (cflag&(CSIZE|PARENB)) == CS8) flags |= LITOUT; if (cflag&MDMBUF) flags |= MDMBUF; @@ -407,23 +569,31 @@ ttcompatgetflags(tp) if ((iflag&IXANY) == 0) flags |= DECCTQ; flags |= lflag&(ECHO|TOSTOP|FLUSHO|PENDIN|NOFLSH); -#ifndef NeXT - if (ttydebug) - printf("getflags: %x\n", flags); -#endif return (flags); } +/* + * ttcompatsetflags + * + * Description: Given a set of compatability flags, convert the compatability + * flags in the terminal flags fields into canonical flags in the + * provided termios struct. + * + * Parameters: struct tty *tp The tty on which the operation is + * being performed. + * struct termios *t The termios structure into which to + * return the converted flags. + * + * Returns: void (implicit: *t, modified) + */ static void -ttcompatsetflags(tp, t) - register struct tty *tp; - register struct termios *t; +ttcompatsetflags(struct tty *tp, struct termios *t) { - register flags = tp->t_flags; - register tcflag_t iflag = t->c_iflag; - register tcflag_t oflag = t->c_oflag; - register tcflag_t lflag = t->c_lflag; - register tcflag_t cflag = t->c_cflag; + int flags = tp->t_flags; + tcflag_t iflag = t->c_iflag; + tcflag_t oflag = t->c_oflag; + tcflag_t lflag = t->c_lflag; + tcflag_t cflag = t->c_cflag; if (flags & RAW) { iflag = IGNBRK; @@ -493,16 +663,28 @@ ttcompatsetflags(tp, t) t->c_cflag = cflag; } +/* + * ttcompatsetlflags + * + * Description: Given a set of compatability terminal state local flags, + * convert the compatability flags in the terminal flags + * fields into canonical flags in the provided termios struct. + * + * Parameters: struct tty *tp The tty on which the operation is + * being performed. + * struct termios *t The termios structure into which to + * return the converted local flags. + * + * Returns: void (implicit: *t, modified) + */ static void -ttcompatsetlflags(tp, t) - register struct tty *tp; - register struct termios *t; +ttcompatsetlflags(struct tty *tp, struct termios *t) { - register flags = tp->t_flags; - register tcflag_t iflag = t->c_iflag; - register tcflag_t oflag = t->c_oflag; - register tcflag_t lflag = t->c_lflag; - register tcflag_t cflag = t->c_cflag; + int flags = tp->t_flags; + tcflag_t iflag = t->c_iflag; + tcflag_t oflag = t->c_oflag; + tcflag_t lflag = t->c_lflag; + tcflag_t cflag = t->c_cflag; iflag &= ~(PARMRK|IGNPAR|IGNCR|INLCR); if (flags&CRTERA) @@ -570,4 +752,3 @@ ttcompatsetlflags(tp, t) t->c_lflag = lflag; t->c_cflag = cflag; } -#endif /* COMPAT_43 || COMPAT_SUNOS */