Adds a subset of the terminal I/O capabilities described in the Single Unix Specification, V4.
Supports:
    Erase previous character.  Default is Backspace or ^H
    Erase line.  Default is ^U
TAB characters are supported and, by default, are rendered as 8 spaces.  They will still be read as a single TAB character.
Both Canonical and Non-Canonical modes are supported.
If a terminal device is opened with O_TTY_INIT in the mode, the device will be initialized to "sane" values for interactive use.  It will be in Canonical mode, Enter will be translated to NewLine and on output, a NewLine is translated to CRLF.  Echoing will be on, control characters are output as ^X, and TABs are expanded.
See the new <sys/termios.h> file for more information.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by:  daryl.mcdaniel@intel.com
Reviewed-by:    erik.c.bjorge@intel.com
Reviewed-by:    leroy.p.leahy@intel.com
Reviewed-by:    lee.g.rosenbaum@intel.com
Reviewed-by:    jaben.carsey@intel.com
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13989 6f19259b-4bc3-4df7-8a09-765794883524
		
	
		
			
				
	
	
		
			162 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			162 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   Canonical Interactive Input Function.
 | |
| 
 | |
|   The functions assume that isatty() is TRUE at the time they are called.
 | |
| 
 | |
|   Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>
 | |
|   This program and the accompanying materials are licensed and made available
 | |
|   under the terms and conditions of the BSD License which accompanies this
 | |
|   distribution.  The full text of the license may be found at
 | |
|   http://opensource.org/licenses/bsd-license.php.
 | |
| 
 | |
|   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | |
|   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | |
| **/
 | |
| #include  <Uefi.h>
 | |
| 
 | |
| #include  <LibConfig.h>
 | |
| 
 | |
| #include  <errno.h>
 | |
| #include  <sys/syslimits.h>
 | |
| #include  <sys/termios.h>
 | |
| #include  <Device/IIO.h>
 | |
| #include  <MainData.h>
 | |
| #include  "IIOutilities.h"
 | |
| #include  "IIOechoCtrl.h"
 | |
| 
 | |
| /** Read a line from the input file in canonical mode.
 | |
|     Perform echoing and input processing as directed by the termios flags.
 | |
| 
 | |
|     @param[in]    filp      A pointer to a file descriptor structure.
 | |
| 
 | |
|     @return     The number of characters in the input buffer, or -1 if there
 | |
|                 was an error.
 | |
| **/
 | |
| ssize_t
 | |
| IIO_CanonRead (
 | |
|   struct __filedes *filp
 | |
|   )
 | |
| {
 | |
|   cIIO             *This;
 | |
|   cFIFO            *InBuf;
 | |
|   struct termios   *Termio;
 | |
|   struct __filedes *fpOut;
 | |
|   size_t            NumRead;
 | |
|   wint_t            InChar;
 | |
|   tcflag_t          IFlag;
 | |
|   tcflag_t          LFlag;
 | |
|   BOOLEAN           EchoIsOK;
 | |
|   BOOLEAN           Activate;
 | |
|   BOOLEAN           FirstRead;
 | |
|   int               OutMode;
 | |
|   UINTN             MaxColumn;
 | |
|   UINTN             MaxRow;
 | |
| 
 | |
|   NumRead   = MAX_INPUT;    // Workaround "potentially uninitialized" warning
 | |
|   EchoIsOK  = FALSE;
 | |
|   FirstRead = TRUE;
 | |
|   This      = filp->devdata;
 | |
|   Termio    = &This->Termio;
 | |
|   InBuf     = This->InBuf;
 | |
| 
 | |
|   // Get a copy of the flags we are going to use
 | |
|   IFlag = Termio->c_iflag;
 | |
|   LFlag = Termio->c_lflag;
 | |
| 
 | |
|   /* Determine what the current screen size is. Also validates the output device. */
 | |
|   OutMode = IIO_GetOutputSize(STDOUT_FILENO, &MaxColumn, &MaxRow);
 | |
|   if(OutMode >= 0) {
 | |
|     /*  Set the maximum screen dimensions. */
 | |
|     This->MaxColumn = MaxColumn;
 | |
|     This->MaxRow    = MaxRow;
 | |
| 
 | |
|     /*  Record where the cursor is at the beginning of this Input operation.
 | |
|         The currently set stdout device is used to determine this.  If there is
 | |
|         no stdout, or stdout is not an interactive device, nothing is recorded.
 | |
|     */
 | |
|     if (IIO_GetCursorPosition(STDOUT_FILENO, &This->InitialXY.Column, &This->InitialXY.Row) >= 0) {
 | |
|       This->CurrentXY.Column  = This->InitialXY.Column;
 | |
|       This->CurrentXY.Row     = This->InitialXY.Row;
 | |
|       EchoIsOK  = TRUE;   // Can only echo to stdout
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   // For now, we only echo to stdout.
 | |
|   fpOut = &gMD->fdarray[STDOUT_FILENO];
 | |
| 
 | |
|   //  Input and process characters until BufferSize is exhausted.
 | |
|   do {
 | |
|     InChar = IIO_GetInChar(filp, FirstRead);
 | |
|     FirstRead = FALSE;
 | |
|     Activate  = TRUE;
 | |
|     if(InChar == CHAR_CARRIAGE_RETURN) {
 | |
|       if((IFlag & IGNCR) != 0) {
 | |
|         continue;   // Restart the do loop, discarding the CR
 | |
|       }
 | |
|       else if((IFlag & ICRNL) != 0) {
 | |
|         InChar = L'\n';
 | |
|       }
 | |
|     }
 | |
|     else if(InChar == CHAR_LINEFEED) {
 | |
|       if((IFlag & INLCR) != 0) {
 | |
|         InChar = L'\r';
 | |
|       }
 | |
|     }
 | |
|     else if(CCEQ(Termio->c_cc[VINTR], InChar)) {
 | |
|       if((LFlag & ISIG) != 0) {
 | |
|         // Raise Signal
 | |
|         // Flush Input Buffer
 | |
|         // Return to caller
 | |
|         InChar = IIO_ECHO_DISCARD;
 | |
|         errno = EINTR;
 | |
|       }
 | |
|       else {
 | |
|         Activate = FALSE;
 | |
|       }
 | |
|     }
 | |
|     else if(CCEQ(Termio->c_cc[VQUIT], InChar)) {
 | |
|       if((LFlag & ISIG) != 0) {
 | |
|         // Raise Signal
 | |
|         // Flush Input Buffer
 | |
|         // Return to caller
 | |
|         InChar = IIO_ECHO_DISCARD;
 | |
|         errno = EINTR;
 | |
|       }
 | |
|       else {
 | |
|         Activate = FALSE;
 | |
|       }
 | |
|     }
 | |
|     else if(CCEQ(Termio->c_cc[VEOF], InChar)) {
 | |
|       InChar = WEOF;
 | |
|     }
 | |
|     else if(CCEQ(Termio->c_cc[VEOL], InChar)) {
 | |
|       EchoIsOK = FALSE;   // Buffer, but don't echo this character
 | |
|     }
 | |
|     else if(CCEQ(Termio->c_cc[VERASE], InChar)) {
 | |
|       InChar = IIO_ECHO_ERASE;
 | |
|       Activate = FALSE;
 | |
|     }
 | |
|     else if(CCEQ(Termio->c_cc[VKILL], InChar)) {
 | |
|       InChar = IIO_ECHO_KILL;
 | |
|       Activate = FALSE;
 | |
|     }
 | |
|     else {
 | |
|       if((InChar < TtySpecKeyMin) || (InChar >= TtyFunKeyMax)) {
 | |
|         Activate = FALSE;
 | |
|       }
 | |
|     }
 | |
|     /** The Echo function is responsible for:
 | |
|           * Adding the character to the input buffer, if appropriate.
 | |
|           * Removing characters from the input buffer for ERASE and KILL processing.
 | |
|           * Visually removing characters from the screen if ECHOE is set.
 | |
|           * Ensuring one can not backspace beyond the beginning of the input text.
 | |
|           * Sending final echo strings to output.
 | |
|     **/
 | |
|     (void)This->Echo(fpOut, (wchar_t)InChar, EchoIsOK);
 | |
|     NumRead = InBuf->Count(InBuf, AsElements);
 | |
|   } while((NumRead < MAX_INPUT) &&
 | |
|           (Activate == FALSE));
 | |
| 
 | |
|   return (ssize_t)NumRead;
 | |
| }
 |