Minor fixes to comments.
[AROS.git] / rom / exec / useralert.c
blob2d0200dbbc8ec322b6f7cf8a7aa7deaa9593acc0
1 #include <aros/debug.h>
2 #include <exec/alerts.h>
3 #include <exec/rawfmt.h>
4 #include <intuition/intuition.h>
5 #include <proto/exec.h>
6 #include <proto/intuition.h>
7 #include <proto/kernel.h>
9 #include "etask.h"
10 #include "exec_intern.h"
11 #include "exec_util.h"
13 static LONG SafeEasyRequest(struct EasyStruct *es, BOOL full, struct IntuitionBase *IntuitionBase)
15 LONG result;
16 APTR req = BuildEasyRequestArgs(NULL, es, 0, NULL);
18 if (!req)
20 /* Return -1 if requester creation failed. This makes us to fallback to safe-mode alert. */
21 return -1;
26 result = SysReqHandler(req, NULL, TRUE);
28 if (full)
30 switch (result)
32 case 1:
33 NewRawDoFmt("*** Logged alert:\n%s\n", RAWFMTFUNC_SERIAL, NULL, es->es_TextFormat);
34 result = -2;
35 break;
39 while (result == -2);
41 FreeSysRequest(req);
42 return result;
45 static const char startstring[] = "Program failed\n";
46 static const char endstring[] = "\nWait for disk activity to finish.";
47 static const char deadend_buttons[] = "More...|Suspend|Reboot|Power off";
48 static const char recoverable_buttons[] = "More...|Continue";
49 static const char full_deadend_buttons[] = "Log|Suspend|Reboot|Power off";
50 static const char full_recoverable_buttons[] = "Log|Continue";
52 static LONG AskSuspend(struct Task *task, ULONG alertNum, struct ExecBase *SysBase)
54 LONG choice = -1;
55 struct IntuitionBase *IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 36);
57 if (IntuitionBase)
59 char *buffer = AllocMem(ALERT_BUFFER_SIZE, MEMF_ANY);
61 if (buffer)
63 struct IntETask *iet = GetIntETask(task);
64 char *buf, *end;
65 struct EasyStruct es = {
66 sizeof (struct EasyStruct),
68 NULL,
69 buffer,
70 NULL,
73 buf = Alert_AddString(buffer, startstring);
74 buf = FormatAlert(buf, alertNum, task, iet ? iet->iet_AlertLocation : NULL, iet ? iet->iet_AlertType : AT_NONE, SysBase);
75 end = buf;
76 buf = Alert_AddString(buf, endstring);
77 *buf = 0;
79 es.es_Title = Alert_GetTitle(alertNum);
81 /* Determine set of buttons */
82 es.es_GadgetFormat = (alertNum & AT_DeadEnd) ? deadend_buttons : recoverable_buttons;
84 D(bug("[UserAlert] Body text:\n%s\n", buffer));
85 choice = SafeEasyRequest(&es, FALSE, IntuitionBase);
87 if (choice == 1)
89 /* 'More' has been pressed. Append full alert data */
90 FormatAlertExtra(end, iet->iet_AlertStack, iet ? iet->iet_AlertType : AT_NONE, iet ? &iet->iet_AlertData : NULL, SysBase);
92 /* Re-post the alert, without 'More...' this time */
93 es.es_GadgetFormat = (alertNum & AT_DeadEnd) ? full_deadend_buttons : full_recoverable_buttons;
95 choice = SafeEasyRequest(&es, TRUE, IntuitionBase);
98 FreeMem(buffer, ALERT_BUFFER_SIZE);
101 CloseLibrary(&IntuitionBase->LibNode);
103 return choice;
107 * This function posts alerts in user-mode via Intuition requester.
108 * Returns initial alert code if something fails and 0 if it was a recoverable
109 * alert and everything went ok.
110 * Note that in case of some crashes (e.g. corrupt memory list) this function
111 * may crash itself, and this has to be handled on a lower level. This is
112 * why we do this trick with iet_AlertCode
114 ULONG Exec_UserAlert(ULONG alertNum, struct ExecBase *SysBase)
116 struct Task *task = SysBase->ThisTask;
117 struct IntETask *iet;
118 LONG res;
120 /* Protect ourselves agains really hard crashes where SysBase->ThisTask is NULL.
121 Obviously we won't go far away in such a case */
122 if (!task)
123 return alertNum;
125 /* Get internal task structure */
126 if ((iet = GetIntETask(task))) {
128 * If we already have alert number for this task, we are in double-crash during displaying
129 * intuition requester. Well, take the initial alert code (because it's more helpful to the programmer)
130 * and proceed with arch-specific Alert().
131 * Since this is a double-crash, we may append AT_DeadEnd flag if our situation has become unrecoverable.
133 D(bug("[UserAlert] Task alert state: 0x%02X\n", iet->iet_AlertFlags));
134 if (iet->iet_AlertFlags & AF_Alert)
137 * Some more logic here. Nested AN_SysScrnType should not make original alert deadend.
138 * It just means we were unable to display it using Intuition requested because there
139 * are no display drivers at all.
141 if (alertNum == AN_SysScrnType)
142 return iet->iet_AlertCode;
143 else
144 return iet->iet_AlertCode | (alertNum & AT_DeadEnd);
148 * Otherwise we can try to put up Intuition requester first. Store alert code in order in ETask
149 * in order to indicate crash condition
151 iet->iet_AlertFlags |= AF_Alert;
152 iet->iet_AlertCode = alertNum;
156 * AN_SysScrnType is somewhat special. We remember it in the ETask (just in case),
157 * but propagate it to supervisor mode immediately. We do it because this error
158 * means we don't have any display modes, so we won't be able to bring up the requester.
160 if (alertNum == AN_SysScrnType)
161 return alertNum;
163 /* Issue a requester */
164 res = AskSuspend(task, alertNum, SysBase);
165 D(bug("[UserAlert] Requester result: %d\n", res));
167 /* If AskSuspend() failed, fail back to safe-mode alert */
168 if (res == -1)
169 return alertNum;
171 /* Halt if we need to */
172 if (alertNum & AT_DeadEnd)
174 switch (res)
176 case 0:
177 ShutdownA(SD_ACTION_POWEROFF);
178 break;
180 case 3:
181 ColdReboot();
182 /* In case if ColdReboot() doesn't work */
183 ShutdownA(SD_ACTION_COLDREBOOT);
184 break;
187 /* Well, stop if the user wants so (or if the reboot didn't work at all) */
188 Wait(0);
190 return 0;