Detabbed
[AROS.git] / rom / dos / runhandler.c
blob9fc8184bb1679693b8e5073e61a772bd81f04526
1 /*
2 Copyright © 1995-2012, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Execute a loaded command synchronously
6 Lang: english
7 */
9 #include <aros/debug.h>
10 #include <exec/memory.h>
11 #include <dos/dosextens.h>
12 #include <dos/filehandler.h>
13 #include <proto/arossupport.h>
14 #include <proto/exec.h>
15 #include <proto/dos.h>
17 #include <string.h>
19 #include "dos_intern.h"
21 /* Under AOS, BCPL handlers expect to receive a pointer to their
22 * startup packet in D1.
24 * This wrapper is here to support that.
26 void BCPL_RunHandler(void);
28 struct MsgPort *RunHandler(struct DeviceNode *deviceNode, const char *path, struct DosLibrary *DOSBase)
30 D(struct FileSysStartupMsg *fssm = NULL;)
31 struct DosPacket *dp;
32 struct MsgPort *reply_port;
33 struct Process *process = NULL;
34 BSTR bpath;
35 ULONG len;
36 CONST_STRPTR handler;
37 APTR entry;
39 handler = AROS_BSTR_ADDR(deviceNode->dn_Handler);
41 /* No possible way to continue? */
42 if (deviceNode->dn_SegList == BNULL && handler == NULL)
43 return NULL;
45 if (deviceNode->dn_SegList == BNULL) {
46 struct Segment *seg = NULL;
48 /* Try to find in the Resident Segment list */
49 Forbid();
50 D(bug("[RunHandler] Looking for handler '%s' in resident list\n",
51 handler));
52 seg = FindSegment(handler, NULL, TRUE);
53 Permit();
55 deviceNode->dn_SegList = seg ? seg->seg_Seg : BNULL;
58 if (deviceNode->dn_SegList == BNULL) {
59 D(bug("[RunHandler] LoadSeg(\"%s\")\n", handler));
61 deviceNode->dn_SegList = LoadSeg(handler);
64 if (deviceNode->dn_SegList == BNULL) {
65 CONST_STRPTR cp = FilePart(handler);
67 if (cp != NULL) {
68 BPTR dir;
69 dir = Lock("L:", SHARED_LOCK);
70 if (dir != BNULL) {
71 BPTR olddir;
72 olddir = CurrentDir(dir);
73 D(bug("[RunHandler] LoadSeg(\"L:%s\")\n", cp));
74 deviceNode->dn_SegList = LoadSeg(cp);
75 CurrentDir(olddir);
80 if (deviceNode->dn_SegList == BNULL) {
81 D(bug("[RunHandler] name '%b' seglist=NULL?\n", deviceNode->dn_Name));
82 return NULL;
85 if (path)
87 bpath = CreateBSTR(path);
88 if (bpath == BNULL)
89 return NULL;
91 else
93 path = AROS_BSTR_ADDR(deviceNode->dn_Name);
94 len = AROS_BSTR_strlen(deviceNode->dn_Name);
95 bpath = MKBADDR(AllocVec(AROS_BSTR_MEMSIZE4LEN(len + 1), MEMF_PUBLIC));
96 if (bpath == BNULL)
97 return NULL;
99 CopyMem(path, AROS_BSTR_ADDR(bpath), len);
100 AROS_BSTR_ADDR(bpath)[len++] = ':';
101 AROS_BSTR_setstrlen(bpath, len);
104 D(bug("[RunHandler] in open by Task '%s'\n", FindTask(NULL)->tc_Node.ln_Name));
106 D(if ((IPTR)deviceNode->dn_Startup >= 64)) /* really an FSSM? */
107 D(fssm = (struct FileSysStartupMsg *)BADDR(deviceNode->dn_Startup);)
109 D(bug("[RunHandler] devicenode=%08lx path='%b' devicename '%b' unit %d dosname '%b' handler=%x seg=%08lx startup=%08lx\n",
110 deviceNode,
111 bpath,
112 fssm ? fssm->fssm_Device : BNULL,
113 fssm ? fssm->fssm_Unit : 0,
114 deviceNode->dn_Name,
115 deviceNode->dn_Handler,
116 deviceNode->dn_SegList,
117 deviceNode->dn_Startup));
119 D(bug("RunHandler: %b has GlobalVec = %d\n", deviceNode->dn_Name, (SIPTR)deviceNode->dn_GlobalVec));
121 #ifdef __mc68000
122 /* BCPL file-handler support */
123 if (deviceNode->dn_GlobalVec != (BPTR)-1 && deviceNode->dn_GlobalVec != (BPTR)-2)
124 entry = BCPL_RunHandler;
125 else
126 #endif
127 entry = BADDR(deviceNode->dn_SegList)+sizeof(IPTR);
129 D(bug("[RunHandler] stacksize %d priority %d\n",
130 deviceNode->dn_StackSize,
131 deviceNode->dn_Priority));
133 /* start it up */
134 process = CreateNewProcTags(
135 NP_Entry, (IPTR)entry,
136 NP_Seglist, (IPTR)deviceNode->dn_SegList,
137 NP_FreeSeglist, (IPTR)FALSE,
138 NP_Name, AROS_BSTR_ADDR(deviceNode->dn_Name), /* GB: always NUL terminated */
139 NP_StackSize, deviceNode->dn_StackSize,
140 NP_Priority, deviceNode->dn_Priority,
141 TAG_DONE);
143 D(bug("[RunHandler] started, process structure is 0x%08x\n", process));
144 reply_port = CreateMsgPort();
145 if (!reply_port) {
146 FreeVec(BADDR(bpath));
147 return NULL;
150 /* build the startup packet */
151 dp = (struct DosPacket *) AllocDosObject(DOS_STDPKT, NULL);
152 if (!dp) {
153 DeleteMsgPort(reply_port);
154 FreeVec(BADDR(bpath));
155 return NULL;
157 dp->dp_Arg1 = (SIPTR)bpath;
158 dp->dp_Arg2 = (SIPTR)deviceNode->dn_Startup;
159 dp->dp_Arg3 = (SIPTR)MKBADDR(deviceNode);
160 dp->dp_Port = reply_port;
162 /* A handler can add volumes during startup, so we have to be fully functional before it
163 replies the startup packet */
165 D(bug("[RunHandler] sending startup packet port=%x\n", &(process->pr_MsgPort)));
166 PutMsg(&(process->pr_MsgPort), dp->dp_Link);
167 WaitPort(reply_port);
168 GetMsg(reply_port);
170 DeleteMsgPort(reply_port);
171 FreeVec(BADDR(bpath));
173 if (dp->dp_Res1 == DOSFALSE)
175 D(bug("[RunHandler] handler failed startup [%d]\n", dp->dp_Res2));
176 process = NULL;
177 deviceNode->dn_Task = NULL; /* Some handlers (e.g. SFS) don't clear dn_Task upon failure. */
179 D(else bug("[RunHandler] '%b' now online, dn_Task 0x%p, pr_MsgPort 0x%p\n", deviceNode->dn_Name, deviceNode->dn_Task, &process->pr_MsgPort);)
181 FreeDosObject(DOS_STDPKT, dp);
183 return process ? &process->pr_MsgPort : NULL;