signals.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985
  1. /*++
  2. Copyright (c) 2013 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. signals.c
  5. Abstract:
  6. This module implements signal handling functionality for the shell.
  7. Author:
  8. Evan Green 14-Jun-2013
  9. Environment:
  10. Kernel
  11. --*/
  12. //
  13. // ------------------------------------------------------------------- Includes
  14. //
  15. #include "sh.h"
  16. #include "shparse.h"
  17. #include <assert.h>
  18. #include <errno.h>
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include "../swlib.h"
  22. //
  23. // ---------------------------------------------------------------- Definitions
  24. //
  25. //
  26. // ------------------------------------------------------ Data Type Definitions
  27. //
  28. typedef struct _SHELL_SIGNAL_STRING {
  29. PSTR Name;
  30. SHELL_SIGNAL Number;
  31. } SHELL_SIGNAL_STRING, *PSHELL_SIGNAL_STRING;
  32. //
  33. // ----------------------------------------------- Internal Function Prototypes
  34. //
  35. BOOL
  36. ShSetSignalAction (
  37. PSHELL Shell,
  38. SHELL_SIGNAL Signal,
  39. PSTR ActionString
  40. );
  41. SHELL_SIGNAL
  42. ShGetSignalFromArgument (
  43. PSTR Argument
  44. );
  45. SHELL_SIGNAL
  46. ShGetSignalNumberFromName (
  47. PSTR Name
  48. );
  49. PSTR
  50. ShGetSignalNameFromNumber (
  51. SHELL_SIGNAL Number
  52. );
  53. PSHELL_SIGNAL_ACTION
  54. ShGetSignalAction (
  55. PSHELL Shell,
  56. SHELL_SIGNAL SignalNumber
  57. );
  58. PSHELL_SIGNAL_ACTION
  59. ShCreateSignalAction (
  60. SHELL_SIGNAL SignalNumber,
  61. PSTR ActionString,
  62. UINTN ActionStringSize
  63. );
  64. VOID
  65. ShDestroySignalAction (
  66. PSHELL_SIGNAL_ACTION SignalAction
  67. );
  68. BOOL
  69. ShPrintTraps (
  70. PSHELL Shell
  71. );
  72. //
  73. // -------------------------------------------------------------------- Globals
  74. //
  75. //
  76. // Store an array of which signals are pending.
  77. //
  78. volatile int ShPendingSignals[ShellSignalCount];
  79. //
  80. // Store the count of signals, which is used for quick detection of whether or
  81. // not new signals have come in.
  82. //
  83. volatile int ShSignalCount;
  84. //
  85. // Define the translation between signal names and numbers.
  86. //
  87. SHELL_SIGNAL_STRING ShSignalNames[] = {
  88. {"EXIT", ShellSignalOnExit},
  89. {"HUP", ShellSignalHangup},
  90. {"INT", ShellSignalInterrupt},
  91. {"QUIT", ShellSignalQuit},
  92. {"ILL", ShellSignalIllegalInstruction},
  93. {"TRAP", ShellSignalTrap},
  94. {"ABRT", ShellSignalAbort},
  95. {"FPE", ShellSignalFloatingPointException},
  96. {"KILL", ShellSignalKill},
  97. {"BUS", ShellSignalBusError},
  98. {"SEGV", ShellSignalSegmentationFault},
  99. {"SYS", ShellSignalBadSystemCall},
  100. {"PIPE", ShellSignalPipe},
  101. {"ALRM", ShellSignalAlarm},
  102. {"TERM", ShellSignalTerminate},
  103. {"URG", ShellSignalUrgentData},
  104. {"STOP", ShellSignalStop},
  105. {"TSTP", ShellSignalTerminalStop},
  106. {"CONT", ShellSignalContinue},
  107. {"CHLD", ShellSignalChild},
  108. {"TTIN", ShellSignalTerminalInput},
  109. {"TTOU", ShellSignalTerminalOutput},
  110. {"XCPU", ShellSignalCpuTime},
  111. {"XFSZ", ShellSignalFileSize},
  112. {"VTALRM", ShellSignalVirtualTimeAlarm},
  113. {"PROF", ShellSignalProfiling},
  114. {"WINCH", ShellSignalWindowChange},
  115. {"USR1", ShellSignalUser1},
  116. {"USR2", ShellSignalUser2},
  117. {NULL, 0},
  118. };
  119. //
  120. // ------------------------------------------------------------------ Functions
  121. //
  122. void
  123. ShSignalHandler (
  124. int SignalNumber
  125. )
  126. /*++
  127. Routine Description:
  128. This routine is called when a signal comes in. It marks the signal as
  129. pending and makes an effort to get out as quickly as possible. The signal
  130. execution environment is fairly hostile, so there's not much that could be
  131. done anyway.
  132. Arguments:
  133. SignalNumber - Supplies the signal number of the signal that came in.
  134. Return Value:
  135. None.
  136. --*/
  137. {
  138. if (SignalNumber >= ShellSignalCount) {
  139. PRINT_ERROR("Unexpected signal %d came in.\n", SignalNumber);
  140. return;
  141. }
  142. //
  143. // Mark the specific signal as pending, and up the total number of signals
  144. // so the topmost shell knows to take a closer look.
  145. //
  146. ShPendingSignals[SignalNumber] = 1;
  147. ShSignalCount += 1;
  148. return;
  149. }
  150. VOID
  151. ShInitializeSignals (
  152. PSHELL Shell
  153. )
  154. /*++
  155. Routine Description:
  156. This routine initializes the shell signals.
  157. Arguments:
  158. Shell - Supplies a pointer to the shell.
  159. Return Value:
  160. None.
  161. --*/
  162. {
  163. if ((Shell->Options & SHELL_OPTION_INTERACTIVE) != 0) {
  164. ShSetSignalDisposition(ShellSignalInterrupt,
  165. ShellSignalDispositionTrap);
  166. ShSetSignalDisposition(ShellSignalQuit, ShellSignalDispositionTrap);
  167. } else {
  168. ShSetSignalDisposition(ShellSignalInterrupt,
  169. ShellSignalDispositionDefault);
  170. ShSetSignalDisposition(ShellSignalQuit, ShellSignalDispositionDefault);
  171. }
  172. return;
  173. }
  174. VOID
  175. ShCheckForSignals (
  176. PSHELL Shell
  177. )
  178. /*++
  179. Routine Description:
  180. This routine checks for any pending signals and runs their associated
  181. actions if they're set.
  182. Arguments:
  183. Shell - Supplies a pointer to the shell to run any pending signals on.
  184. Return Value:
  185. None.
  186. --*/
  187. {
  188. PSHELL_SIGNAL_ACTION Action;
  189. pid_t Child;
  190. PSTR EvalArguments[2];
  191. INT SavedReturnValue;
  192. INT Signal;
  193. //
  194. // If fork is supported, perform wait to clean up any asynchronous nodes.
  195. //
  196. if (SwForkSupported != FALSE) {
  197. while (TRUE) {
  198. Child = SwWaitPid(-1, 1, NULL);
  199. if (Child <= 0) {
  200. break;
  201. }
  202. }
  203. }
  204. if (ShSignalCount == Shell->LastSignalCount) {
  205. return;
  206. }
  207. Shell->LastSignalCount = ShSignalCount;
  208. for (Signal = 0; Signal < ShellSignalCount; Signal += 1) {
  209. if (ShPendingSignals[Signal] == 0) {
  210. continue;
  211. }
  212. ShPendingSignals[Signal] = 0;
  213. Action = ShGetSignalAction(Shell, Signal);
  214. if ((Action != NULL) && (Action->ActionSize > 1)) {
  215. SavedReturnValue = Shell->LastReturnValue;
  216. EvalArguments[0] = "eval";
  217. EvalArguments[1] = Action->Action;
  218. ShBuiltinEval(Shell, 2, EvalArguments);
  219. Shell->LastReturnValue = SavedReturnValue;
  220. }
  221. }
  222. return;
  223. }
  224. VOID
  225. ShRunAtExitSignal (
  226. PSHELL Shell
  227. )
  228. /*++
  229. Routine Description:
  230. This routine runs the "exit" trap handler on signal 0 if one was set.
  231. Arguments:
  232. Shell - Supplies a pointer to the shell to run any pending signals on.
  233. Return Value:
  234. None.
  235. --*/
  236. {
  237. if (Shell->SkipExitSignal != FALSE) {
  238. return;
  239. }
  240. if (ShGetSignalAction(Shell, ShellSignalOnExit) != NULL) {
  241. assert(Shell->Exited != FALSE);
  242. Shell->Exited = FALSE;
  243. //
  244. // Avoid calling the at exit signal again if the at exit signal calls
  245. // exit.
  246. //
  247. Shell->SkipExitSignal = TRUE;
  248. //
  249. // This is not a real signal so doing this won't race with incrementing
  250. // any actual signals. The total signal count might, but it's ok if
  251. // it only gets incremented by 1 instead of 2, the only real important
  252. // thing is that it's different from what's in the shell.
  253. //
  254. ShPendingSignals[ShellSignalOnExit] += 1;
  255. ShSignalCount += 1;
  256. ShCheckForSignals(Shell);
  257. Shell->Exited = TRUE;
  258. }
  259. return;
  260. }
  261. VOID
  262. ShSetAllSignalDispositions (
  263. PSHELL Shell
  264. )
  265. /*++
  266. Routine Description:
  267. This routine sets all the signal dispositions in accordance with the
  268. given shell. This is usually called when entering or exiting a subshell.
  269. Arguments:
  270. Shell - Supplies a pointer to the shell to operate in accordance with.
  271. Return Value:
  272. None.
  273. --*/
  274. {
  275. PSHELL_SIGNAL_ACTION Action;
  276. SHELL_SIGNAL Signal;
  277. for (Signal = 1; Signal < ShellSignalCount; Signal += 1) {
  278. Action = ShGetSignalAction(Shell, Signal);
  279. //
  280. // Trap the signal if one of the following is true:
  281. // 1) There's a requested action.
  282. // 2) It's an interactive shell and the signal is SIGINT or SIGQUIT.
  283. //
  284. if ((Action != NULL) ||
  285. (((Shell->Options & SHELL_OPTION_INTERACTIVE) != 0) &&
  286. ((Signal == ShellSignalInterrupt) ||
  287. (Signal == ShellSignalQuit)))) {
  288. ShSetSignalDisposition(Signal, ShellSignalDispositionTrap);
  289. } else {
  290. ShSetSignalDisposition(Signal, ShellSignalDispositionDefault);
  291. }
  292. }
  293. return;
  294. }
  295. VOID
  296. ShDestroySignalActionList (
  297. PLIST_ENTRY ActionList
  298. )
  299. /*++
  300. Routine Description:
  301. This routine destroys all the signal actions on the given signal action
  302. list.
  303. Arguments:
  304. ActionList - Supplies a pointer to the head of the action list.
  305. Return Value:
  306. None.
  307. --*/
  308. {
  309. PSHELL_SIGNAL_ACTION Action;
  310. while (LIST_EMPTY(ActionList) == FALSE) {
  311. Action = LIST_VALUE(ActionList->Next, SHELL_SIGNAL_ACTION, ListEntry);
  312. LIST_REMOVE(&(Action->ListEntry));
  313. ShDestroySignalAction(Action);
  314. }
  315. return;
  316. }
  317. INT
  318. ShBuiltinTrap (
  319. PSHELL Shell,
  320. INT ArgumentCount,
  321. PSTR *Arguments
  322. )
  323. /*++
  324. Routine Description:
  325. This routine implements the trap command, which handles signal catching
  326. within the shell.
  327. Arguments:
  328. Shell - Supplies a pointer to the shell.
  329. ArgumentCount - Supplies the number of arguments on the command line.
  330. Arguments - Supplies the array of pointers to strings representing each
  331. argument.
  332. Return Value:
  333. 0 on success.
  334. 1 on failure.
  335. --*/
  336. {
  337. PSHELL_SIGNAL_ACTION Action;
  338. ULONG ArgumentIndex;
  339. BOOL Result;
  340. SHELL_SIGNAL Signal;
  341. ULONG StartIndex;
  342. StartIndex = 1;
  343. //
  344. // A -- at the beginning is basically ignored as an argument.
  345. //
  346. if ((ArgumentCount > 1) && (strcmp(Arguments[1], "--") == 0)) {
  347. StartIndex = 2;
  348. }
  349. if (ArgumentCount <= StartIndex) {
  350. Result = ShPrintTraps(Shell);
  351. if (Result == FALSE) {
  352. return 1;
  353. }
  354. return 0;
  355. }
  356. //
  357. // If there's only one argument, then delete the action for the given
  358. // signal.
  359. //
  360. if (ArgumentCount == StartIndex + 1) {
  361. Signal = ShGetSignalFromArgument(Arguments[StartIndex]);
  362. if (Signal == ShellSignalInvalid) {
  363. PRINT_ERROR("trap: %s: bad trap\n", Arguments[StartIndex]);
  364. return 1;
  365. }
  366. Action = ShGetSignalAction(Shell, Signal);
  367. if (Action != NULL) {
  368. LIST_REMOVE(&(Action->ListEntry));
  369. ShDestroySignalAction(Action);
  370. }
  371. return 0;
  372. }
  373. //
  374. // Loop through all the signal numbers.
  375. //
  376. for (ArgumentIndex = StartIndex + 1;
  377. ArgumentIndex < ArgumentCount;
  378. ArgumentIndex += 1) {
  379. Signal = ShGetSignalFromArgument(Arguments[ArgumentIndex]);
  380. if (Signal == ShellSignalInvalid) {
  381. PRINT_ERROR("trap: %s: bad trap\n", Arguments[ArgumentIndex]);
  382. return 1;
  383. }
  384. Result = ShSetSignalAction(Shell, Signal, Arguments[StartIndex]);
  385. if (Result == FALSE) {
  386. return 1;
  387. }
  388. }
  389. return 0;
  390. }
  391. //
  392. // --------------------------------------------------------- Internal Functions
  393. //
  394. BOOL
  395. ShSetSignalAction (
  396. PSHELL Shell,
  397. SHELL_SIGNAL Signal,
  398. PSTR ActionString
  399. )
  400. /*++
  401. Routine Description:
  402. This routine sets the signal action for the given signal.
  403. Arguments:
  404. Shell - Supplies a pointer to the shell where the action will be set.
  405. Signal - Supplies the signal number.
  406. ActionString - Supplies the action to perform. If this is "-" the signal
  407. will be ignored. Otherwise the action word will be "eval"ed when the
  408. signal occurs.
  409. Return Value:
  410. TRUE on success.
  411. FALSE on failure.
  412. --*/
  413. {
  414. PSHELL_SIGNAL_ACTION Action;
  415. UINTN ActionStringSize;
  416. BOOL Result;
  417. assert(Signal < ShellSignalCount);
  418. Action = ShGetSignalAction(Shell, Signal);
  419. //
  420. // If the action is "-", delete any existing action and reset the signal
  421. // to its default action.
  422. //
  423. if (strcmp(ActionString, "-") == 0) {
  424. if (Action != NULL) {
  425. LIST_REMOVE(&(Action->ListEntry));
  426. ShDestroySignalAction(Action);
  427. }
  428. //
  429. // Continue to trap SIGINT and SIGQUIT on interactive shells.
  430. //
  431. if (((Shell->Options & SHELL_OPTION_INTERACTIVE) != 0) &&
  432. ((Signal == ShellSignalInterrupt) || (Signal == ShellSignalTrap))) {
  433. Result = ShSetSignalDisposition(Signal,
  434. ShellSignalDispositionTrap);
  435. } else {
  436. Result = ShSetSignalDisposition(Signal,
  437. ShellSignalDispositionDefault);
  438. }
  439. if (Result == FALSE) {
  440. return FALSE;
  441. }
  442. //
  443. // Set the signal to the given action word.
  444. //
  445. } else {
  446. ActionStringSize = strlen(ActionString) + 1;
  447. if (Action != NULL) {
  448. if (Action->Action != NULL) {
  449. free(Action->Action);
  450. }
  451. Action->Action = SwStringDuplicate(ActionString, ActionStringSize);
  452. if (Action->Action == NULL) {
  453. LIST_REMOVE(&(Action->ListEntry));
  454. ShDestroySignalAction(Action);
  455. return FALSE;
  456. }
  457. Action->ActionSize = ActionStringSize;
  458. } else {
  459. Action = ShCreateSignalAction(Signal,
  460. ActionString,
  461. ActionStringSize);
  462. if (Action == NULL) {
  463. return FALSE;
  464. }
  465. INSERT_BEFORE(&(Action->ListEntry), &(Shell->SignalActionList));
  466. }
  467. if (Signal != ShellSignalOnExit) {
  468. Result = ShSetSignalDisposition(Signal, ShellSignalDispositionTrap);
  469. if (Result == FALSE) {
  470. return FALSE;
  471. }
  472. }
  473. }
  474. return TRUE;
  475. }
  476. SHELL_SIGNAL
  477. ShGetSignalFromArgument (
  478. PSTR Argument
  479. )
  480. /*++
  481. Routine Description:
  482. This routine returns the signal number for the given signal name.
  483. Arguments:
  484. Argument - Supplies the name of the signal.
  485. Return Value:
  486. Returns the signal number on success.
  487. ShellSignalInvalid if the name did not match any signals.
  488. --*/
  489. {
  490. PSTR AfterScan;
  491. SHELL_SIGNAL Signal;
  492. Signal = ShGetSignalNumberFromName(Argument);
  493. if (Signal != ShellSignalInvalid) {
  494. return Signal;
  495. }
  496. Signal = strtoul(Argument, &AfterScan, 10);
  497. if (AfterScan == Argument) {
  498. return ShellSignalInvalid;
  499. }
  500. if (ShGetSignalNameFromNumber(Signal) == NULL) {
  501. return ShellSignalInvalid;
  502. }
  503. return Signal;
  504. }
  505. SHELL_SIGNAL
  506. ShGetSignalNumberFromName (
  507. PSTR Name
  508. )
  509. /*++
  510. Routine Description:
  511. This routine returns the signal number for the given signal name.
  512. Arguments:
  513. Name - Supplies the name of the signal.
  514. Return Value:
  515. Returns the signal number on success.
  516. ShellSignalInvalid if the name did not match any signals.
  517. --*/
  518. {
  519. ULONG Index;
  520. Index = 0;
  521. while (ShSignalNames[Index].Name != NULL) {
  522. if (strcasecmp(Name, ShSignalNames[Index].Name) == 0) {
  523. return ShSignalNames[Index].Number;
  524. }
  525. Index += 1;
  526. }
  527. return ShellSignalInvalid;
  528. }
  529. PSTR
  530. ShGetSignalNameFromNumber (
  531. SHELL_SIGNAL Number
  532. )
  533. /*++
  534. Routine Description:
  535. This routine returns the signal name for the given signal number.
  536. Arguments:
  537. Number - Supplies the signal number.
  538. Return Value:
  539. Returns the name string on success. The caller does not own this memory,
  540. and should not modify or free it.
  541. NULL if the given number is not valid.
  542. --*/
  543. {
  544. ULONG Index;
  545. Index = 0;
  546. while (ShSignalNames[Index].Name != NULL) {
  547. if (ShSignalNames[Index].Number == Number) {
  548. return ShSignalNames[Index].Name;
  549. }
  550. Index += 1;
  551. }
  552. return NULL;
  553. }
  554. PSHELL_SIGNAL_ACTION
  555. ShGetSignalAction (
  556. PSHELL Shell,
  557. SHELL_SIGNAL SignalNumber
  558. )
  559. /*++
  560. Routine Description:
  561. This routine attempts to return the signal action structure associated
  562. with the given signal number.
  563. Arguments:
  564. Shell - Supplies a pointer to the shell whose actions should be searched.
  565. SignalNumber - Supplies the signal number.
  566. Return Value:
  567. Returns a pointer to the signal action structure on success.
  568. NULL if the signal has no action.
  569. --*/
  570. {
  571. PSHELL_SIGNAL_ACTION Action;
  572. PLIST_ENTRY CurrentEntry;
  573. CurrentEntry = Shell->SignalActionList.Next;
  574. while (CurrentEntry != &(Shell->SignalActionList)) {
  575. Action = LIST_VALUE(CurrentEntry, SHELL_SIGNAL_ACTION, ListEntry);
  576. CurrentEntry = CurrentEntry->Next;
  577. if (Action->SignalNumber == SignalNumber) {
  578. return Action;
  579. }
  580. }
  581. return NULL;
  582. }
  583. PSHELL_SIGNAL_ACTION
  584. ShCreateSignalAction (
  585. SHELL_SIGNAL SignalNumber,
  586. PSTR ActionString,
  587. UINTN ActionStringSize
  588. )
  589. /*++
  590. Routine Description:
  591. This routine creates a shell action structure.
  592. Arguments:
  593. SignalNumber - Supplies the signal number this action is associated with.
  594. ActionString - Supplies a pointer to the action string to eval when the
  595. signal occurs. A copy of this string will be made.
  596. ActionStringSize - Supplies the size of the action string in bytes including
  597. the null terminator.
  598. Return Value:
  599. Returns a pointer to the shiny new action structure on success.
  600. NULL on failure.
  601. --*/
  602. {
  603. PSHELL_SIGNAL_ACTION Action;
  604. BOOL Result;
  605. Result = FALSE;
  606. Action = malloc(sizeof(SHELL_SIGNAL_ACTION));
  607. if (Action == NULL) {
  608. goto CreateSignalActionEnd;
  609. }
  610. memset(Action, 0, sizeof(SHELL_SIGNAL_ACTION));
  611. Action->SignalNumber = SignalNumber;
  612. Action->Action = SwStringDuplicate(ActionString, ActionStringSize);
  613. if (Action->Action == NULL) {
  614. goto CreateSignalActionEnd;
  615. }
  616. Action->ActionSize = ActionStringSize;
  617. Result = TRUE;
  618. CreateSignalActionEnd:
  619. if (Result == FALSE) {
  620. if (Action != NULL) {
  621. if (Action->Action != NULL) {
  622. free(Action->Action);
  623. }
  624. free(Action);
  625. Action = NULL;
  626. }
  627. }
  628. return Action;
  629. }
  630. VOID
  631. ShDestroySignalAction (
  632. PSHELL_SIGNAL_ACTION SignalAction
  633. )
  634. /*++
  635. Routine Description:
  636. This routine destroys a shell signal action structure. It assumes it has
  637. already been removed from its list.
  638. Arguments:
  639. SignalAction - Supplies a pointer to the action to destroy.
  640. Return Value:
  641. None.
  642. --*/
  643. {
  644. if (SignalAction->Action != NULL) {
  645. free(SignalAction->Action);
  646. }
  647. free(SignalAction);
  648. }
  649. BOOL
  650. ShPrintTraps (
  651. PSHELL Shell
  652. )
  653. /*++
  654. Routine Description:
  655. This routine prints all the shell traps.
  656. Arguments:
  657. Shell - Supplies a pointer to the shell.
  658. Return Value:
  659. TRUE on success.
  660. FALSE on failure.
  661. --*/
  662. {
  663. PSHELL_SIGNAL_ACTION Action;
  664. PLIST_ENTRY CurrentEntry;
  665. PSTR QuotedString;
  666. UINTN QuotedStringSize;
  667. BOOL Result;
  668. PSTR SignalName;
  669. CurrentEntry = Shell->SignalActionList.Next;
  670. while (CurrentEntry != &(Shell->SignalActionList)) {
  671. Action = LIST_VALUE(CurrentEntry, SHELL_SIGNAL_ACTION, ListEntry);
  672. CurrentEntry = CurrentEntry->Next;
  673. Result = ShStringFormatForReentry(Action->Action,
  674. Action->ActionSize,
  675. &QuotedString,
  676. &QuotedStringSize);
  677. if (Result == FALSE) {
  678. return FALSE;
  679. }
  680. SignalName = ShGetSignalNameFromNumber(Action->SignalNumber);
  681. assert(SignalName != NULL);
  682. printf("trap -- %s %s\n", QuotedString, SignalName);
  683. free(QuotedString);
  684. }
  685. return TRUE;
  686. }