123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732 |
- /*++
- Copyright (c) 2013 Minoca Corp.
- This file is licensed under the terms of the GNU General Public License
- version 3. Alternative licensing terms are available. Contact
- info@minocacorp.com for details. See the LICENSE file at the root of this
- project for complete licensing information.
- Module Name:
- termios.c
- Abstract:
- This module implements terminal support.
- Author:
- Evan Green 23-Jun-2013
- Environment:
- User Mode C Library
- --*/
- //
- // ------------------------------------------------------------------- Includes
- //
- #include "libcp.h"
- #include <assert.h>
- #include <errno.h>
- #include <string.h>
- #include <sys/ioctl.h>
- #include <termios.h>
- #include <unistd.h>
- //
- // ---------------------------------------------------------------------- Macro
- //
- //
- // This macro asserts that the terminal flags are equivalent between the
- // kernel and the C library.
- //
- #define ASSERT_TERMINAL_FLAGS_EQUIVALENT() \
- assert((BRKINT == TERMINAL_INPUT_SIGNAL_ON_BREAK) && \
- (ICRNL == TERMINAL_INPUT_CR_TO_NEWLINE) && \
- (IGNBRK == TERMINAL_INPUT_IGNORE_BREAK) && \
- (IGNCR == TERMINAL_INPUT_IGNORE_CR) && \
- (IGNPAR == TERMINAL_INPUT_IGNORE_PARITY_ERRORS) && \
- (INLCR == TERMINAL_INPUT_NEWLINE_TO_CR) && \
- (INPCK == TERMINAL_INPUT_ENABLE_PARITY_CHECK) && \
- (ISTRIP == TERMINAL_INPUT_STRIP) && \
- (IXANY == TERMINAL_INPUT_ANY_CHARACTER_RESTARTS_OUTPUT) && \
- (IXOFF == TERMINAL_INPUT_ENABLE_INPUT_FLOW_CONTROL) && \
- (IXON == TERMINAL_INPUT_ENABLE_OUTPUT_FLOW_CONTROL) && \
- (IMAXBEL == TERMINAL_INPUT_MAX_BELL) && \
- (PARMRK == TERMINAL_INPUT_MARK_PARITY_ERRORS) && \
- (OPOST == TERMINAL_OUTPUT_POST_PROCESS) && \
- (ONLCR == TERMINAL_OUTPUT_NEWLINE_TO_CRLF) && \
- (OCRNL == TERMINAL_OUTPUT_CR_TO_NEWLINE) && \
- (ONOCR == TERMINAL_OUTPUT_NO_CR_AT_COLUMN_ZERO) && \
- (ONLRET == TERMINAL_OUTPUT_NEWLINE_IS_CR) && \
- (OFILL == TERMINAL_OUTPUT_USE_FILL_CHARACTERS) && \
- (NLDLY == TERMINAL_OUTPUT_NEWLINE_DELAY) && \
- (NL0 == 0) && \
- (NL1 == TERMINAL_OUTPUT_NEWLINE_DELAY) && \
- (CRDLY == TERMINAL_OUTPUT_CR_DELAY_MASK) && \
- (CR0 == 0) && \
- (CR1 == TERMINAL_OUTPUT_CR_DELAY_1) && \
- (CR2 == TERMINAL_OUTPUT_CR_DELAY_2) && \
- (CR3 == TERMINAL_OUTPUT_CR_DELAY_3) && \
- (TABDLY == TERMINAL_OUTPUT_TAB_DELAY_MASK) && \
- (TAB0 == 0) && \
- (TAB1 == TERMINAL_OUTPUT_TAB_DELAY_1) && \
- (TAB2 == TERMINAL_OUTPUT_TAB_DELAY_2) && \
- (TAB3 == TERMINAL_OUTPUT_TAB_DELAY_3) && \
- (BSDLY == TERMINAL_OUTPUT_BACKSPACE_DELAY) && \
- (BS0 == 0) && \
- (BS1 == TERMINAL_OUTPUT_BACKSPACE_DELAY) && \
- (VTDLY == TERMINAL_OUTPUT_VERTICAL_TAB_DELAY) && \
- (VT0 == 0) && \
- (VT1 == TERMINAL_OUTPUT_VERTICAL_TAB_DELAY) && \
- (FFDLY == TERMINAL_OUTPUT_FORM_FEED_DELAY) && \
- (FF0 == 0) && \
- (FF1 == TERMINAL_OUTPUT_FORM_FEED_DELAY) && \
- (OFDEL == TERMINAL_OUTPUT_FILL_DEL) && \
- (CSIZE == TERMINAL_CONTROL_CHARACTER_SIZE_MASK) && \
- (CS5 == TERMINAL_CONTROL_5_BITS_PER_CHARACTER) && \
- (CS6 == TERMINAL_CONTROL_6_BITS_PER_CHARACTER) && \
- (CS7 == TERMINAL_CONTROL_7_BITS_PER_CHARACTER) && \
- (CS8 == TERMINAL_CONTROL_8_BITS_PER_CHARACTER) && \
- (CSTOPB == TERMINAL_CONTROL_2_STOP_BITS) && \
- (CREAD == TERMINAL_CONTROL_ENABLE_RECEIVE) && \
- (PARENB == TERMINAL_CONTROL_ENABLE_PARITY) && \
- (PARODD == TERMINAL_CONTROL_ODD_PARITY) && \
- (HUPCL == TERMINAL_CONTROL_HANGUP_ON_CLOSE) && \
- (CLOCAL == TERMINAL_CONTROL_NO_HANGUP) && \
- (ECHO == TERMINAL_LOCAL_ECHO) && \
- (ECHOE == TERMINAL_LOCAL_ECHO_ERASE) && \
- (ECHOK == TERMINAL_LOCAL_ECHO_KILL_NEWLINE) && \
- (ECHOKE == TERMINAL_LOCAL_ECHO_KILL_EXTENDED) && \
- (ECHONL == TERMINAL_LOCAL_ECHO_NEWLINE) && \
- (ECHOCTL == TERMINAL_LOCAL_ECHO_CONTROL) && \
- (ICANON == TERMINAL_LOCAL_CANONICAL) && \
- (IEXTEN == TERMINAL_LOCAL_EXTENDED) && \
- (ISIG == TERMINAL_LOCAL_SIGNALS) && \
- (NOFLSH == TERMINAL_LOCAL_NO_FLUSH) && \
- (TOSTOP == TERMINAL_LOCAL_STOP_BACKGROUND_WRITES))
- //
- // ---------------------------------------------------------------- Definitions
- //
- //
- // ------------------------------------------------------ Data Type Definitions
- //
- //
- // ----------------------------------------------- Internal Function Prototypes
- //
- //
- // -------------------------------------------------------------------- Globals
- //
- //
- // ------------------------------------------------------------------ Functions
- //
- LIBC_API
- int
- isatty (
- int FileDescriptor
- )
- /*++
- Routine Description:
- This routine determines if the given file descriptor is backed by an
- interactive terminal device or not.
- Arguments:
- FileDescriptor - Supplies the file descriptor to query.
- Return Value:
- 1 if the given file descriptor is backed by a terminal device.
- 0 on error or if the file descriptor is not a terminal device. On error,
- the errno variable will be set to give more details.
- --*/
- {
- struct termios Settings;
- if (tcgetattr(FileDescriptor, &Settings) == 0) {
- return 1;
- }
- return 0;
- }
- LIBC_API
- int
- tcgetattr (
- int FileDescriptor,
- struct termios *Settings
- )
- /*++
- Routine Description:
- This routine gets the current terminal settings.
- Arguments:
- FileDescriptor - Supplies the file descriptor for the terminal.
- Settings - Supplies a pointer where the terminal settings will be returned
- on success.
- Return Value:
- 0 on success.
- -1 on failure, and the errno variable will be set to provide more
- information.
- --*/
- {
- return ioctl(FileDescriptor, TCGETS, Settings);
- }
- LIBC_API
- int
- tcsetattr (
- int FileDescriptor,
- int When,
- const struct termios *NewSettings
- )
- /*++
- Routine Description:
- This routine sets the given terminal's attributes.
- Arguments:
- FileDescriptor - Supplies the file descriptor for the terminal.
- When - Supplies more information about when the new settings should take
- effect. See TCSA* definitions.
- NewSettings - Supplies a pointer to the new settings.
- Return Value:
- 0 on success.
- -1 on failure, and the errno variable will be set to provide more
- information.
- --*/
- {
- int Result;
- if (When == TCSANOW) {
- Result = ioctl(FileDescriptor, TCSETS, NewSettings);
- } else if (When == TCSADRAIN) {
- Result = ioctl(FileDescriptor, TCSETSW, NewSettings);
- } else if (When == TCSAFLUSH) {
- Result = ioctl(FileDescriptor, TCSETSF, NewSettings);
- } else {
- errno = EINVAL;
- Result = -1;
- }
- return Result;
- }
- LIBC_API
- speed_t
- cfgetispeed (
- const struct termios *Settings
- )
- /*++
- Routine Description:
- This routine gets the input baud rate from the given terminal settings.
- Arguments:
- Settings - Supplies a pointer to the terminal settings retrieved with a
- call to tcgetattr.
- Return Value:
- Returns the input speed, in baud.
- --*/
- {
- return Settings->c_ispeed;
- }
- LIBC_API
- speed_t
- cfgetospeed (
- const struct termios *Settings
- )
- /*++
- Routine Description:
- This routine gets the output baud rate from the given terminal settings.
- Arguments:
- Settings - Supplies a pointer to the terminal settings retrieved with a
- call to tcgetattr.
- Return Value:
- Returns the output speed, in baud.
- --*/
- {
- return Settings->c_ospeed;
- }
- LIBC_API
- int
- cfsetispeed (
- struct termios *Settings,
- speed_t NewBaudRate
- )
- /*++
- Routine Description:
- This routine sets the input baud rate from the given terminal settings.
- Arguments:
- Settings - Supplies a pointer to the terminal settings retrieved with a
- call to tcgetattr.
- NewBaudRate - Supplies the new input baud rate to set.
- Return Value:
- 0 on success.
- -1 on failure, and the errno will be set to EINVAL to indicate the given
- baud rate is invalid or not achievable.
- --*/
- {
- Settings->c_ispeed = NewBaudRate;
- return 0;
- }
- LIBC_API
- int
- cfsetospeed (
- struct termios *Settings,
- speed_t NewBaudRate
- )
- /*++
- Routine Description:
- This routine sets the output baud rate from the given terminal settings.
- Arguments:
- Settings - Supplies a pointer to the terminal settings retrieved with a
- call to tcgetattr.
- NewBaudRate - Supplies the new output baud rate to set.
- Return Value:
- 0 on success.
- -1 on failure, and the errno will be set to EINVAL to indicate the given
- baud rate is invalid or not achievable.
- --*/
- {
- Settings->c_ospeed = NewBaudRate;
- return 0;
- }
- LIBC_API
- void
- cfmakeraw (
- struct termios *Settings
- )
- /*++
- Routine Description:
- This routine sets the given settings to "raw" mode, disabling all line
- processing features and making the terminal as basic as possible.
- Arguments:
- Settings - Supplies a pointer to the terminal settings to adjust to raw
- mode.
- Return Value:
- None.
- --*/
- {
- Settings->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR |
- ICRNL | IXON | IMAXBEL);
- Settings->c_oflag &= ~OPOST;
- Settings->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
- Settings->c_cflag &= ~(CSIZE | PARENB);
- Settings->c_cflag |= CS8;
- Settings->c_cc[VMIN] = 1;
- Settings->c_cc[VTIME] = 0;
- return;
- }
- LIBC_API
- int
- tcflush (
- int FileDescriptor,
- int Selector
- )
- /*++
- Routine Description:
- This routine discards data written to the the given terminal, data received
- but not yet read from the terminal, or both.
- Attempts to use this function from a process which is a member of the
- background process group on the given terminal will cause the process group
- to be sent a SIGTTOU. If the calling process is blocking or ignoring
- SIGTTOU, the process shall be allowed to perform the operation, and no
- signal is sent.
- Arguments:
- FileDescriptor - Supplies the file descriptor of the terminal to flush.
- Selector - Supplies the type of flush to perform. Valid values are
- TCIFLUSH to flush data received but not read, TCOFLUSH to flush data
- written but not transmitted, and TCIOFLUSH to flush both types.
- Return Value:
- 0 on success.
- -1 on failure, and the errno will be set to contain more information.
- --*/
- {
- assert((TCIFLUSH == SYS_FLUSH_FLAG_READ) &&
- (TCOFLUSH == SYS_FLUSH_FLAG_WRITE) &&
- (TCIOFLUSH == (SYS_FLUSH_FLAG_READ | SYS_FLUSH_FLAG_WRITE)));
- return ioctl(FileDescriptor, TCFLSH, Selector);
- }
- LIBC_API
- int
- tcdrain (
- int FileDescriptor
- )
- /*++
- Routine Description:
- This routine waits until all output written to the terminal at the given
- file descriptor is written.
- Attempts to use this function from a process which is a member of the
- background process group on the given terminal will cause the process group
- to be sent a SIGTTOU. If the calling process is blocking or ignoring
- SIGTTOU, the process shall be allowed to perform the operation, and no
- signal is sent.
- Arguments:
- FileDescriptor - Supplies the file descriptor of the terminal to drain.
- Return Value:
- 0 on success.
- -1 on failure, and the errno will be set to contain more information.
- --*/
- {
- //
- // TCSBRK with a non-zero value is undefined, but in this implementation
- // implements tcdrain behavior.
- //
- return ioctl(FileDescriptor, TCSBRK, 1);
- }
- LIBC_API
- int
- tcflow (
- int FileDescriptor,
- int Action
- )
- /*++
- Routine Description:
- This routine suspends or restarts transmission of data on the given
- terminal.
- Attempts to use this function from a process which is a member of the
- background process group on the given terminal will cause the process group
- to be sent a SIGTTOU. If the calling process is blocking or ignoring
- SIGTTOU, the process shall be allowed to perform the operation, and no
- signal is sent.
- Arguments:
- FileDescriptor - Supplies the file descriptor of the terminal.
- Action - Supplies the action to perform. Valid values are:
- TCOOFF - Suspends output.
- TCOON - Resumes suspended output.
- TCIOFF - Causes the system to transmit a STOP character, which is
- intended to cause the terminal device to stop transmitting data to
- this system.
- TCION - Causes the system to transmit a START character, which is
- intended to restart the sending of data to this terminal.
- Return Value:
- 0 on success.
- -1 on failure, and the errno will be set to contain more information.
- --*/
- {
- return ioctl(FileDescriptor, TCXONC, Action);
- }
- LIBC_API
- int
- tcsendbreak (
- int FileDescriptor,
- int Duration
- )
- /*++
- Routine Description:
- This routine sends a continuous stream of zero-valued bits for a specific
- duration if the given terminal is using asynchronous serial data
- transmission. If the terminal is not using asynchronous serial data
- transmission, this routine returns without performing any action.
- Attempts to use this function from a process which is a member of the
- background process group on the given terminal will cause the process group
- to be sent a SIGTTOU. If the calling process is blocking or ignoring
- SIGTTOU, the process shall be allowed to perform the operation, and no
- signal is sent.
- Arguments:
- FileDescriptor - Supplies the file descriptor of the terminal.
- Duration - Supplies a value that if zero causes the duration to be between
- 0.25 and 0.5 seconds. If duration is not zero, it sends zero-valued
- bits for an implementation-defined length of time.
- Return Value:
- 0 on success.
- -1 on failure, and the errno will be set to contain more information.
- --*/
- {
- return ioctl(FileDescriptor, TCSBRK, Duration);
- }
- LIBC_API
- pid_t
- tcgetsid (
- int FileDescriptor
- )
- /*++
- Routine Description:
- This routine gets the process group ID of the session for which the
- terminal specified by the given file descriptor is the controlling terminal.
- Arguments:
- FileDescriptor - Supplies the file descriptor of the terminal.
- Return Value:
- Returns the process group ID associated with the terminal on success.
- -1 on failure, and errno will be set to contain more information.
- --*/
- {
- pid_t ProcessGroup;
- int Status;
- ProcessGroup = -1;
- Status = ioctl(FileDescriptor, TIOCGSID, &ProcessGroup);
- if (Status != 0) {
- return (pid_t)-1;
- }
- return ProcessGroup;
- }
- LIBC_API
- int
- tcsetpgrp (
- int FileDescriptor,
- pid_t ProcessGroupId
- )
- /*++
- Routine Description:
- This routine sets the foreground process group ID associated with the
- given terminal file descriptor. The application shall ensure that the file
- associated with the given descriptor is the controlling terminal of the
- calling process and the controlling terminal is currently associated with
- the session of the calling process. The application shall ensure that the
- given process group ID is led by a process in the same session as the
- calling process.
- Arguments:
- FileDescriptor - Supplies the file descriptor of the terminal.
- ProcessGroupId - Supplies the process group ID to set for the terminal.
- Return Value:
- 0 on success.
- -1 on failure, and the errno will be set to contain more information.
- --*/
- {
- PROCESS_GROUP_ID Identifier;
- Identifier = ProcessGroupId;
- return ioctl(FileDescriptor, TIOCSPGRP, &Identifier);
- }
- LIBC_API
- pid_t
- tcgetpgrp (
- int FileDescriptor
- )
- /*++
- Routine Description:
- This routine returns the value of the process group ID of the foreground
- process associated with the given terminal. If ther is no foreground
- process group, this routine returns a value greater than 1 that does not
- match the process group ID of any existing process group.
- Arguments:
- FileDescriptor - Supplies the file descriptor of the terminal.
- Return Value:
- Returns the process group ID of the foreground process associated with the
- terminal on success.
- -1 on failure, and errno will be set to contain more information. Possible
- values of errno are:
- EBADF if the file descriptor is invalid.
- ENOTTY if the calling process does not having a controlling terminal, or
- the file is not the controlling terminal.
- --*/
- {
- PROCESS_GROUP_ID Identifier;
- int Result;
- Result = ioctl(FileDescriptor, TIOCGPGRP, &Identifier);
- if (Result < 0) {
- return Result;
- }
- return (pid_t)Identifier;
- }
- //
- // --------------------------------------------------------- Internal Functions
- //
|