]> git.proxmox.com Git - mirror_edk2.git/blob - ShellPkg/Library/UefiShellLevel3CommandsLib/Help.c
ShellPkg: Remove memory leak when printing help and there are dynamic commands installed
[mirror_edk2.git] / ShellPkg / Library / UefiShellLevel3CommandsLib / Help.c
1 /** @file
2 Main file for Help shell level 3 function.
3
4 Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved. <BR>
5 Copyright (c) 2014, ARM Limited. All rights reserved. <BR>
6 (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
7
8 This program and the accompanying materials
9 are licensed and made available under the terms and conditions of the BSD License
10 which accompanies this distribution. The full text of the license may be found at
11 http://opensource.org/licenses/bsd-license.php
12
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15
16 **/
17
18 #include "UefiShellLevel3CommandsLib.h"
19
20 #include <Library/ShellLib.h>
21 #include <Library/HandleParsingLib.h>
22
23 #include <Protocol/EfiShellDynamicCommand.h>
24
25 /**
26 Attempt to print help from a dynamically added command.
27
28 @param[in] CommandToGetHelpOn The unicode name of the command that help is
29 requested on.
30 @param[in] SectionToGetHelpOn Pointer to the section specifier(s).
31 @param[in] PrintCommandText Print the command followed by the help content
32 or just help.
33
34 @retval EFI_SUCCESS The help was displayed
35 @retval EFI_NOT_FOUND The command name could not be found
36 @retval EFI_DEVICE_ERROR The help data format was incorrect.
37 **/
38 EFI_STATUS
39 EFIAPI
40 PrintDynamicCommandHelp(
41 IN CHAR16 *CommandToGetHelpOn,
42 IN CHAR16 *SectionToGetHelpOn,
43 IN BOOLEAN PrintCommandText
44 )
45 {
46 EFI_STATUS Status;
47 BOOLEAN Found;
48 EFI_HANDLE *CommandHandleList;
49 EFI_HANDLE *NextCommand;
50 EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *DynamicCommand;
51
52 Status = EFI_NOT_FOUND;
53 Found = FALSE;
54 CommandHandleList = NULL;
55
56 CommandHandleList = GetHandleListByProtocol(&gEfiShellDynamicCommandProtocolGuid);
57
58 if (CommandHandleList == NULL) {
59 //
60 // not found or out of resources
61 //
62 return Status;
63 }
64
65 for (NextCommand = CommandHandleList; *NextCommand != NULL; NextCommand++) {
66 Status = gBS->HandleProtocol(
67 *NextCommand,
68 &gEfiShellDynamicCommandProtocolGuid,
69 (VOID **)&DynamicCommand
70 );
71
72 if (EFI_ERROR(Status)) {
73 continue;
74 }
75
76 //
77 // Check execution break flag when printing multiple command help information.
78 //
79 if (ShellGetExecutionBreakFlag ()) {
80 break;
81 }
82
83 if ((gUnicodeCollation->MetaiMatch (gUnicodeCollation, (CHAR16 *)DynamicCommand->CommandName, CommandToGetHelpOn)) ||
84 (gEfiShellProtocol->GetAlias (CommandToGetHelpOn, NULL) != NULL && (gUnicodeCollation->MetaiMatch (gUnicodeCollation, (CHAR16 *)DynamicCommand->CommandName, (CHAR16*)(gEfiShellProtocol->GetAlias(CommandToGetHelpOn, NULL)))))) {
85 // Print as Shell Help if in ManPage format.
86 Status = ShellPrintHelp (DynamicCommand->CommandName, SectionToGetHelpOn,
87 PrintCommandText);
88 if (Status == EFI_DEVICE_ERROR) {
89 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_HELP_INV),
90 gShellLevel3HiiHandle, DynamicCommand->CommandName);
91 } else if (EFI_ERROR(Status)) {
92 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_HELP_NF),
93 gShellLevel3HiiHandle, DynamicCommand->CommandName);
94 } else {
95 Found = TRUE;
96 }
97 }
98 }
99
100 SHELL_FREE_NON_NULL(CommandHandleList);
101
102 return (Found ? EFI_SUCCESS : Status);
103
104 }
105
106 STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
107 {L"-usage", TypeFlag},
108 {L"-section", TypeMaxValue},
109 {L"-verbose", TypeFlag},
110 {L"-v", TypeFlag},
111 {NULL, TypeMax}
112 };
113
114 /**
115 Function for 'help' command.
116
117 @param[in] ImageHandle Handle to the Image (NULL if Internal).
118 @param[in] SystemTable Pointer to the System Table (NULL if Internal).
119 **/
120 SHELL_STATUS
121 EFIAPI
122 ShellCommandRunHelp (
123 IN EFI_HANDLE ImageHandle,
124 IN EFI_SYSTEM_TABLE *SystemTable
125 )
126 {
127 EFI_STATUS Status;
128 LIST_ENTRY *Package;
129 CHAR16 *ProblemParam;
130 SHELL_STATUS ShellStatus;
131 CONST COMMAND_LIST *CommandList;
132 CONST COMMAND_LIST *Node;
133 CHAR16 *CommandToGetHelpOn;
134 CHAR16 *SectionToGetHelpOn;
135 CHAR16 *HiiString;
136 BOOLEAN Found;
137 BOOLEAN PrintCommandText;
138
139 PrintCommandText = TRUE;
140 ProblemParam = NULL;
141 ShellStatus = SHELL_SUCCESS;
142 CommandToGetHelpOn = NULL;
143 SectionToGetHelpOn = NULL;
144 Found = FALSE;
145
146 //
147 // initialize the shell lib (we must be in non-auto-init...)
148 //
149 Status = ShellInitialize();
150 ASSERT_EFI_ERROR(Status);
151
152 Status = CommandInit();
153 ASSERT_EFI_ERROR(Status);
154
155 //
156 // parse the command line
157 //
158 Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
159 if (EFI_ERROR(Status)) {
160 if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
161 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel3HiiHandle, L"help", ProblemParam);
162 FreePool(ProblemParam);
163 ShellStatus = SHELL_INVALID_PARAMETER;
164 } else {
165 ASSERT(FALSE);
166 }
167 } else {
168 //
169 // Check for conflicting parameters.
170 //
171 if (ShellCommandLineGetFlag(Package, L"-usage")
172 &&ShellCommandLineGetFlag(Package, L"-section")
173 &&(ShellCommandLineGetFlag(Package, L"-verbose") || ShellCommandLineGetFlag(Package, L"-v"))
174 ){
175 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CON), gShellLevel3HiiHandle, L"help");
176 ShellStatus = SHELL_INVALID_PARAMETER;
177 } else if (ShellCommandLineGetRawValue(Package, 2) != NULL) {
178 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel3HiiHandle, L"help");
179 ShellStatus = SHELL_INVALID_PARAMETER;
180 } else {
181 //
182 // Get the command name we are getting help on
183 //
184 ASSERT(CommandToGetHelpOn == NULL);
185 StrnCatGrow(&CommandToGetHelpOn, NULL, ShellCommandLineGetRawValue(Package, 1), 0);
186 if (CommandToGetHelpOn == NULL && ShellCommandLineGetFlag(Package, L"-?")) {
187 //
188 // If we dont have a command and we got a simple -?
189 // we are looking for help on help command.
190 //
191 StrnCatGrow(&CommandToGetHelpOn, NULL, L"help", 0);
192 }
193
194 if (CommandToGetHelpOn == NULL) {
195 StrnCatGrow(&CommandToGetHelpOn, NULL, L"*", 0);
196 ASSERT(SectionToGetHelpOn == NULL);
197 StrnCatGrow(&SectionToGetHelpOn, NULL, L"NAME", 0);
198 } else {
199 PrintCommandText = FALSE;
200 ASSERT(SectionToGetHelpOn == NULL);
201 //
202 // Get the section name for the given command name
203 //
204 if (ShellCommandLineGetFlag(Package, L"-section")) {
205 StrnCatGrow(&SectionToGetHelpOn, NULL, ShellCommandLineGetValue(Package, L"-section"), 0);
206 } else if (ShellCommandLineGetFlag(Package, L"-usage")) {
207 StrnCatGrow(&SectionToGetHelpOn, NULL, L"NAME,SYNOPSIS", 0);
208 } else if (ShellCommandLineGetFlag(Package, L"-verbose") || ShellCommandLineGetFlag(Package, L"-v")) {
209 } else {
210 //
211 // The output of help <command> will display NAME, SYNOPSIS, OPTIONS, DESCRIPTION, and EXAMPLES sections.
212 //
213 StrnCatGrow (&SectionToGetHelpOn, NULL, L"NAME,SYNOPSIS,OPTIONS,DESCRIPTION,EXAMPLES", 0);
214 }
215 }
216
217 if (gUnicodeCollation->StriColl(gUnicodeCollation, CommandToGetHelpOn, L"special") == 0) {
218 //
219 // we need info on the special characters
220 //
221 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HELP_SC_HEADER), gShellLevel3HiiHandle);
222 HiiString = HiiGetString(gShellLevel3HiiHandle, STRING_TOKEN(STR_HELP_SC_DATA), NULL);
223 ShellPrintEx(-1, -1, L"%s", HiiString);
224 FreePool(HiiString);
225 Found = TRUE;
226 } else {
227 CommandList = ShellCommandGetCommandList(TRUE);
228 ASSERT(CommandList != NULL);
229 for ( Node = (COMMAND_LIST*)GetFirstNode(&CommandList->Link)
230 ; CommandList != NULL && !IsListEmpty(&CommandList->Link) && !IsNull(&CommandList->Link, &Node->Link)
231 ; Node = (COMMAND_LIST*)GetNextNode(&CommandList->Link, &Node->Link)
232 ){
233 //
234 // Checking execution break flag when print multiple command help information.
235 //
236 if (ShellGetExecutionBreakFlag ()) {
237 break;
238 }
239 if ((gUnicodeCollation->MetaiMatch(gUnicodeCollation, Node->CommandString, CommandToGetHelpOn)) ||
240 (gEfiShellProtocol->GetAlias(CommandToGetHelpOn, NULL) != NULL && (gUnicodeCollation->MetaiMatch(gUnicodeCollation, Node->CommandString, (CHAR16*)(gEfiShellProtocol->GetAlias(CommandToGetHelpOn, NULL)))))) {
241 //
242 // We have a command to look for help on.
243 //
244 Status = ShellPrintHelp(Node->CommandString, SectionToGetHelpOn, PrintCommandText);
245 if (Status == EFI_DEVICE_ERROR) {
246 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HELP_INV), gShellLevel3HiiHandle, Node->CommandString);
247 } else if (EFI_ERROR(Status)) {
248 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HELP_NF), gShellLevel3HiiHandle, Node->CommandString);
249 } else {
250 Found = TRUE;
251 }
252 }
253 }
254
255 //
256 // now try to match against the dynamic command list and print help
257 //
258 Status = PrintDynamicCommandHelp (CommandToGetHelpOn, SectionToGetHelpOn,
259 PrintCommandText);
260 if (!EFI_ERROR(Status)) {
261 Found = TRUE;
262 }
263
264 //
265 // Search the .man file for Shell applications (Shell external commands).
266 //
267 if (!Found) {
268 Status = ShellPrintHelp(CommandToGetHelpOn, SectionToGetHelpOn, FALSE);
269 if (Status == EFI_DEVICE_ERROR) {
270 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HELP_INV), gShellLevel3HiiHandle, CommandToGetHelpOn);
271 } else if (EFI_ERROR(Status)) {
272 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HELP_NF), gShellLevel3HiiHandle, CommandToGetHelpOn);
273 } else {
274 Found = TRUE;
275 }
276 }
277 }
278
279 if (!Found) {
280 ShellStatus = SHELL_NOT_FOUND;
281 }
282
283 //
284 // free the command line package
285 //
286 ShellCommandLineFreeVarList (Package);
287 }
288 }
289
290 if (CommandToGetHelpOn != NULL && StrCmp(CommandToGetHelpOn, L"*") == 0){
291 //
292 // If '*' then the command entered was 'Help' without qualifiers, This footer
293 // provides additional info on help switches
294 //
295 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HELP_FOOTER), gShellLevel3HiiHandle);
296 }
297 if (CommandToGetHelpOn != NULL) {
298 FreePool(CommandToGetHelpOn);
299 }
300 if (SectionToGetHelpOn != NULL) {
301 FreePool(SectionToGetHelpOn);
302 }
303
304 return (ShellStatus);
305 }