home *** CD-ROM | disk | FTP | other *** search
/ Aminet 18 / aminetcdnumber181997.iso / Aminet / misc / emu / AROSdev.lha / AROS / rom / dos / lddemon.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-27  |  6.9 KB  |  291 lines

  1. /*
  2.     (C) 1995-96 AROS - The Amiga Replacement OS
  3.     $Id: lddemon.c,v 1.13 1997/01/27 13:16:15 digulla Exp $
  4.     $Log: lddemon.c,v $
  5.     Revision 1.13  1997/01/27 13:16:15  digulla
  6.     The library/device is already added in InitResident(). Don't add it twice.
  7.  
  8.     Revision 1.12  1997/01/27 00:36:23    ldp
  9.     Polish
  10.  
  11.     Revision 1.11  1997/01/16 17:42:13    digulla
  12.     Polish
  13.  
  14.  
  15.     Desc: Loader for shared libraries and devices
  16.     Lang: english
  17. */
  18. #include <exec/execbase.h>
  19. #include <exec/resident.h>
  20. #include <exec/memory.h>
  21. #include <exec/errors.h>
  22. #include <exec/libraries.h>
  23. #include <proto/exec.h>
  24. #include <dos/dosextens.h>
  25. #include <proto/dos.h>
  26. #include "dos_intern.h"
  27.  
  28. static BPTR LDLoad(STRPTR name, STRPTR basedir, struct DosLibrary *DOSBase)
  29. {
  30.     BPTR seglist;
  31.     struct Process *me=(struct Process *)FindTask(NULL);
  32.     struct DosList *dl1, *dl2;
  33.     struct Process *caller=DOSBase->dl_LDCaller;
  34.  
  35.     if(caller->pr_Task.tc_Node.ln_Type==NT_PROCESS)
  36.     {
  37.     /* Try the caller's current dir */
  38.     me->pr_CurrentDir=caller->pr_CurrentDir;
  39.     seglist=LoadSeg(name);
  40.     if(seglist)
  41.         return seglist;
  42.     }
  43.     /* Try the system's default directory. */
  44.     dl1=LockDosList(LDF_ALL|LDF_READ);
  45.     dl2=FindDosEntry(dl1,basedir,LDF_VOLUMES);
  46.     if(dl2==NULL)
  47.     dl2=FindDosEntry(dl1,basedir,LDF_DEVICES|LDF_ASSIGNS);
  48.     if(dl2!=NULL)
  49.     {
  50.     struct FileHandle fh;
  51.     fh.fh_Unit  =dl2->dol_Unit;
  52.     fh.fh_Device=dl2->dol_Device;
  53.     me->pr_CurrentDir=MKBADDR(&fh);
  54.     seglist=LoadSeg(name);
  55.     }
  56.     UnLockDosList(LDF_ALL|LDF_READ);
  57.     return seglist;
  58. }
  59.  
  60. static struct Library *LDInit(BPTR seglist, struct DosLibrary *DOSBase)
  61. {
  62.     BPTR seg=seglist;
  63.     while(seg)
  64.     {
  65.     STRPTR addr=(STRPTR)BADDR(seg)-AROS_ALIGN(sizeof(ULONG));
  66.     ULONG size=*(ULONG *)addr;
  67.     for(;size>=sizeof(struct Resident);size-=AROS_PTRALIGN,addr+=AROS_PTRALIGN)
  68.     {
  69.         struct Resident *res=(struct Resident *)addr;
  70.         if(res->rt_MatchWord==RTC_MATCHWORD&&res->rt_MatchTag==res)
  71.         {
  72.         struct Library *lib=InitResident(res,seglist);
  73.         if(lib==NULL)
  74.             UnLoadSeg(seglist);
  75.         return lib;
  76.         }
  77.     }
  78.     seg=*(BPTR *)BADDR(seg);
  79.     }
  80.     UnLoadSeg(seglist);
  81.     return NULL;
  82. }
  83.  
  84. void LDDemon(void)
  85. {
  86.     extern struct DosLibrary *DOSBase;
  87.     BPTR seglist;
  88.     for(;;)
  89.     {
  90.     Wait(SIGF_DOS);
  91.     seglist=LDLoad(DOSBase->dl_LDName,(STRPTR)DOSBase->dl_LDPtr,DOSBase);
  92.     DOSBase->dl_LDPtr=LDInit(seglist,DOSBase);
  93.     Signal(&DOSBase->dl_LDCaller->pr_Task,SIGF_DOS);
  94.     }
  95. }
  96.  
  97. AROS_LH2(struct Library *,OpenLibrary,
  98. AROS_LHA(STRPTR,libName,A1),AROS_LHA(ULONG,version,D0),
  99. struct ExecBase *,sysbase,0,Dos)
  100. {
  101.     AROS_LIBFUNC_INIT
  102.     extern struct DosLibrary *DOSBase;
  103.     struct Library *library;
  104.     Forbid();
  105.     library=(struct Library *)FindName(&SysBase->LibList,libName);
  106.     if(library==NULL)
  107.     {
  108.     ObtainSemaphore(&DOSBase->dl_LDSigSem);
  109.     DOSBase->dl_LDCaller=(struct Process *)FindTask(NULL);
  110.     DOSBase->dl_LDName  =libName;
  111.     DOSBase->dl_LDPtr   ="libs:";
  112.     Signal((struct Task *)DOSBase->dl_LDDemon,SIGF_DOS);
  113.     Wait(SIGF_DOS);
  114.     library=(struct Library *)DOSBase->dl_LDPtr;
  115.     ReleaseSemaphore(&DOSBase->dl_LDSigSem);
  116.     }
  117.     if(library!=NULL)
  118.     {
  119.     if(library->lib_Version>=version)
  120.         library=AROS_LVO_CALL1(struct Library *,
  121.         AROS_LCA(ULONG,version,D0),
  122.         struct Library *,library,1,
  123.         );
  124.     else
  125.         library=NULL;
  126.     }
  127.     Permit();
  128.     return library;
  129.     AROS_LIBFUNC_EXIT
  130. }
  131.  
  132. AROS_LH4(BYTE,OpenDevice,
  133.     AROS_LHA(STRPTR,devName,A0),
  134.     AROS_LHA(ULONG,unitNumber,D0),
  135.     AROS_LHA(struct IORequest *,iORequest,A1),
  136.     AROS_LHA(ULONG,flags,D1),
  137.     struct ExecBase *,sysbase,0,Dos)
  138. {
  139.     AROS_LIBFUNC_INIT
  140.     extern struct DosLibrary *DOSBase;
  141.     struct Device *device;
  142.     UBYTE ret=IOERR_OPENFAIL;
  143.     Forbid();
  144.     device=(struct Device *)FindName(&SysBase->DeviceList,devName);
  145.     if(device==NULL)
  146.     {
  147.     ObtainSemaphore(&DOSBase->dl_LDSigSem);
  148.     DOSBase->dl_LDCaller=(struct Process *)FindTask(NULL);
  149.     DOSBase->dl_LDName  =devName;
  150.     DOSBase->dl_LDPtr   ="devs:";
  151.     Signal((struct Task *)DOSBase->dl_LDDemon,SIGF_DOS);
  152.     Wait(SIGF_DOS);
  153.     device=(struct Device *)DOSBase->dl_LDPtr;
  154.     ReleaseSemaphore(&DOSBase->dl_LDSigSem);
  155.     }
  156.     if(device!=NULL)
  157.     {
  158.     iORequest->io_Error=0;
  159.     iORequest->io_Device=device;
  160.     iORequest->io_Flags=flags;
  161.     iORequest->io_Message.mn_Node.ln_Type=NT_REPLYMSG;
  162.     AROS_LVO_CALL3(void,
  163.         AROS_LCA(struct IORequest *,iORequest,A1),
  164.         AROS_LCA(ULONG,unitNumber,D0),
  165.         AROS_LCA(ULONG,flags,D1),
  166.         struct Device *,device,1,
  167.     );
  168.     ret=iORequest->io_Error;
  169.     if(ret)
  170.         iORequest->io_Device=NULL;
  171.     }
  172.     Permit();
  173.     return ret;
  174.     AROS_LIBFUNC_EXIT
  175. }
  176.  
  177. AROS_LH1(void,CloseLibrary,
  178.     AROS_LHA(struct Library *,library,A1),
  179.     struct ExecBase *,sysbase,0,Dos)
  180. {
  181.     AROS_LIBFUNC_INIT
  182.     extern struct DosLibrary *DOSBase;
  183.     BPTR seglist;
  184.     if(library!=NULL)
  185.     {
  186.     Forbid();
  187.     seglist=AROS_LVO_CALL0(BPTR,
  188.         struct Library *,library,2,);
  189.     if(seglist)
  190.     {
  191.         DOSBase->dl_LDReturn=MEM_TRY_AGAIN;
  192.         UnLoadSeg(seglist);
  193.     }
  194.     Permit();
  195.     }
  196.     AROS_LIBFUNC_EXIT
  197. }
  198.  
  199. AROS_LH1(void,CloseDevice,
  200. AROS_LHA(struct IORequest *,iORequest,A1),
  201. struct ExecBase *,sysbase,0,Dos)
  202. {
  203.     AROS_LIBFUNC_INIT
  204.     extern struct DosLibrary *DOSBase;
  205.     BPTR seglist;
  206.     Forbid();
  207.     if(iORequest->io_Device!=NULL)
  208.     {
  209.     seglist=AROS_LVO_CALL1(BPTR,
  210.         AROS_LHA(struct IORequest *,iORequest,A1),
  211.         struct Device *,iORequest->io_Device,2,
  212.     );
  213.     iORequest->io_Device=(struct Device *)-1;
  214.     if(seglist)
  215.     {
  216.         DOSBase->dl_LDReturn=MEM_TRY_AGAIN;
  217.         UnLoadSeg(seglist);
  218.     }
  219.     }
  220.     Permit();
  221.     AROS_LIBFUNC_EXIT
  222. }
  223.  
  224. AROS_LH1(void,RemLibrary,
  225. AROS_LHA(struct Library *,library,A1),
  226. struct ExecBase *,sysbase,0,Dos)
  227. {
  228.     AROS_LIBFUNC_INIT
  229.     extern struct DosLibrary *DOSBase;
  230.     BPTR seglist;
  231.     Forbid();
  232.     seglist=AROS_LVO_CALL0(BPTR,
  233.     struct Library *,library,3,
  234.     );
  235.     if(seglist)
  236.     {
  237.     DOSBase->dl_LDReturn=MEM_TRY_AGAIN;
  238.     UnLoadSeg(seglist);
  239.     }
  240.     Permit();
  241.     AROS_LIBFUNC_EXIT
  242. }
  243.  
  244. LONG LDFlush(void)
  245. {
  246.     extern struct DosLibrary *DOSBase;
  247.     struct Library *library;
  248.  
  249.     DOSBase->dl_LDReturn=MEM_DID_NOTHING;
  250.  
  251.     /* Forbid() is already done, but I don't want to rely on it. */
  252.     Forbid();
  253.  
  254.     /* Follow the linked list of shared libraries. */
  255.     library=(struct Library *)SysBase->LibList.lh_Head;
  256.     while(library->lib_Node.ln_Succ!=NULL)
  257.     {
  258.     /* Flush libraries with a 0 open count */
  259.     if(!library->lib_OpenCnt)
  260.     {
  261.         RemLibrary(library);
  262.         /* Did it really go away? */
  263.         if(DOSBase->dl_LDReturn!=MEM_DID_NOTHING)
  264.         {
  265.         /* Yes. Return it. */
  266.         Permit();
  267.         return DOSBase->dl_LDReturn;
  268.         }
  269.     }
  270.     /* Go to next. */
  271.     library=(struct Library *)library->lib_Node.ln_Succ;
  272.     }
  273.     /* Do the same with the device list. */
  274.     library=(struct Library *)SysBase->DeviceList.lh_Head;
  275.     while(library->lib_Node.ln_Succ!=NULL)
  276.     {
  277.     if(!library->lib_OpenCnt)
  278.     {
  279.         RemLibrary(library);
  280.         if(DOSBase->dl_LDReturn!=MEM_DID_NOTHING)
  281.         {
  282.         Permit();
  283.         return DOSBase->dl_LDReturn;
  284.         }
  285.     }
  286.     library=(struct Library *)library->lib_Node.ln_Succ;
  287.     }
  288.     Permit();
  289.     return MEM_DID_NOTHING;
  290. }
  291.