• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   Canonical Interactive Input Function.
3 
4   The functions assume that isatty() is TRUE at the time they are called.
5 
6   Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved.<BR>
7   This program and the accompanying materials are licensed and made available
8   under the terms and conditions of the BSD License which accompanies this
9   distribution.  The full text of the license may be found at
10   http://opensource.org/licenses/bsd-license.php.
11 
12   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14 **/
15 #include  <Uefi.h>
16 
17 #include  <LibConfig.h>
18 
19 #include  <errno.h>
20 #include  <sys/syslimits.h>
21 #include  <sys/termios.h>
22 #include  <Device/IIO.h>
23 #include  <MainData.h>
24 #include  "IIOutilities.h"
25 #include  "IIOechoCtrl.h"
26 
27 /** Read a line from the input file in canonical mode.
28     Perform echoing and input processing as directed by the termios flags.
29 
30     @param[in]    filp      A pointer to a file descriptor structure.
31 
32     @return     The number of characters in the input buffer, or -1 if there
33                 was an error.
34 **/
35 ssize_t
IIO_CanonRead(struct __filedes * filp)36 IIO_CanonRead (
37   struct __filedes *filp
38   )
39 {
40   cIIO             *This;
41   cFIFO            *InBuf;
42   struct termios   *Termio;
43   struct __filedes *fpOut;
44   size_t            NumRead;
45   wint_t            InChar;
46   tcflag_t          IFlag;
47   tcflag_t          LFlag;
48   BOOLEAN           EchoIsOK;
49   BOOLEAN           Activate;
50   BOOLEAN           FirstRead;
51   int               OutMode;
52   UINTN             MaxColumn;
53   UINTN             MaxRow;
54 
55   NumRead   = MAX_INPUT;    // Workaround "potentially uninitialized" warning
56   EchoIsOK  = FALSE;
57   FirstRead = TRUE;
58   This      = filp->devdata;
59   Termio    = &This->Termio;
60   InBuf     = This->InBuf;
61 
62   // Get a copy of the flags we are going to use
63   IFlag = Termio->c_iflag;
64   LFlag = Termio->c_lflag;
65 
66   /* Determine what the current screen size is. Also validates the output device. */
67   OutMode = IIO_GetOutputSize(STDOUT_FILENO, &MaxColumn, &MaxRow);
68   if(OutMode >= 0) {
69     /*  Set the maximum screen dimensions. */
70     This->MaxColumn = MaxColumn;
71     This->MaxRow    = MaxRow;
72 
73     /*  Record where the cursor is at the beginning of this Input operation.
74         The currently set stdout device is used to determine this.  If there is
75         no stdout, or stdout is not an interactive device, nothing is recorded.
76     */
77     if (IIO_GetCursorPosition(STDOUT_FILENO, &This->InitialXY.Column, &This->InitialXY.Row) >= 0) {
78       This->CurrentXY.Column  = This->InitialXY.Column;
79       This->CurrentXY.Row     = This->InitialXY.Row;
80       EchoIsOK  = TRUE;   // Can only echo to stdout
81     }
82   }
83 
84   // For now, we only echo to stdout.
85   fpOut = &gMD->fdarray[STDOUT_FILENO];
86 
87   //  Input and process characters until BufferSize is exhausted.
88   do {
89     InChar = IIO_GetInChar(filp, FirstRead);
90     if (InChar == WEOF) {
91       NumRead = 0;
92       break;
93     }
94     FirstRead = FALSE;
95     Activate  = TRUE;
96     if(InChar == CHAR_CARRIAGE_RETURN) {
97       if((IFlag & IGNCR) != 0) {
98         continue;   // Restart the do loop, discarding the CR
99       }
100       else if((IFlag & ICRNL) != 0) {
101         InChar = L'\n';
102       }
103     }
104     else if(InChar == CHAR_LINEFEED) {
105       if((IFlag & INLCR) != 0) {
106         InChar = L'\r';
107       }
108     }
109     else if(CCEQ(Termio->c_cc[VINTR], InChar)) {
110       if((LFlag & ISIG) != 0) {
111         // Raise Signal
112         // Flush Input Buffer
113         // Return to caller
114         InChar = IIO_ECHO_DISCARD;
115         errno = EINTR;
116       }
117       else {
118         Activate = FALSE;
119       }
120     }
121     else if(CCEQ(Termio->c_cc[VQUIT], InChar)) {
122       if((LFlag & ISIG) != 0) {
123         // Raise Signal
124         // Flush Input Buffer
125         // Return to caller
126         InChar = IIO_ECHO_DISCARD;
127         errno = EINTR;
128       }
129       else {
130         Activate = FALSE;
131       }
132     }
133     else if(CCEQ(Termio->c_cc[VEOF], InChar)) {
134       InChar = WEOF;
135       NumRead = 0;
136       EchoIsOK = FALSE;   // Buffer, but don't echo this character
137     }
138     else if(CCEQ(Termio->c_cc[VEOL], InChar)) {
139       EchoIsOK = FALSE;   // Buffer, but don't echo this character
140     }
141     else if(CCEQ(Termio->c_cc[VERASE], InChar)) {
142       InChar = IIO_ECHO_ERASE;
143       Activate = FALSE;
144     }
145     else if(CCEQ(Termio->c_cc[VKILL], InChar)) {
146       InChar = IIO_ECHO_KILL;
147       Activate = FALSE;
148     }
149     else {
150       if((InChar < TtySpecKeyMin) || (InChar >= TtyFunKeyMax)) {
151         Activate = FALSE;
152       }
153     }
154     /** The Echo function is responsible for:
155           * Adding the character to the input buffer, if appropriate.
156           * Removing characters from the input buffer for ERASE and KILL processing.
157           * Visually removing characters from the screen if ECHOE is set.
158           * Ensuring one can not backspace beyond the beginning of the input text.
159           * Sending final echo strings to output.
160     **/
161     (void)This->Echo(fpOut, (wchar_t)InChar, EchoIsOK);
162     NumRead = InBuf->Count(InBuf, AsElements);
163   } while((NumRead < MAX_INPUT) &&
164           (Activate == FALSE));
165 
166   return (ssize_t)NumRead;
167 }
168