We’re facing issues with the input redirection in shell (specifically with the 
input redirection from ASCII file).
I’m wondering if anybody faced similar issues, or perhaps, Shell developers can 
provide some insights.

According to Shell specification (section 3.4.4.2) shell supports input 
redirection using the following syntax:
‘Command <  filename’ to redirect standard input from a Unicode file.
‘Command <a  filename’ to redirect standard input from an ASCII file.

Here is the e-mail from one of our developers describing the issues we faced 
and workarounds we came up with:

=====
I faced an issue with input redirection in shell.
It is working with Unicode file, but not working with ASCII file.

I tried to experiment with the “ls –b” command.
The command prints one screen and requests user confirmation to continue 
(“Press ENTER to continue or “Q” break:”).
I created a Unicode file 1.txt which contains only “q”.
When I use command “ls –b < 1.txt” the command behaves as expected: prints a 
single screen and exists as if I pressed “q”.
When I converted the same file to ASCII and tried to run “ls –b <a 1.txt” 
command, the command didn’t work as expected.
After displaying the first screen the command printed the message “Press ENTER 
to continue or “Q” break:” numerous times (about 20) and finally exited without 
reading the “q” key.

I made a fix in FileInterfaceFileRead function in FileHandleWrappers.c file 
(see the patch below).
The function reads ASCII input string and converts it to a Unicode string using 
UnicodeSPrint function:
UnicodeSPrint(Buffer, *BufferSize, L"%a", AsciiBuffer);

The problem is that the *BufferSize that is coming to a function as an input 
parameter is not large enough to add a NULL terminator.
In case of “ls –b” command, the *BufferSize is 2,  and UnicodeSPrint produces a 
blank string.
I tried to use UnicodeSPrint with a temporary buffer that is large enough for a 
NULL terminator. Once string is converted I use CopyMem to copy data(excluding 
NULL terminator) to the original Buffer.
These changes resolved the original problem (the redirection from ASCII file 
worked fine); however, I noticed another problem.
If 1.txt ASCII file contains multiple characters, for example “abcdefg” each 
even character is skipped (using the same command  “ls –b <a 1.txt”) and the 
result is as if user pressed a, c, e, g characters on each “Press ENTER to 
continue or “Q” break:” request.

I found out that this is because size passed to 
(((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Read(((EFI_FILE_PROTOCOL_FILE*)This)->Orig,
 &Size, AsciiBuffer));  function is equal to a total Unicode buffer size, which 
means the function will read more ASCII characters that can actually fit into a 
Unicode buffer(twice as much).
After setting  Size to a half of the Unicode buffer size (*BufferSize/2) the 
problem was fixed; however, another problem arose: it looks like content of the 
redirection file affects the redirection behavior.
For example having “eeeeq”  will results in reading all characters including q. 
While having “acdeq” will result in successfully reading only a and c and 
throwing a lot of “Press ENTER to continue or “Q” break:” messages after that 
like it was described in the beginning.

Here is the modifications I’ve made:

diff --git a/ShellPkg/Application/Shell/FileHandleWrappers.c 
b/ShellPkg/Application/Shell/FileHandleWrappers.c
index 18b6c3e..8903c50 100644
--- a/ShellPkg/Application/Shell/FileHandleWrappers.c
+++ b/ShellPkg/Application/Shell/FileHandleWrappers.c
@@ -1671,7 +1671,9 @@ FileInterfaceFileRead(
   )
{
   CHAR8       *AsciiBuffer;
+  VOID       *TmpBuf;
   UINTN       Size;
+  UINTN                   Number = 0;
   EFI_STATUS  Status;
   if (((EFI_FILE_PROTOCOL_FILE*)This)->Unicode) {
     //
@@ -1683,9 +1685,22 @@ FileInterfaceFileRead(
     // Ascii
     //
     AsciiBuffer = AllocateZeroPool((Size = *BufferSize));
+    Size = *BufferSize/2;
     Status = 
(((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Read(((EFI_FILE_PROTOCOL_FILE*)This)->Orig,
 &Size, AsciiBuffer));
-    UnicodeSPrint(Buffer, *BufferSize, L"%a", AsciiBuffer);
+    if (!EFI_ERROR(Status))
+    {
+      TmpBuf = AllocateZeroPool((*BufferSize + 2)); //UnicodeSPrint adds null 
terminator to any output so we need a bigger buffer
+      Number = UnicodeSPrint(TmpBuf, *BufferSize + 2, L"%a", AsciiBuffer);
+      if (Number)
+             CopyMem (Buffer, TmpBuf, *BufferSize); //Copy output to final 
destination without null terminator.
+      FreePool(TmpBuf);
+    }
     FreePool(AsciiBuffer);
+    if (Number)
+      *BufferSize = Number*2;
+    else
+      *BufferSize = Size*2;
+
     return (Status);
   }
}
==

Thanks
Felix


The information contained in this message may be confidential and proprietary 
to American Megatrends, Inc.  This communication is intended to be read only by 
the individual or entity to whom it is addressed or by their designee. If the 
reader of this message is not the intended recipient, you are on notice that 
any distribution of this message, in any form, is strictly prohibited.  Please 
promptly notify the sender by reply e-mail or by telephone at 770-246-8600, and 
then delete or destroy all copies of the transmission.
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to