]> git.proxmox.com Git - mirror_edk2.git/commitdiff
ShellPkg: Add pipe support for parse command
authorTapan Shah <tapandshah@hp.com>
Wed, 3 Jun 2015 20:33:41 +0000 (20:33 +0000)
committerjcarsey <jcarsey@Edk2>
Wed, 3 Jun 2015 20:33:41 +0000 (20:33 +0000)
parse reads data from StdIn when pipe is used and does not require –sfo output stored in a file. (e.g.:  fs0:\> ls *.nsh –sfo | parse FileInfo 2)

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Tapan Shah <tapandshah@hp.com>
Reviewed-by: Jaben Carsey <jaben.carsey@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17555 6f19259b-4bc3-4df7-8a09-765794883524

ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.c
ShellPkg/Library/UefiShellLevel2CommandsLib/Parse.c

index f2249257604459caed20378e7da0915ecf7eab31..b6d5d991a6786eee271023e9f8967449b5356eac 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Provides interface to shell internal functions for shell commands.\r
 \r
-  (C) Copyright 2013-2014 Hewlett-Packard Development Company, L.P.<BR>\r
+  (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.<BR>\r
   Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>\r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
@@ -1622,7 +1622,6 @@ ShellFileHandleEof(
 \r
   gEfiShellProtocol->GetFilePosition(Handle, &Pos);\r
   Info = gEfiShellProtocol->GetFileInfo (Handle);\r
-  ASSERT(Info != NULL);\r
   gEfiShellProtocol->SetFilePosition(Handle, Pos);\r
 \r
   if (Info == NULL) {\r
index 69a104389f0c09457ae71aa095262c9d9f03609c..545b7af3427f0a77edb336b18bf80712eb7d2692 100644 (file)
 \r
 #include "UefiShellLevel2CommandsLib.h"\r
 \r
+/**\r
+  Check if data is coming from StdIn output.\r
+\r
+  @param[in] None\r
\r
+  @retval TRUE  StdIn stream data available to parse \r
+  @retval FALSE StdIn stream data is not available to parse. \r
+**/\r
+BOOLEAN\r
+IsStdInDataAvailable (\r
+  VOID\r
+  )\r
+{\r
+  SHELL_FILE_HANDLE FileHandle;\r
+  EFI_STATUS        Status;\r
+  CHAR16            CharBuffer; \r
+  UINTN             CharSize;\r
+  UINT64            OriginalFilePosition;\r
+\r
+  Status               = EFI_SUCCESS; \r
+  FileHandle           = NULL;\r
+  OriginalFilePosition = 0;\r
+\r
+  if (ShellOpenFileByName (L">i", &FileHandle, EFI_FILE_MODE_READ, 0) == EFI_SUCCESS) {\r
+    CharSize = sizeof(CHAR16);\r
+    gEfiShellProtocol->GetFilePosition (FileHandle, &OriginalFilePosition);\r
+    Status = gEfiShellProtocol->ReadFile (FileHandle, &CharSize, &CharBuffer);\r
+    if (EFI_ERROR (Status) || (CharSize != sizeof(CHAR16))) {\r
+      return FALSE;\r
+    }\r
+    gEfiShellProtocol->SetFilePosition(FileHandle, OriginalFilePosition);\r
+  }\r
+\r
+  if (FileHandle == NULL) {\r
+    return FALSE;\r
+  } else {\r
+    return TRUE;\r
+  }\r
+}\r
+\r
+/**\r
+  Function to read a single line (up to but not including the \n) using StdIn data from a SHELL_FILE_HANDLE.\r
+\r
+  If the position upon start is 0, then the Ascii Boolean will be set.  This should be\r
+  maintained and not changed for all operations with the same file.\r
+\r
+  @param[in]       Handle        SHELL_FILE_HANDLE to read from.\r
+  @param[in, out]  Buffer        The pointer to buffer to read into.\r
+  @param[in, out]  Size          The pointer to number of bytes in Buffer.\r
+  @param[in]       Truncate      If the buffer is large enough, this has no effect.\r
+                                 If the buffer is is too small and Truncate is TRUE,\r
+                                 the line will be truncated.\r
+                                 If the buffer is is too small and Truncate is FALSE,\r
+                                 then no read will occur.\r
+\r
+  @retval EFI_SUCCESS           The operation was successful.  The line is stored in\r
+                                Buffer.\r
+  @retval EFI_INVALID_PARAMETER Handle was NULL.\r
+  @retval EFI_INVALID_PARAMETER Size was NULL.\r
+  @retval EFI_BUFFER_TOO_SMALL  Size was not large enough to store the line.\r
+                                Size was updated to the minimum space required.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ShellFileHandleReadStdInLine(\r
+  IN SHELL_FILE_HANDLE          Handle,\r
+  IN OUT CHAR16                 *Buffer,\r
+  IN OUT UINTN                  *Size,\r
+  IN BOOLEAN                    Truncate\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  CHAR16      CharBuffer;\r
+  UINTN       CharSize;\r
+  UINTN       CountSoFar;\r
+  UINT64      OriginalFilePosition;\r
+\r
+\r
+  if (Handle == NULL\r
+    ||Size   == NULL\r
+   ){\r
+    return (EFI_INVALID_PARAMETER);\r
+  }\r
+  if (Buffer == NULL) {\r
+    ASSERT(*Size == 0);\r
+  } else {\r
+    *Buffer = CHAR_NULL;\r
+  }\r
+  gEfiShellProtocol->GetFilePosition (Handle, &OriginalFilePosition);\r
+\r
+  for (CountSoFar = 0;;CountSoFar++){\r
+    CharBuffer = 0;\r
+    CharSize = sizeof(CHAR16);\r
+    Status = gEfiShellProtocol->ReadFile (Handle, &CharSize, &CharBuffer);\r
+    if (  EFI_ERROR(Status)\r
+       || CharSize == 0\r
+       || (CharBuffer == L'\n')\r
+     ){\r
+      break;\r
+    }\r
+    //\r
+    // if we have space save it...\r
+    //\r
+    if ((CountSoFar+1)*sizeof(CHAR16) < *Size){\r
+      ASSERT(Buffer != NULL);\r
+      ((CHAR16*)Buffer)[CountSoFar] = CharBuffer;\r
+      ((CHAR16*)Buffer)[CountSoFar+1] = CHAR_NULL;\r
+    }\r
+  }\r
+\r
+  //\r
+  // if we ran out of space tell when...\r
+  //\r
+  if ((CountSoFar+1)*sizeof(CHAR16) > *Size){\r
+    *Size = (CountSoFar+1)*sizeof(CHAR16);\r
+    if (!Truncate) {\r
+      gEfiShellProtocol->SetFilePosition(Handle, OriginalFilePosition);\r
+    } else {\r
+      DEBUG((DEBUG_WARN, "The line was truncated in ShellFileHandleReadLine"));\r
+    }\r
+    return (EFI_BUFFER_TOO_SMALL);\r
+  }\r
+  while(Buffer[StrLen(Buffer)-1] == L'\r') {\r
+    Buffer[StrLen(Buffer)-1] = CHAR_NULL;\r
+  }\r
+\r
+  return (Status);\r
+}\r
+\r
+\r
+/**\r
+  Function to read a single line using StdIn from a SHELL_FILE_HANDLE. The \n is not included in the returned\r
+  buffer.  The returned buffer must be callee freed.\r
+\r
+  If the position upon start is 0, then the Ascii Boolean will be set.  This should be\r
+  maintained and not changed for all operations with the same file.\r
+\r
+  @param[in]       Handle        SHELL_FILE_HANDLE to read from.\r
+\r
+  @return                        The line of text from the file.\r
+  @retval NULL                   There was not enough memory available.\r
+\r
+  @sa ShellFileHandleReadLine\r
+**/\r
+CHAR16*\r
+EFIAPI\r
+ParseReturnStdInLine (\r
+  IN SHELL_FILE_HANDLE Handle\r
+  )\r
+{\r
+  CHAR16          *RetVal;\r
+  UINTN           Size;\r
+  EFI_STATUS      Status;\r
+\r
+  Size   = 0;\r
+  RetVal = NULL;\r
+\r
+  Status = ShellFileHandleReadStdInLine (Handle, RetVal, &Size, FALSE);\r
+  if (Status == EFI_BUFFER_TOO_SMALL) {\r
+    RetVal = AllocateZeroPool(Size);\r
+    if (RetVal == NULL) {\r
+      return (NULL);\r
+    }\r
+    Status = ShellFileHandleReadStdInLine (Handle, RetVal, &Size, FALSE);\r
+\r
+  }\r
+  if (EFI_ERROR(Status) && (RetVal != NULL)) {\r
+    FreePool(RetVal);\r
+    RetVal = NULL;\r
+  }\r
+  return (RetVal);\r
+}\r
+\r
 /**\r
   Do the actual parsing of the file.  the file should be SFO output from a \r
   shell command or a similar format.\r
   @param[in] ColumnIndex            The column number to get.\r
   @param[in] TableNameInstance      Which instance of the table to get (row).\r
   @param[in] ShellCommandInstance   Which instance of the command to get.\r
+  @param[in] StreamingUnicode       Indicates Input file is StdIn Unicode streaming data or not\r
 \r
   @retval SHELL_NOT_FOUND     The requested instance was not found.\r
   @retval SHELL_SUCCESS       The operation was successful.\r
@@ -35,7 +209,8 @@ PerformParsing(
   IN CONST CHAR16 *TableName,\r
   IN CONST UINTN  ColumnIndex,\r
   IN CONST UINTN  TableNameInstance,\r
-  IN CONST UINTN  ShellCommandInstance\r
+  IN CONST UINTN  ShellCommandInstance,\r
+  IN BOOLEAN      StreamingUnicode\r
   )\r
 {\r
   SHELL_FILE_HANDLE FileHandle;\r
@@ -62,9 +237,14 @@ PerformParsing(
     ShellStatus = SHELL_NOT_FOUND;\r
   } else {\r
     for (LoopVariable = 0 ; LoopVariable < ShellCommandInstance && !ShellFileHandleEof(FileHandle);) {\r
-      TempLine = ShellFileHandleReturnLine(FileHandle, &Ascii);\r
-      if (TempLine == NULL) {\r
-        break;\r
+     if (StreamingUnicode) {\r
+       TempLine = ParseReturnStdInLine (FileHandle);\r
+     } else {\r
+       TempLine = ShellFileHandleReturnLine (FileHandle, &Ascii); \r
+     }\r
+\r
+      if ((TempLine == NULL) || (*TempLine == CHAR_NULL && StreamingUnicode == TRUE)) {\r
+         break;\r
       }\r
 \r
       //\r
@@ -80,7 +260,11 @@ PerformParsing(
     if (LoopVariable == ShellCommandInstance) {\r
       LoopVariable = 0;\r
       while(1) {\r
-        TempLine = ShellFileHandleReturnLine(FileHandle, &Ascii);\r
+        if (StreamingUnicode) {\r
+          TempLine = ParseReturnStdInLine (FileHandle);\r
+        } else {\r
+          TempLine = ShellFileHandleReturnLine (FileHandle, &Ascii); \r
+        }\r
         if (TempLine == NULL\r
             || *TempLine == CHAR_NULL\r
             || StrStr (TempLine, L"ShellCommand,") == TempLine) {\r
@@ -99,7 +283,7 @@ PerformParsing(
             }\r
             if (ColumnLoop == ColumnIndex) {\r
               if (ColumnPointer == NULL) {\r
-              ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellLevel2HiiHandle, L"parse", L"Column Index");  \r
+                ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellLevel2HiiHandle, L"parse", L"Column Index");  \r
                 ShellStatus = SHELL_INVALID_PARAMETER;\r
               } else {\r
                 TempSpot = StrStr (ColumnPointer, L",\"");\r
@@ -156,9 +340,11 @@ ShellCommandRunParse (
   SHELL_STATUS        ShellStatus;\r
   UINTN               ShellCommandInstance;\r
   UINTN               TableNameInstance;\r
+  BOOLEAN             StreamingUnicode;\r
 \r
-  ShellStatus   = SHELL_SUCCESS;\r
-  ProblemParam  = NULL;\r
+  ShellStatus      = SHELL_SUCCESS;\r
+  ProblemParam     = NULL;\r
+  StreamingUnicode = FALSE;\r
 \r
   //\r
   // initialize the shell lib (we must be in non-auto-init...)\r
@@ -169,7 +355,7 @@ ShellCommandRunParse (
   //\r
   // parse the command line\r
   //\r
-  Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);\r
+  Status = ShellCommandLineParseEx (ParamList, &Package, &ProblemParam, TRUE, FALSE);\r
   if (EFI_ERROR(Status)) {\r
     if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {\r
       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"parse", ProblemParam);  \r
@@ -179,17 +365,25 @@ ShellCommandRunParse (
       ASSERT(FALSE);\r
     }\r
   } else {\r
-    if (ShellCommandLineGetCount(Package) < 4) {\r
+    StreamingUnicode = IsStdInDataAvailable ();\r
+    if ((!StreamingUnicode && (ShellCommandLineGetCount(Package) < 4)) ||\r
+        (ShellCommandLineGetCount(Package) < 3)) {\r
       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle, L"parse");  \r
       ShellStatus = SHELL_INVALID_PARAMETER;\r
-    } else if (ShellCommandLineGetCount(Package) > 4) {\r
+    } else if ((StreamingUnicode && (ShellCommandLineGetCount(Package) > 3)) ||\r
+                (ShellCommandLineGetCount(Package) > 4)) {\r
       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle, L"parse");  \r
       ShellStatus = SHELL_INVALID_PARAMETER;\r
     } else {\r
-      FileName      = ShellCommandLineGetRawValue(Package, 1);\r
-      TableName     = ShellCommandLineGetRawValue(Package, 2);\r
-      ColumnString  = ShellCommandLineGetRawValue(Package, 3);\r
-\r
+      if (StreamingUnicode) {\r
+        FileName         = L">i";\r
+        TableName        = ShellCommandLineGetRawValue(Package, 1);\r
+        ColumnString     = ShellCommandLineGetRawValue(Package, 2);\r
+      } else {\r
+        FileName         = ShellCommandLineGetRawValue(Package, 1);\r
+        TableName        = ShellCommandLineGetRawValue(Package, 2);\r
+        ColumnString     = ShellCommandLineGetRawValue(Package, 3);\r
+      }\r
       if (ShellCommandLineGetValue(Package, L"-i") == NULL) {\r
         TableNameInstance = (UINTN)-1;\r
       } else {\r
@@ -201,7 +395,7 @@ ShellCommandRunParse (
         ShellCommandInstance = ShellStrToUintn(ShellCommandLineGetValue(Package, L"-s"));\r
       }\r
 \r
-      ShellStatus = PerformParsing(FileName, TableName, ShellStrToUintn(ColumnString), TableNameInstance, ShellCommandInstance);\r
+      ShellStatus = PerformParsing(FileName, TableName, ShellStrToUintn(ColumnString), TableNameInstance, ShellCommandInstance, StreamingUnicode);\r
     }\r
   }\r
 \r