2 Copyright © 1995-2007, The AROS Development Team. All rights reserved.
5 Loader for shared libraries and devices.
8 #include <exec/execbase.h>
9 #include <exec/resident.h>
10 #include <exec/memory.h>
11 #include <exec/errors.h>
12 #include <exec/libraries.h>
13 #include <exec/devices.h>
14 #include <exec/ports.h>
15 #include <exec/lists.h>
16 #include <exec/alerts.h>
17 #include <exec/tasks.h>
19 #include <dos/dosextens.h>
20 #include <dos/dostags.h>
21 #include <aros/asmcall.h>
23 #include <aros/debug.h>
25 #include <proto/exec.h>
26 #include <proto/dos.h>
27 #include "dos_intern.h"
28 #include LC_LIBDEFS_FILE
34 #define CHECK_DEPENDENCY 1
36 /* Please leave them here! They are needed on Linux-M68K */
37 AROS_LD2(struct Library
*, OpenLibrary
,
38 AROS_LDA(STRPTR
, libname
, A1
),
39 AROS_LDA(ULONG
, version
, D0
),
40 struct ExecBase
*, SysBase
, 0, Dos
);
41 AROS_LD4(BYTE
, OpenDevice
,
42 AROS_LDA(STRPTR
, devname
, A0
),
43 AROS_LDA(ULONG
, unitNumber
, D0
),
44 AROS_LDA(struct IORequest
*, iORequest
, A1
),
45 AROS_LDA(ULONG
, flags
, D1
),
46 struct ExecBase
*, SysBase
, 0, Dos
);
47 AROS_LD1(void, CloseLibrary
,
48 AROS_LDA(struct Library
*, library
, A1
),
49 struct ExecBase
*, SysBase
, 0, Dos
);
50 AROS_LD1(void, CloseDevice
,
51 AROS_LDA(struct IORequest
*, iORequest
, A1
),
52 struct ExecBase
*, SysBase
, 0, Dos
);
53 AROS_LD1(void, RemLibrary
,
54 AROS_LDA(struct Library
*, library
, A1
),
55 struct ExecBase
*, SysBase
, 0, Dos
);
59 struct Message ldd_Msg
; /* Message link */
60 struct MsgPort ldd_ReplyPort
; /* Callers ReplyPort */
62 STRPTR ldd_Name
; /* Name of thing to load */
63 ULONG ldd_Version
; /* Version of thing to load */
65 STRPTR ldd_BaseDir
; /* Base directory to load from */
66 struct Library
* ldd_Return
; /* The result */
72 #define LIBEND LDDemon_end
74 #include <libcore/compiler.h>
76 static const char name
[];
77 static const char version
[];
78 extern const int LIBEND TEXT_SECTION
;
79 static ULONG
AROS_SLIB_ENTRY(Init
, LDDemon
)();
81 const struct Resident LDDemon_resident
=
84 (struct Resident
*)&LDDemon_resident
,
92 AROS_SLIB_ENTRY(Init
,LDDemon
)
95 static const char name
[] = "LDDemon";
96 static const char version
[] = "$VER: LDDemon 41.3 (11.3.2007)\r\n";
97 static const char ldDemonName
[] = "Lib & Dev Loader Daemon";
100 BPTR LDLoad( caller, name, basedir, DOSBase )
101 Try and load a segment from disk for the object <name>, relative
102 to directory <basedir>. Will also try <caller>'s current and home
107 struct Process
*caller
,
110 struct DosLibrary
*DOSBase
113 struct ExecBase
*SysBase
= DOSBase
->dl_SysBase
;
114 struct Process
*me
= (struct Process
*)FindTask(NULL
);
121 If the caller was a process, we have more scope for loading
122 libraries. We can load them from the callers current directory,
123 or from the PROGDIR: assign. These could both be the same
127 "[LDLoad] caller=(%p) %s, name=%s, basedir=%s\n",
128 caller
, caller
->pr_Task
.tc_Node
.ln_Name
, name
, basedir
131 if (!strstr(name
, ":")) {
132 delimPos
= strlen(basedir
);
133 pathLen
= delimPos
+ strlen(name
) + 2;
134 path
= AllocMem(pathLen
, MEMF_ANY
);
136 strcpy(path
, basedir
);
137 path
[delimPos
] = '/';
138 strcpy(&path
[delimPos
+ 1], name
);
140 if (__is_process(caller
))
142 /* Try the current directory of the caller */
144 D(bug("[LDLoad] Process\n"));
145 me
->pr_CurrentDir
= caller
->pr_CurrentDir
;
146 D(bug("[LDLoad] Trying currentdir\n"));
147 seglist
= LoadSeg(name
);
148 if ((!seglist
) && path
)
149 seglist
= LoadSeg(path
);
151 /* The the program directory of the caller */
152 if((!seglist
) && (caller
->pr_HomeDir
!= NULL
))
154 D(bug("[LDLoad] Trying homedir\n"));
155 me
->pr_CurrentDir
= caller
->pr_HomeDir
;
156 seglist
= LoadSeg(name
);
157 if ((!seglist
) && path
)
158 seglist
= LoadSeg(path
);
164 /* Nup, lets try the default directory as supplied. */
165 D(bug("[LDLoad] Trying defaultir\n"));
166 path
[delimPos
] = ':';
167 seglist
= LoadSeg(path
);
169 FreeMem(path
, pathLen
);
172 seglist
=LoadSeg(name
);
178 Library *LDInit(seglist, DOSBase)
179 Initialise the library.
181 static struct Library
*
182 LDInit(BPTR seglist
, struct DosLibrary
*DOSBase
)
184 struct ExecBase
*SysBase
= DOSBase
->dl_SysBase
;
189 STRPTR addr
= (STRPTR
)((IPTR
)BADDR(seg
)-sizeof(ULONG
));
190 ULONG size
= *(ULONG
*)addr
;
193 addr
+= sizeof(BPTR
) + sizeof(ULONG
),
194 size
-= sizeof(BPTR
) + sizeof(ULONG
);
195 size
>= sizeof(struct Resident
) ;
197 // size -= AROS_PTRALIGN, addr += AROS_PTRALIGN
200 struct Resident
*res
= (struct Resident
*)addr
;
201 if( res
->rt_MatchWord
== RTC_MATCHWORD
202 && res
->rt_MatchTag
== res
)
206 D(bug("[LDInit] Calling InitResident(%p) on %s\n", res
, res
->rt_Name
));
208 lib
= InitResident(res
, seglist
);
210 D(bug("[LDInit] Done calling InitResident(%p) on %s\n", res
, res
->rt_Name
));
216 seg
= *(BPTR
*)BADDR(seg
);
218 D(bug("[LDInit] Couldn't find Resident for %p\n", seglist
));
223 struct Library
*(*__OpenLibrary
)();
224 BYTE (*__OpenDevice
)();
226 #define ExecOpenLibrary(libname, version) \
227 AROS_CALL2(struct Library *, __OpenLibrary, \
228 AROS_LCA(STRPTR, libname, A1), \
229 AROS_LCA(ULONG, version, D0), \
230 struct ExecBase *, SysBase)
232 #define ExecOpenDevice(devname, unitNumber, iORequest, flags) \
233 AROS_CALL4(BYTE, __OpenDevice, \
234 AROS_LCA(STRPTR, devname, A0), \
235 AROS_LCA(ULONG, unitNumber, D0), \
236 AROS_LCA(struct IORequest *, iORequest, A1), \
237 AROS_LCA(ULONG, flags, D1), \
238 struct ExecBase *, SysBase)
241 struct Library *AROS_SLIB_ENTRY(OpenLibrary, Exec)();
242 BYTE AROS_SLIB_ENTRY(OpenDevice, Exec)();
244 #define ExecOpenLibrary(libname, version) \
245 AROS_CALL2(struct Library *, &AROS_SLIB_ENTRY(OpenLibrary, Exec), \
246 AROS_LCA(STRPTR, libname, A1), \
247 AROS_LCA(ULONG, version, D0), \
248 struct ExecBase *, SysBase)
250 #define ExecOpenDevice(devname, unitNumber, iORequest, flags) \
251 AROS_CALL4(BYTE, &AROS_SLIB_ENTRY(OpenDevice, Exec), \
252 AROS_LCA(STRPTR, devname, A0), \
253 AROS_LCA(ULONG, unitNumber, D0), \
254 AROS_LCA(struct IORequest *, iORequest, A1), \
255 AROS_LCA(ULONG, flags, D1), \
256 struct ExecBase *, SysBase)
261 struct Node ldon_Node
;
262 struct SignalSemaphore ldon_SigSem
;
263 ULONG ldon_AccessCount
;
265 struct Task
*ldon_FirstLocker
;
269 struct LDObjectNode
*LDNewObjectNode(STRPTR name
, struct DosLibrary
*DOSBase
)
271 struct ExecBase
*SysBase
= DOSBase
->dl_SysBase
;
273 struct LDObjectNode
*ret
= AllocVec(sizeof(struct LDObjectNode
), MEMF_ANY
);
276 ULONG len
= strlen(name
);
277 STRPTR dupname
= AllocVec(len
+1, MEMF_ANY
);
280 CopyMem(name
, dupname
, len
);
282 ret
->ldon_Node
.ln_Name
= dupname
;
283 InitSemaphore(&ret
->ldon_SigSem
);
284 ret
->ldon_AccessCount
= 0;
287 ret
->ldon_FirstLocker
= FindTask(0);
298 VOID
LDDestroyObjectNode(struct LDObjectNode
*object
, struct DosLibrary
*DOSBase
)
300 struct ExecBase
*SysBase
= DOSBase
->dl_SysBase
;
302 FreeVec(object
->ldon_Node
.ln_Name
);
306 AROS_LH2(struct Library
*, OpenLibrary
,
307 AROS_LHA(STRPTR
, libname
, A1
),
308 AROS_LHA(ULONG
, version
, D0
),
309 struct ExecBase
*, SysBase
, 0, Dos
)
313 struct DosLibrary
*DOSBase
= SysBase
->ex_RamLibPrivate
;
314 struct Library
*library
, *tmplib
;
315 STRPTR stripped_libname
;
316 struct LDObjectNode
*object
;
319 We get the DOS semaphore to prevent the following:
320 - task 1 tries to open foobar.library, needs to load it from disk...
321 - task 1 Permit()'s (since its not doing list things)
322 - task switch (whilst LDDemon MAY get process next it might not)
323 - task 2 tries to open foobar.library, needs to load it from disk...
324 - it also requests LDDemon to open foobar.library, so it is now
325 trying to open it twice
327 We block all OpenLibrary() callers from searching the list until
328 all the other OpenLibrary() callers have returned. That way,
329 task #2 won't ask for foobar.library until task #1 has got its
330 response back from the LDDemon process.
332 falemagn: I changed the implementation of all that.
333 There's a list of "LDObjectNodes", that contain the name
334 of the object being opened. Since the problem is that more
335 processes can attempt to open the same device/library Instead of
336 locking a global semaphore until the opening is done, we lock a
337 per-object semaphore, so that others libraries/devices can be opened
338 in the meantime. Before a deadlock could happen if there was a
341 Process A opens L --------> LDDemon loads L and locks sem S
347 L spawns a process B and ----------> The process opens
348 waits for it to respond a library but gets loked
349 to a message <----/---- because sem S is locked
356 Hopefully this won't happen anymore now.
360 /* We use FilePart() because the liblist is built from resident IDs,
361 and contain no path. Eg. The user can request gadgets/foo.gadget,
362 but the resident only contains foo.gadget
364 stripped_libname
= FilePart(libname
);
365 ObtainSemaphore(&DOSBase
->dl_LDObjectsListSigSem
);
366 object
= (struct LDObjectNode
*)FindName(&DOSBase
->dl_LDObjectsList
, stripped_libname
);
369 object
= LDNewObjectNode(stripped_libname
, DOSBase
);
372 AddTail(&DOSBase
->dl_LDObjectsList
, (struct Node
*)object
);
378 object
->ldon_AccessCount
+= 1;
383 struct Task
*curtask
= FindTask(0);
384 struct ETask
*et
= GetETask(curtask
);
386 D(bug("Checking for circular dependency\n"));
389 while (curtask
&& curtask
!= object
->ldon_FirstLocker
)
390 curtask
= et
->et_Parent
;
394 bug("Circular dependency found!\n");
400 ReleaseSemaphore(&DOSBase
->dl_LDObjectsListSigSem
);
406 ObtainSemaphore(&object
->ldon_SigSem
);
408 /* Call the EXEC's OpenLibrary function */
409 library
= ExecOpenLibrary(stripped_libname
, version
);
411 if( library
== NULL
)
413 /* Use stack for now, this could be a security hole */
416 ldd
.ldd_ReplyPort
.mp_SigBit
= SIGB_SINGLE
;
417 ldd
.ldd_ReplyPort
.mp_SigTask
= FindTask(NULL
);
418 NEWLIST(&ldd
.ldd_ReplyPort
.mp_MsgList
);
419 ldd
.ldd_ReplyPort
.mp_Flags
= PA_SIGNAL
;
420 ldd
.ldd_ReplyPort
.mp_Node
.ln_Type
= NT_MSGPORT
;
422 ldd
.ldd_Msg
.mn_Node
.ln_Type
= NT_MESSAGE
;
424 ldd
.ldd_Msg
.mn_Length
= sizeof(struct LDDMsg
);
425 ldd
.ldd_Msg
.mn_ReplyPort
= &ldd
.ldd_ReplyPort
;
427 ldd
.ldd_Name
= libname
;
428 ldd
.ldd_Version
= version
;
429 ldd
.ldd_BaseDir
= "libs";
431 SetSignal(0, SIGF_SINGLE
);
432 D(bug("[LDCaller] Sending request for %s v%ld\n", libname
, version
));
433 PutMsg(DOSBase
->dl_LDDemonPort
, (struct Message
*)&ldd
);
434 WaitPort(&ldd
.ldd_ReplyPort
);
435 D(bug("[LDCaller] Returned\n"));
437 library
= LDInit(ldd
.ldd_Return
, DOSBase
);
439 if( library
!= NULL
)
442 We have to Forbid() here because we need to look through the list
443 again, we also need to call the libOpen vector, which wants us
444 under a Forbidden state.
446 falemagn: well, it doesn't want us under a Forbidden state, it just
447 wants to be single threaded, and it is, in fact, so no
448 need for Forbid()/Permit() around open. I Hope... :)
452 tmplib
= (struct Library
*)FindName(&SysBase
->LibList
, stripped_libname
);
458 if(library
->lib_Version
>= version
)
460 D(bug("[LDCaller] Calling libOpen() of %s\n",
461 library
->lib_Node
.ln_Name
));
463 library
= AROS_LVO_CALL1(struct Library
*,
464 AROS_LCA(ULONG
, version
, D0
),
465 struct Library
*, library
, 1,
468 D(bug("[LDCaller] libOpen() returned\n"));
478 the library is not on disk so
482 struct Resident
*resident
;
484 resident
= FindResident(stripped_libname
);
487 if (resident
->rt_Version
>= version
)
489 if (InitResident(resident
, NULL
))
490 library
= ExecOpenLibrary(stripped_libname
, version
);
496 Release the semaphore here, after calling Open vector. This
497 means that library open is singlethreaded by the semaphore.
498 It also handles circular dependant libraries. (Won't deadlock),
499 and recursive OpenLibrary calls (Semaphores nest when obtained
500 several times in a row by the same task).
502 ObtainSemaphore(&DOSBase
->dl_LDObjectsListSigSem
);
503 if (--(object
->ldon_AccessCount
) == 0)
505 Remove((struct Node
*)object
);
506 LDDestroyObjectNode(object
, DOSBase
);
509 ReleaseSemaphore(&object
->ldon_SigSem
);
510 ReleaseSemaphore(&DOSBase
->dl_LDObjectsListSigSem
);
517 AROS_LH4(BYTE
, OpenDevice
,
518 AROS_LHA(STRPTR
, devname
, A0
),
519 AROS_LHA(ULONG
, unitNumber
, D0
),
520 AROS_LHA(struct IORequest
*, iORequest
, A1
),
521 AROS_LHA(ULONG
, flags
, D1
),
522 struct ExecBase
*, SysBase
, 0, Dos
)
526 struct DosLibrary
*DOSBase
= SysBase
->ex_RamLibPrivate
;
527 struct Device
*tmpdev
;
528 STRPTR stripped_devname
;
529 struct LDObjectNode
*object
;
531 iORequest
->io_Error
= IOERR_OPENFAIL
;
532 iORequest
->io_Device
= NULL
;
534 /* We use FilePart() because the liblist is built from resident IDs,
535 which contain no path. Eg. The user can request gadgets/foo.gadget,
536 but the resident only contains foo.gadget
539 stripped_devname
= FilePart(devname
);
541 ObtainSemaphore(&DOSBase
->dl_LDObjectsListSigSem
);
542 object
= (struct LDObjectNode
*)FindName(&DOSBase
->dl_LDObjectsList
, stripped_devname
);
546 object
= LDNewObjectNode(stripped_devname
, DOSBase
);
549 AddTail(&DOSBase
->dl_LDObjectsList
, (struct Node
*)object
);
555 object
->ldon_AccessCount
+= 1;
560 struct Task
*curtask
= FindTask(0);
561 struct ETask
*et
= GetETask(curtask
);
565 while (curtask
&& curtask
!= object
->ldon_FirstLocker
)
566 curtask
= et
->et_Parent
;
570 bug("[LDCaller] Circular dependency found!\n");
576 ReleaseSemaphore(&DOSBase
->dl_LDObjectsListSigSem
);
579 return IOERR_OPENFAIL
;
581 ObtainSemaphore(&object
->ldon_SigSem
);
583 ExecOpenDevice(stripped_devname
, unitNumber
, iORequest
, flags
);
585 if (iORequest
->io_Error
)
587 /* Use stack for now, this could be a security hole */
590 ldd
.ldd_ReplyPort
.mp_SigBit
= SIGB_SINGLE
;
591 ldd
.ldd_ReplyPort
.mp_SigTask
= FindTask(NULL
);
592 NEWLIST(&ldd
.ldd_ReplyPort
.mp_MsgList
);
593 ldd
.ldd_ReplyPort
.mp_Flags
= PA_SIGNAL
;
594 ldd
.ldd_ReplyPort
.mp_Node
.ln_Type
= NT_MSGPORT
;
596 ldd
.ldd_Msg
.mn_Node
.ln_Type
= NT_MESSAGE
;
597 ldd
.ldd_Msg
.mn_Length
= sizeof(struct LDDMsg
);
598 ldd
.ldd_Msg
.mn_ReplyPort
= &ldd
.ldd_ReplyPort
;
600 ldd
.ldd_Name
= devname
;
601 ldd
.ldd_BaseDir
= "devs";
603 SetSignal(0, SIGF_SINGLE
);
604 D(bug("[LDCaller] Sending request for %s\n", devname
));
605 PutMsg(DOSBase
->dl_LDDemonPort
, (struct Message
*)&ldd
);
606 WaitPort(&ldd
.ldd_ReplyPort
);
607 D(bug("[LDCaller] Returned\n"));
609 iORequest
->io_Device
= (struct Device
*)LDInit(ldd
.ldd_Return
, DOSBase
);
611 if(iORequest
->io_Device
)
614 tmpdev
= (struct Device
*)FindName(&SysBase
->DeviceList
, stripped_devname
);
618 iORequest
->io_Device
= tmpdev
;
620 iORequest
->io_Error
= 0;
621 iORequest
->io_Message
.mn_Node
.ln_Type
= NT_REPLYMSG
;
623 D(bug("[LDCaller] Calling devOpen() of %s unit %ld\n",
624 iORequest
->io_Device
->dd_Library
.lib_Node
.ln_Name
, unitNumber
));
626 AROS_LVO_CALL3NR(void,
627 AROS_LCA(struct IORequest
*, iORequest
, A1
),
628 AROS_LCA(ULONG
, unitNumber
, D0
),
629 AROS_LCA(ULONG
, flags
, D1
),
630 struct Device
*, iORequest
->io_Device
, 1,
633 D(bug("[LDCaller] devOpen() returned\n"));
635 if (iORequest
->io_Error
)
636 iORequest
->io_Device
= NULL
;
640 ObtainSemaphore(&DOSBase
->dl_LDObjectsListSigSem
);
641 if (--(object
->ldon_AccessCount
) == 0)
643 Remove((struct Node
*)object
);
644 LDDestroyObjectNode(object
, DOSBase
);
647 ReleaseSemaphore(&object
->ldon_SigSem
);
648 ReleaseSemaphore(&DOSBase
->dl_LDObjectsListSigSem
);
650 D(bug("%s", iORequest
->io_Error
?"[LDCaller] Couldn't open the device\n":""));
652 return iORequest
->io_Error
;
657 AROS_LH1(void, CloseLibrary
,
658 AROS_LHA(struct Library
*, library
, A1
),
659 struct ExecBase
*, SysBase
, 0, Dos
)
663 struct DosLibrary
*DOSBase
= SysBase
->ex_RamLibPrivate
;
666 if( library
!= NULL
)
669 seglist
= AROS_LVO_CALL0(BPTR
, struct Library
*, library
, 2, );
672 DOSBase
->dl_LDReturn
= MEM_TRY_AGAIN
;
674 /* Safe to call from a Task */
683 AROS_LH1(void, CloseDevice
,
684 AROS_LHA(struct IORequest
*, iORequest
, A1
),
685 struct ExecBase
*, SysBase
, 0, Dos
)
688 struct DosLibrary
*DOSBase
= SysBase
->ex_RamLibPrivate
;
692 if( iORequest
->io_Device
!= NULL
)
694 seglist
= AROS_LVO_CALL1(BPTR
,
695 AROS_LCA(struct IORequest
*, iORequest
, A1
),
696 struct Device
, iORequest
->io_Device
, 2, );
697 iORequest
->io_Device
=(struct Device
*)-1;
700 DOSBase
->dl_LDReturn
= MEM_TRY_AGAIN
;
708 AROS_LH1(void, RemLibrary
,
709 AROS_LHA(struct Library
*, library
, A1
),
710 struct ExecBase
*, SysBase
, 0, Dos
)
714 struct DosLibrary
*DOSBase
= SysBase
->ex_RamLibPrivate
;
718 seglist
= AROS_LVO_CALL1(BPTR
,
719 AROS_LCA(struct Library
*, library
, D0
),
720 struct Library
*, library
, 3, );
723 DOSBase
->dl_LDReturn
= MEM_TRY_AGAIN
;
731 AROS_UFH3(LONG
, LDFlush
,
732 AROS_UFHA(struct MemHandlerData
*, lmhd
, A0
),
733 AROS_UFHA(APTR
, data
, A1
),
734 AROS_UFHA(struct ExecBase
*, SysBase
, A6
)
739 struct DosLibrary
*DOSBase
= SysBase
->ex_RamLibPrivate
;
740 struct Library
*library
;
742 D(bug("[LDDemon] Flush called\n"));
743 DOSBase
->dl_LDReturn
= MEM_DID_NOTHING
;
745 /* Forbid() is already done, but I don't want to rely on it. */
748 /* Follow the linked list of shared libraries. */
749 library
= (struct Library
*)SysBase
->LibList
.lh_Head
;
750 while(library
->lib_Node
.ln_Succ
!= NULL
)
752 /* Flush libraries with a 0 open count */
753 if( ! library
->lib_OpenCnt
)
756 /* Did it really go away? */
757 if( DOSBase
->dl_LDReturn
!= MEM_DID_NOTHING
)
759 /* Yes! Return it. */
761 return MEM_TRY_AGAIN
;
764 /* Go on to next library. */
765 library
= (struct Library
*)library
->lib_Node
.ln_Succ
;
768 /* Do the same with the device list. */
769 library
= (struct Library
*)SysBase
->DeviceList
.lh_Head
;
770 while(library
->lib_Node
.ln_Succ
!= NULL
)
772 /* Flush libraries with a 0 open count */
773 if( ! library
->lib_OpenCnt
)
775 RemDevice((struct Device
*)library
);
776 /* Did it really go away? */
777 if( DOSBase
->dl_LDReturn
!= MEM_DID_NOTHING
)
779 /* Yes! Return it. */
781 return MEM_TRY_AGAIN
;
784 /* Go on to next library. */
785 library
= (struct Library
*)library
->lib_Node
.ln_Succ
;
788 return MEM_DID_NOTHING
;
795 The LDDemon process entry. Sits around and does nothing until a
796 request for a library comes, when it will then find the library
797 and hopefully open it.
799 AROS_UFH3(void, LDDemon
,
800 AROS_UFHA(STRPTR
, argstr
, A0
),
801 AROS_UFHA(ULONG
, arglen
, D0
),
802 AROS_UFHA(struct ExecBase
*, SysBase
, A6
)
807 struct DosLibrary
*DOSBase
= SysBase
->ex_RamLibPrivate
;
812 WaitPort(DOSBase
->dl_LDDemonPort
);
813 while( (ldd
= (struct LDDMsg
*)GetMsg(DOSBase
->dl_LDDemonPort
)) )
815 D(bug("[LDDemon] Got a request for %s in %s\n",
816 ldd
->ldd_Name
, ldd
->ldd_BaseDir
));
818 ldd
->ldd_Return
= LDLoad(
819 ldd
->ldd_ReplyPort
.mp_SigTask
,
824 D(bug("[LDDemon] Replying with %p as result\n", ldd
->ldd_Return
));
825 ReplyMsg((struct Message
*)ldd
);
826 } /* messages available */
832 AROS_UFH3(ULONG
, AROS_SLIB_ENTRY(Init
, LDDemon
),
833 AROS_UFHA(ULONG
, dummy
, D0
),
834 AROS_UFHA(BPTR
, segList
, A0
),
835 AROS_UFHA(struct ExecBase
*, sysBase
, A6
)
840 struct DosLibrary
*DOSBase
;
841 struct TagItem tags
[] =
843 { NP_Entry
, (IPTR
)LDDemon
},
846 { NP_WindowPtr
, -1 },
847 { NP_Name
, (IPTR
)ldDemonName
},
848 { NP_StackSize
, AROS_STACKSIZE
},
852 /* We want version v41 of DOS, since it corresponds to AROS atm... */
853 if((DOSBase
= (struct DosLibrary
*)OpenLibrary("dos.library", 41)) == NULL
)
855 Alert(AT_DeadEnd
| AN_RAMLib
| AG_OpenLib
| AO_DOSLib
);
858 SysBase
->ex_RamLibPrivate
= DOSBase
;
860 if( (DOSBase
->dl_LDDemonPort
= CreateMsgPort()) == NULL
)
862 Alert( AN_RAMLib
| AG_NoMemory
| AT_DeadEnd
);
865 FreeSignal(DOSBase
->dl_LDDemonPort
->mp_SigBit
);
866 DOSBase
->dl_LDDemonPort
->mp_SigBit
= SIGBREAKB_CTRL_F
;
868 DOSBase
->dl_LDHandler
.is_Node
.ln_Name
= (STRPTR
)ldDemonName
;
869 DOSBase
->dl_LDHandler
.is_Node
.ln_Pri
= 0;
870 DOSBase
->dl_LDHandler
.is_Code
= (void (*)())LDFlush
;
871 DOSBase
->dl_LDHandler
.is_Data
= NULL
;
873 NEWLIST(&DOSBase
->dl_LDObjectsList
);
874 InitSemaphore(&DOSBase
->dl_LDObjectsListSigSem
);
875 AddMemHandler(&DOSBase
->dl_LDHandler
);
878 * Grab the semaphore ourself. The reason for this is that it will
879 * cause all other tasks to wait until we have finished initialising
880 * before they try and open something.
882 ObtainSemaphore(&DOSBase
->dl_LDObjectsListSigSem
);
884 #define SetFunc(offs,ptr) \
885 SetFunction(&SysBase->LibNode, (offs)*LIB_VECTSIZE, \
886 AROS_SLIB_ENTRY(ptr,Dos))
888 /* Do not set the vectors until you have initialised everything else. */
889 __OpenLibrary
= SetFunc(-92, OpenLibrary
);
890 __OpenDevice
= SetFunc(-74, OpenDevice
);
891 (void)SetFunc(-69, CloseLibrary
);
892 (void)SetFunc(-75, CloseDevice
);
893 (void)SetFunc(-67, RemLibrary
);
894 (void)SetFunc(-73, RemLibrary
);
896 if( !(DOSBase
->dl_LDDemonTask
= CreateNewProc((struct TagItem
*)tags
)) )
898 Alert( AT_DeadEnd
| AN_RAMLib
| AG_ProcCreate
);
901 /* Fix up the MsgPort */
903 DOSBase
->dl_LDDemonPort
->mp_SigTask
= DOSBase
->dl_LDDemonTask
;
905 /* Then unlock the semaphore to allow other processes to run. */
906 ReleaseSemaphore(&DOSBase
->dl_LDObjectsListSigSem
);
913 const int LIBEND TEXT_SECTION
= 1;