]> git.proxmox.com Git - mirror_edk2.git/blame - StdLib/LibC/StdLib/Environs.c
Changes so that Argv points to narrow-character versions of the command-line arguments.
[mirror_edk2.git] / StdLib / LibC / StdLib / Environs.c
CommitLineData
2aa62f2b 1/** @file\r
2 Implementation of the <stdlib.h> functions responsible for communication with\r
3 the environment:\r
4 - abort(void)\r
5 - atexit(void(*handler)(void))\r
6 - exit(int status)\r
7 - _Exit(int status)\r
8\r
53e1e5c6 9 Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>\r
2aa62f2b 10 This program and the accompanying materials are licensed and made available under\r
11 the terms and conditions of the BSD License that accompanies this distribution.\r
12 The full text of the license may be found at\r
53e1e5c6 13 http://opensource.org/licenses/bsd-license.\r
2aa62f2b 14\r
15 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
16 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
17\r
18**/\r
19#include <Uefi.h>\r
20#include <Library/UefiBootServicesTableLib.h>\r
21#include <Library/BaseLib.h>\r
22#include <Library/MemoryAllocationLib.h>\r
23#include <Library/ShellLib.h>\r
24\r
25#include <LibConfig.h>\r
26\r
27#include <errno.h>\r
28#include <signal.h>\r
29#include <stdlib.h>\r
30#include <MainData.h>\r
31\r
32/* ################# Public Functions ################################### */\r
33\r
34/** The abort function causes abnormal program termination to occur, unless\r
35 the signal SIGABRT is being caught and the signal handler does not return.\r
36\r
37 Open streams with unwritten buffered data are not flushed, open\r
38 streams are not closed, and temporary files are not removed by abort.\r
39\r
40**/\r
41void\r
42abort(void)\r
43{\r
44 if (!gMD->aborting) {\r
45 gMD->aborting = TRUE;\r
46\r
47 if (gMD->cleanup != NULL) {\r
48 gMD->cleanup();\r
49 }\r
50 }\r
51 raise(SIGABRT);\r
52 _Exit(EXIT_FAILURE); // In case raise returns.\r
53}\r
54\r
55/** The atexit function registers the function pointed to by func, to be\r
56 called without arguments at normal program termination.\r
57\r
58 The implementation shall support the registration of\r
59 at least 32 functions.\r
60\r
61 @return The atexit function returns zero if the registration succeeds,\r
62 nonzero if it fails.\r
63**/\r
64int\r
65atexit(void (*handler)(void))\r
66{\r
67 int retval = 1;\r
68\r
69 if((handler != NULL) && (gMD->num_atexit < ATEXIT_MAX)) {\r
70 gMD->atexit_handler[gMD->num_atexit++] = handler;\r
71 retval = 0;\r
72 }\r
73 return retval;\r
74}\r
75\r
76/** The exit function causes normal program termination to occur. If more than\r
77 one call to the exit function is executed by a program,\r
78 the behavior is undefined.\r
79\r
80 First, all functions registered by the atexit function are called, in the\r
81 reverse order of their registration. If, during the call to any such function, a\r
82 call to the longjmp function is made that would terminate the call to the\r
83 registered function, the behavior is undefined.\r
84\r
85 Next, all open streams with unwritten buffered data are flushed, all open\r
86 streams are closed, and all files created by the tmpfile function\r
87 are removed.\r
88\r
89 The status returned to the host environment is determined in the same way\r
90 as for the _Exit function.\r
91**/\r
92void\r
93exit(int status)\r
94{\r
53e1e5c6 95 void (*CleanUp)(void); // Pointer to Cleanup Function\r
96 int i;\r
97\r
98 if(gMD != NULL) {\r
99 CleanUp = gMD->cleanup; // Preserve the pointer to the Cleanup Function\r
2aa62f2b 100\r
101 // Call all registered atexit functions in reverse order\r
53e1e5c6 102 i = gMD->num_atexit;\r
2aa62f2b 103 if( i > 0) {\r
104 do {\r
105 (gMD->atexit_handler[--i])();\r
106 } while( i > 0);\r
107 }\r
108\r
53e1e5c6 109 if (CleanUp != NULL) {\r
110 CleanUp();\r
111 }\r
2aa62f2b 112 }\r
113 _Exit(status);\r
114}\r
115\r
2aa62f2b 116/** The _Exit function causes normal program termination to occur and control\r
117 to be returned to the host environment.\r
118\r
119 No functions registered by the atexit function or signal handlers\r
120 registered by the signal function are called. Open streams with unwritten\r
121 buffered data are not flushed, open streams are not closed, and temporary\r
122 files are not removed by abort.\r
123\r
124 Finally, control is returned to the host environment. If the value of\r
125 status is zero, or EXIT_SUCCESS, status is returned unchanged. If the value\r
126 of status is EXIT_FAILURE, RETURN_ABORTED is returned.\r
127 Otherwise, status is returned unchanged.\r
128**/\r
129void\r
130_Exit(int status)\r
131{\r
132 RETURN_STATUS ExitVal = (RETURN_STATUS)status;\r
2aa62f2b 133\r
134 if( ExitVal == EXIT_FAILURE) {\r
135 ExitVal = RETURN_ABORTED;\r
136 }\r
137\r
53e1e5c6 138 if(gMD->FinalCleanup != NULL) {\r
139 gMD->FinalCleanup(); // gMD does not exist when this returns.\r
140 }\r
2aa62f2b 141\r
53e1e5c6 142 gBS->Exit(gImageHandle, ExitVal, 0, NULL); /* abort() */\r
2aa62f2b 143}\r
144\r
145/** If string is a null pointer, the system function determines whether the\r
146 host environment has a command processor. If string is not a null pointer,\r
147 the system function passes the string pointed to by string to that command\r
148 processor to be executed in a manner which the implementation shall\r
149 document; this might then cause the program calling system to behave in a\r
150 non-conforming manner or to terminate.\r
151\r
152 @retval EXIT_FAILURE EFIerrno will contain the EFI status code\r
153 indicating the cause of failure.\r
154\r
155 @retval EXIT_SUCCESS EFIerrno will contain the EFI status returned\r
156 by the executed command string.\r
157 @retval 0 If string is NULL, 0 means a command processor\r
158 is not available.\r
159 @retval 1 If string is NULL, 1 means a command processor\r
160 is available.\r
161**/\r
162int\r
163system(const char *string)\r
164{\r
165 EFI_STATUS CmdStat;\r
166 EFI_STATUS OpStat;\r
167 EFI_HANDLE MyHandle = gImageHandle;\r
168\r
169 if( string == NULL) {\r
170 return 1;\r
171 }\r
172 (void)AsciiStrToUnicodeStr( string, gMD->UString);\r
173 OpStat = ShellExecute( &MyHandle, gMD->UString, FALSE, NULL, &CmdStat);\r
174 if(OpStat == RETURN_SUCCESS) {\r
175 EFIerrno = CmdStat;\r
176 return EXIT_SUCCESS;\r
177 }\r
178 EFIerrno = OpStat;\r
179 return EXIT_FAILURE;\r
180}\r
181\r
182/** The getenv function searches an environment list, provided by the host\r
183 environment, for a string that matches the string pointed to by name. The\r
184 set of environment names and the method for altering the environment list\r
185 are determined by the underlying UEFI Shell implementation.\r
186\r
187 @return The getenv function returns a pointer to a string associated with\r
188 the matched list member. The string pointed to shall not be\r
189 modified by the program, but may be overwritten by a subsequent\r
190 call to the getenv function. If the specified name cannot be\r
191 found, a null pointer is returned.\r
192**/\r
193char *getenv(const char *name)\r
194{\r
195 const CHAR16 *EfiEnv;\r
196 char *retval = NULL;\r
197\r
198 (void)AsciiStrToUnicodeStr( name, gMD->UString);\r
199 EfiEnv = ShellGetEnvironmentVariable(gMD->UString);\r
200 if(EfiEnv != NULL) {\r
201 retval = UnicodeStrToAsciiStr( EfiEnv, gMD->ASgetenv);\r
202 }\r
203\r
204 return retval;\r
205}\r
53e1e5c6 206\r
207\r
208/**\r
209 Add or update a variable in the environment list\r
210\r
211 @param name Address of a zero terminated name string\r
212 @param value Address of a zero terminated value string\r
213 @param rewrite TRUE allows overwriting existing values\r
214\r
215 @retval Returns 0 upon success\r
216 @retval Returns -1 upon failure, sets errno with more information\r
217\r
218 Errors\r
219\r
220 EINVAL - name is NULL or points to a zero length string\r
221 EALREADY - name already set and rewrite set to FALSE\r
222 ENODEV - Unable to set non-volatile version of environment variable\r
223 ENOMEM - Unable to set volatile version of environment variable\r
224 ENOTSUP - Variable storage not supported\r
225\r
226**/\r
227int\r
228setenv (\r
229 register const char * name,\r
230 register const char * value,\r
231 int rewrite\r
232 )\r
233{\r
234 CONST CHAR16 * HostName;\r
235 int retval;\r
236 EFI_STATUS Status;\r
237 CHAR16 * UName;\r
238 CHAR16 * UValue;\r
239\r
240 //\r
241 // Assume failure\r
242 //\r
243 retval = -1;\r
244\r
245 //\r
246 // Validate the inputs\r
247 //\r
248 errno = EINVAL;\r
249 if (( NULL != name ) && ( 0 != *name )) {\r
250 //\r
251 // Get the storage locations for the unicode strings\r
252 //\r
253 UName = &gMD->UString[0];\r
254 UValue = &gMD->UString2[0];\r
255\r
256 //\r
257 // Convert the strings\r
258 //\r
259 AsciiStrToUnicodeStr ( name, UName );\r
260 AsciiStrToUnicodeStr ( value, UValue );\r
261\r
262 //\r
263 // Determine if the string is already present\r
264 //\r
265 errno = EALREADY;\r
266 HostName = ShellGetEnvironmentVariable ( UName );\r
267 if ( rewrite || ( NULL == HostName )) {\r
268 //\r
269 // Support systems that don't have non-volatile memory\r
270 //\r
271 errno = ENOMEM;\r
272 Status = ShellSetEnvironmentVariable ( UName, UValue, TRUE );\r
273 if ( EFI_ERROR ( Status )) {\r
274 if ( EFI_UNSUPPORTED == Status ) {\r
275 errno = ENOTSUP;\r
276 }\r
277 }\r
278 else {\r
279 //\r
280 // Permanently set the environment variable\r
281 //\r
282 errno = ENODEV;\r
283 Status = ShellSetEnvironmentVariable ( UName, UValue, FALSE );\r
284 if ( !EFI_ERROR ( Status )) {\r
285 //\r
286 // Success\r
287 //\r
288 errno = 0;\r
289 retval = 0;\r
290 }\r
291 }\r
292 }\r
293 }\r
294\r
295 //\r
296 // Return the operation status\r
297 //\r
298 return retval;\r
299}\r
300\r