BPicture: Fix archive constructor.
[haiku.git] / src / add-ons / kernel / debugger / run_on_exit / run_on_exit.cpp
blob1987fd03c8b80b47fa56c77f5c2de9a17106cc86
1 /*
2 * Copyright 2009, Michael Lotz, mmlr@mlotz.ch
3 * Distributed under the terms of the MIT License.
4 */
5 #include <debug.h>
6 #include <signal.h>
7 #include <string.h>
8 #include <image.h>
11 static sem_id sRequestSem = -1;
12 static char sCommandBuffer[1024];
13 static uint32 sCommandOffset = 0;
14 static uint32 sCommandCount = 0;
17 static int32
18 run_on_exit_loop(void *data)
20 while (true) {
21 if (acquire_sem(sRequestSem) != B_OK)
22 break;
24 char *pointer = sCommandBuffer;
25 while (sCommandCount > 0) {
26 uint8 argCount = (uint8)pointer[0];
27 pointer++;
29 const char *args[argCount];
30 for (uint8 i = 0; i < argCount; i++) {
31 args[i] = pointer;
32 uint32 length = strlen(pointer);
33 pointer += length + 1;
36 thread_id thread = load_image(argCount, args, NULL);
37 if (thread >= B_OK)
38 resume_thread(thread);
39 sCommandCount--;
42 sCommandOffset = 0;
45 return 0;
49 static int
50 add_run_on_exit_command(int argc, char **argv)
52 if (argc < 2 || strcmp(argv[1], "--help") == 0) {
53 print_debugger_command_usage(argv[0]);
54 return 0;
57 if (argc > 256) {
58 kprintf("too many arguments\n");
59 return 0;
62 size_t totalLength = 1;
63 for (int32 i = 1; i < argc; i++)
64 totalLength += strlen(argv[i]) + 1;
66 if (sCommandOffset + totalLength > sizeof(sCommandBuffer)) {
67 kprintf("no space left in command buffer\n");
68 return 0;
71 char *pointer = sCommandBuffer + sCommandOffset;
72 *pointer++ = (char)(argc - 1);
74 for (int32 i = 1; i < argc; i++) {
75 strcpy(pointer, argv[i]);
76 pointer += strlen(argv[i]) + 1;
79 sCommandOffset += totalLength;
80 sCommandCount++;
81 return 0;
85 static void
86 exit_debugger()
88 if (sCommandCount > 0)
89 release_sem_etc(sRequestSem, 1, B_DO_NOT_RESCHEDULE);
93 static status_t
94 std_ops(int32 op, ...)
96 if (op == B_MODULE_INIT) {
97 sRequestSem = create_sem(0, "run_on_exit_request");
98 if (sRequestSem < B_OK)
99 return sRequestSem;
101 thread_id thread = spawn_kernel_thread(&run_on_exit_loop,
102 "run_on_exit_loop", B_NORMAL_PRIORITY, NULL);
103 if (thread < B_OK)
104 return thread;
106 resume_thread(thread);
108 add_debugger_command_etc("on_exit", &add_run_on_exit_command,
109 "Adds a command to be run when leaving the kernel debugger",
110 "<command> [<arguments>]\n"
111 "Adds a command to be run when leaving the kernel debugger.\n", 0);
113 return B_OK;
114 } else if (op == B_MODULE_UNINIT) {
115 remove_debugger_command("on_exit", &add_run_on_exit_command);
116 // deleting the sem will also cause the thread to exit
117 delete_sem(sRequestSem);
118 sRequestSem = -1;
119 return B_OK;
122 return B_BAD_VALUE;
126 static struct debugger_module_info sModuleInfo = {
128 "debugger/run_on_exit/v1",
129 B_KEEP_LOADED,
130 &std_ops
133 NULL,
134 exit_debugger,
135 NULL,
136 NULL
139 module_info *modules[] = {
140 (module_info *)&sModuleInfo,
141 NULL