added concrete implementations of putc(), getc(), getchar() and gets()
[tangerine.git] / rom / dos / lddemon.c
blob9fa3e16cc4db7dad994b768c6d260670d0a6de97
1 /*
2 Copyright © 1995-2007, The AROS Development Team. All rights reserved.
3 $Id$
5 Loader for shared libraries and devices.
6 */
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>
18 #include <dos/dos.h>
19 #include <dos/dosextens.h>
20 #include <dos/dostags.h>
21 #include <aros/asmcall.h>
22 #define DEBUG 0
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
30 #include <string.h>
32 #undef SysBase
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);
57 struct LDDMsg
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 */
69 #ifdef LIBEND
70 #undef LIBEND
71 #endif
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 =
83 RTC_MATCHWORD,
84 (struct Resident *)&LDDemon_resident,
85 &LIBEND,
86 RTF_AFTERDOS,
87 VERSION_NUMBER,
88 NT_PROCESS,
89 -125,
90 (STRPTR)name,
91 (STRPTR)&version[6],
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
103 directories.
105 static BPTR
106 LDLoad(
107 struct Process *caller,
108 STRPTR name,
109 STRPTR basedir,
110 struct DosLibrary *DOSBase
113 struct ExecBase *SysBase = DOSBase->dl_SysBase;
114 struct Process *me = (struct Process *)FindTask(NULL);
115 BPTR seglist = NULL;
116 STRPTR path;
117 ULONG pathLen;
118 int delimPos;
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
124 though.
126 D(bug(
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);
135 if (path) {
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);
162 if (path) {
163 if (!seglist) {
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);
171 } else
172 seglist =LoadSeg(name);
174 return seglist;
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;
185 BPTR seg = seglist;
187 while(seg)
189 STRPTR addr= (STRPTR)((IPTR)BADDR(seg)-sizeof(ULONG));
190 ULONG size = *(ULONG *)addr;
192 for(
193 addr += sizeof(BPTR) + sizeof(ULONG),
194 size -= sizeof(BPTR) + sizeof(ULONG);
195 size >= sizeof(struct Resident) ;
196 size -= 2, addr += 2
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 )
204 struct Library *lib;
206 D(bug("[LDInit] Calling InitResident(%p) on %s\n", res, res->rt_Name));
207 Forbid();
208 lib = InitResident(res, seglist);
209 Permit();
210 D(bug("[LDInit] Done calling InitResident(%p) on %s\n", res, res->rt_Name));
211 if( lib == NULL )
212 UnLoadSeg(seglist);
213 return lib;
216 seg = *(BPTR *)BADDR(seg);
218 D(bug("[LDInit] Couldn't find Resident for %p\n", seglist));
219 UnLoadSeg(seglist);
220 return NULL;
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)
259 struct LDObjectNode
261 struct Node ldon_Node;
262 struct SignalSemaphore ldon_SigSem;
263 ULONG ldon_AccessCount;
264 #if CHECK_DEPENDENCY
265 struct Task *ldon_FirstLocker;
266 #endif
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);
274 if (ret)
276 ULONG len = strlen(name);
277 STRPTR dupname = AllocVec(len+1, MEMF_ANY);
278 if (dupname)
280 CopyMem(name, dupname, len);
281 dupname[len] = '\0';
282 ret->ldon_Node.ln_Name = dupname;
283 InitSemaphore(&ret->ldon_SigSem);
284 ret->ldon_AccessCount = 0;
286 #if CHECK_DEPENDENCY
287 ret->ldon_FirstLocker = FindTask(0);
288 #endif
290 return ret;
292 FreeVec(ret);
295 return NULL;
298 VOID LDDestroyObjectNode(struct LDObjectNode *object, struct DosLibrary *DOSBase)
300 struct ExecBase *SysBase = DOSBase->dl_SysBase;
302 FreeVec(object->ldon_Node.ln_Name);
303 FreeVec(object);
306 AROS_LH2(struct Library *, OpenLibrary,
307 AROS_LHA(STRPTR, libname, A1),
308 AROS_LHA(ULONG, version, D0),
309 struct ExecBase *, SysBase, 0, Dos)
311 AROS_LIBFUNC_INIT
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
339 situation like this:
341 Process A opens L --------> LDDemon loads L and locks sem S
344 1 / \ 3
346 / 2 \
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
353 Proces B will never
354 respond to L.
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);
367 if (!object)
369 object = LDNewObjectNode(stripped_libname, DOSBase);
370 if (object)
372 AddTail(&DOSBase->dl_LDObjectsList, (struct Node *)object);
376 if (object)
378 object->ldon_AccessCount += 1;
380 #if CHECK_DEPENDENCY
381 else
383 struct Task *curtask = FindTask(0);
384 struct ETask *et = GetETask(curtask);
386 D(bug("Checking for circular dependency\n"));
387 if (et)
389 while (curtask && curtask != object->ldon_FirstLocker)
390 curtask = et->et_Parent;
392 if (curtask)
394 bug("Circular dependency found!\n");
395 object = NULL;
399 #endif
400 ReleaseSemaphore(&DOSBase->dl_LDObjectsListSigSem);
402 if (!object)
403 return NULL;
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 */
414 struct LDDMsg ldd;
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... :)
451 Forbid();
452 tmplib = (struct Library *)FindName(&SysBase->LibList, stripped_libname);
453 Permit();
455 if( tmplib != NULL )
456 library = tmplib;
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"));
470 else
471 library = NULL;
475 if (library == NULL)
478 the library is not on disk so
479 check Resident List
482 struct Resident *resident;
484 resident = FindResident(stripped_libname);
485 if (resident)
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);
508 else
509 ReleaseSemaphore(&object->ldon_SigSem);
510 ReleaseSemaphore(&DOSBase->dl_LDObjectsListSigSem);
512 return library;
514 AROS_LIBFUNC_EXIT
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)
524 AROS_LIBFUNC_INIT
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);
544 if (!object)
546 object = LDNewObjectNode(stripped_devname, DOSBase);
547 if (object)
549 AddTail(&DOSBase->dl_LDObjectsList, (struct Node*)object);
553 if (object)
555 object->ldon_AccessCount += 1;
557 #if CHECK_DEPENDENCY
558 else
560 struct Task *curtask = FindTask(0);
561 struct ETask *et = GetETask(curtask);
563 if (et)
565 while (curtask && curtask != object->ldon_FirstLocker)
566 curtask = et->et_Parent;
568 if (curtask)
570 bug("[LDCaller] Circular dependency found!\n");
571 object = NULL;
575 #endif
576 ReleaseSemaphore(&DOSBase->dl_LDObjectsListSigSem);
578 if (!object)
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 */
588 struct LDDMsg ldd;
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)
613 Forbid();
614 tmpdev = (struct Device *)FindName(&SysBase->DeviceList, stripped_devname);
615 Permit();
617 if(tmpdev != NULL)
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);
646 else
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;
654 AROS_LIBFUNC_EXIT
657 AROS_LH1(void, CloseLibrary,
658 AROS_LHA(struct Library *, library, A1),
659 struct ExecBase *, SysBase, 0, Dos)
661 AROS_LIBFUNC_INIT
663 struct DosLibrary *DOSBase = SysBase->ex_RamLibPrivate;
664 BPTR seglist;
666 if( library != NULL )
668 Forbid();
669 seglist = AROS_LVO_CALL0(BPTR, struct Library *, library, 2, );
670 if( seglist )
672 DOSBase->dl_LDReturn = MEM_TRY_AGAIN;
674 /* Safe to call from a Task */
675 UnLoadSeg(seglist);
677 Permit();
680 AROS_LIBFUNC_EXIT
683 AROS_LH1(void, CloseDevice,
684 AROS_LHA(struct IORequest *, iORequest, A1),
685 struct ExecBase *, SysBase, 0, Dos)
687 AROS_LIBFUNC_INIT
688 struct DosLibrary *DOSBase = SysBase->ex_RamLibPrivate;
689 BPTR seglist = NULL;
691 Forbid();
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;
698 if( seglist )
700 DOSBase->dl_LDReturn = MEM_TRY_AGAIN;
701 UnLoadSeg(seglist);
704 Permit();
705 AROS_LIBFUNC_EXIT
708 AROS_LH1(void, RemLibrary,
709 AROS_LHA(struct Library *, library, A1),
710 struct ExecBase *, SysBase, 0, Dos)
712 AROS_LIBFUNC_INIT
714 struct DosLibrary *DOSBase = SysBase->ex_RamLibPrivate;
715 BPTR seglist;
717 Forbid();
718 seglist = AROS_LVO_CALL1(BPTR,
719 AROS_LCA(struct Library *, library, D0),
720 struct Library *, library, 3, );
721 if( seglist )
723 DOSBase->dl_LDReturn = MEM_TRY_AGAIN;
724 UnLoadSeg(seglist);
726 Permit();
728 AROS_LIBFUNC_EXIT
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)
737 AROS_USERFUNC_INIT
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. */
746 Forbid();
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 )
755 RemLibrary(library);
756 /* Did it really go away? */
757 if( DOSBase->dl_LDReturn != MEM_DID_NOTHING )
759 /* Yes! Return it. */
760 Permit();
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. */
780 Permit();
781 return MEM_TRY_AGAIN;
784 /* Go on to next library. */
785 library = (struct Library *)library->lib_Node.ln_Succ;
787 Permit();
788 return MEM_DID_NOTHING;
790 AROS_USERFUNC_EXIT
794 void LDDemon()
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)
805 AROS_USERFUNC_INIT
807 struct DosLibrary *DOSBase = SysBase->ex_RamLibPrivate;
808 struct LDDMsg *ldd;
810 for(;;)
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,
820 ldd->ldd_Name,
821 ldd->ldd_BaseDir,
822 DOSBase);
824 D(bug("[LDDemon] Replying with %p as result\n", ldd->ldd_Return));
825 ReplyMsg((struct Message *)ldd);
826 } /* messages available */
829 AROS_USERFUNC_EXIT
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)
838 AROS_USERFUNC_INIT
840 struct DosLibrary *DOSBase;
841 struct TagItem tags[] =
843 { NP_Entry, (IPTR)LDDemon },
844 { NP_Input, 0 },
845 { NP_Output, 0 },
846 { NP_WindowPtr, -1 },
847 { NP_Name, (IPTR)ldDemonName },
848 { NP_StackSize, AROS_STACKSIZE },
849 { TAG_END , 0 }
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);
908 return 0;
910 AROS_USERFUNC_EXIT
913 const int LIBEND TEXT_SECTION = 1;