home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus Special 6 / Sonderheft_6-96.iso / pd / libraries / wbstart / src / wbstart.c < prev    next >
C/C++ Source or Header  |  1996-11-03  |  9KB  |  306 lines

  1. /*
  2.  * wbstart.c  V2.2
  3.  *
  4.  * Library routines
  5.  *
  6.  * (c) 1991-1996 Stefan Becker
  7.  */
  8.  
  9. #include "wbstart.h"
  10.  
  11. /*
  12.  * Object file dummy entry point
  13.  */
  14. static ULONG Dummy(void)
  15. {
  16.  return(0);
  17. }
  18.  
  19. /* Library name, ID string and other constant strings */
  20. #define INTTOSTR(a) #a
  21. static const char LibraryName[] = WBSTART_NAME;
  22. static const char LibraryID[]   = "$VER: " WBSTART_NAME " "
  23.                                    INTTOSTR(WBSTART_VERSION) "."
  24.                                    INTTOSTR(WBSTART_REVISION)
  25.                                    " (" __COMMODORE_DATE__ ")\r\n";
  26. static const char HandlerName[] = "WBStart Handler";
  27. const char        DosName[]     = "dos.library";
  28.  
  29. /* Standard library function prototypes */
  30. __geta4 static struct Library *LibraryInit(__A0 BPTR, __A6 struct Library *);
  31. __geta4 static struct Library *LibraryOpen(__A6 struct WBStartBase *);
  32. __geta4 static BPTR            LibraryClose(__A6 struct WBStartBase *);
  33. __geta4 static BPTR            LibraryExpunge(__A6 struct WBStartBase *);
  34.         static ULONG           LibraryReserved(void);
  35.  
  36. /* Library specific function prototypes */
  37. __geta4 static LONG WBStartTagList(__A0 struct TagItem *,
  38.                                    __A6 struct WBStartBase *);
  39.  
  40. /* ROMTag structure */
  41. static const struct Resident ROMTag = { RTC_MATCHWORD, &ROMTag, &ROMTag + 1, 0,
  42.  WBSTART_VERSION, NT_LIBRARY, 0, LibraryName, LibraryID, LibraryInit
  43. };
  44.  
  45. /* Library functions table */
  46. static const APTR LibraryVectors[] = {
  47.  /* Standard functions */
  48.  (APTR) LibraryOpen,
  49.  (APTR) LibraryClose,
  50.  (APTR) LibraryExpunge,
  51.  (APTR) LibraryReserved,
  52.  
  53.  /* Library specific functions */
  54.  (APTR) LibraryReserved, /* reserved for ARexx */
  55.  (APTR) WBStartTagList,
  56.  
  57.  /* End of table */
  58.  (APTR) -1
  59. };
  60.  
  61. /* Handler process creation data */
  62. static const struct TagItem WBStartHandlerTags[] = {
  63.  NP_Entry,       (ULONG) WBStartHandler,
  64.  NP_CurrentDir,  NULL,
  65.  NP_Name,        (ULONG) HandlerName,
  66.  NP_Priority,    0,
  67.  NP_ConsoleTask, NULL,
  68.  NP_WindowPtr,   NULL,
  69.  NP_HomeDir,     NULL,
  70.  NP_Cli,         TRUE,
  71.  NP_CommandName, (ULONG) HandlerName,
  72.  TAG_DONE
  73. };
  74.  
  75. /* Global library bases */
  76. struct Library     *SysBase;
  77. struct WBStartBase *WBStartBase = NULL; /* dcc: DON'T REMOVE THE ASSIGNMENT! */
  78.  
  79. /* Initialize library */
  80. __geta4 static struct Library *LibraryInit(__A0 BPTR Segment,
  81.                                            __A6 struct Library *ExecBase)
  82. {
  83.  struct WBStartBase *wbsb = NULL;
  84.  
  85.  /* Check OS version, must be OS 3.x or better */
  86.  if (ExecBase->lib_Version >= 39) {
  87.  
  88.   /* Initialize SysBase */
  89.   SysBase = ExecBase;
  90.  
  91.   if (wbsb = (struct WBStartBase *) MakeLibrary(LibraryVectors, NULL, NULL,
  92.                                                  sizeof(struct WBStartBase),
  93.                                                  NULL)) {
  94.  
  95.    /* Initialize libray structure */
  96.    wbsb->wbsb_Library.lib_Node.ln_Type = NT_LIBRARY;
  97.    wbsb->wbsb_Library.lib_Node.ln_Name = LibraryName;
  98.    wbsb->wbsb_Library.lib_Flags        = LIBF_CHANGED | LIBF_SUMUSED;
  99.    wbsb->wbsb_Library.lib_Version      = WBSTART_VERSION;
  100.    wbsb->wbsb_Library.lib_Revision     = WBSTART_REVISION;
  101.    wbsb->wbsb_Library.lib_IdString     = (APTR) LibraryID;
  102.    wbsb->wbsb_State                    = WBSTART_HANDLER_INACTIVE;
  103.    wbsb->wbsb_Segment                  = Segment;
  104.    wbsb->wbsb_Process                  = NULL;
  105.    wbsb->wbsb_Port                     = NULL;
  106.    wbsb->wbsb_ReplyPort.mp_Flags       = PA_SIGNAL;
  107.    wbsb->wbsb_Message.mn_Length        = sizeof(struct Message);
  108.  
  109.    /* Initialize reply ports' message list */
  110.    NewList(&wbsb->wbsb_ReplyPort.mp_MsgList);
  111.  
  112.    /* Initialize Semaphore */
  113.    InitSemaphore(&wbsb->wbsb_Semaphore);
  114.  
  115.    /* Add the library to the system */
  116.    AddLibrary((struct Library *) wbsb);
  117.  
  118.    /* Set global library base pointer */
  119.    WBStartBase = wbsb;
  120.  
  121.    DEBUGLOG(kprintf("Init Lib: %08lx Seg; 0x%08lx\n", wbsb, Segment);)
  122.   }
  123.  }
  124.  
  125.  /* Return new library pointer */
  126.  return((struct Library *) wbsb);
  127. }
  128.  
  129. /* Standard library function: Open. Called in Forbid() state */
  130. __geta4 static struct Library *LibraryOpen(__A6 struct WBStartBase *wbsb)
  131. {
  132.  /* Oh another user :-) */
  133.  wbsb->wbsb_Library.lib_OpenCnt++;
  134.  
  135.  /* Reset delayed expunge flag */
  136.  wbsb->wbsb_Library.lib_Flags &= ~LIBF_DELEXP;
  137.  
  138.  DEBUGLOG(kprintf("Open Lib: %ld\n", wbsb->wbsb_Library.lib_OpenCnt);)
  139.  
  140.  /* Return library pointer */
  141.  return(&wbsb->wbsb_Library);
  142. }
  143.  
  144. /* Standard library function: Close. Called in Forbid() state */
  145. __geta4 static BPTR LibraryClose(__A6 struct WBStartBase *wbsb)
  146. {
  147.  BPTR rc = NULL;
  148.  
  149.  /* Open count greater zero, only one user and delayed expunge bit set? */
  150.  if ((wbsb->wbsb_Library.lib_OpenCnt > 0) &&
  151.      (--wbsb->wbsb_Library.lib_OpenCnt == 0) &&
  152.      (wbsb->wbsb_Library.lib_Flags & LIBF_DELEXP))
  153.  
  154.   /* Yes, try to remove the library */
  155.   rc = LibraryExpunge(wbsb);
  156.  
  157.  DEBUGLOG(kprintf("Close Lib: %ld (0x%08lx)\n", wbsb->wbsb_Library.lib_OpenCnt,
  158.                   rc);)
  159.  
  160.  /* Return library segment if expunge was successful */
  161.  return(rc);
  162. }
  163.  
  164. /* Standard library function: Expunge. Called in Forbid() state */
  165. __geta4 static BPTR LibraryExpunge(__A6 struct WBStartBase *wbsb)
  166. {
  167.  BPTR rc = NULL;
  168.  
  169.  DEBUGLOG(kprintf("Expunge Lib: %08lx Seg: 0x%08lx\n", wbsb,
  170.                   wbsb->wbsb_Segment);)
  171.  
  172.  /* Does anybody use library now? */
  173.  if (wbsb->wbsb_Library.lib_OpenCnt > 0)
  174.  
  175.   /* No, library still in use -> set delayed expunge flag */
  176.   wbsb->wbsb_Library.lib_Flags |= LIBF_DELEXP;
  177.  
  178.  /* Is handler inactive? */
  179.  else if (wbsb->wbsb_State == WBSTART_HANDLER_INACTIVE) {
  180.  
  181.   /* Yes, remove library */
  182.   Remove(&wbsb->wbsb_Library.lib_Node);
  183.  
  184.   /* Return library segment */
  185.   rc = wbsb->wbsb_Segment;
  186.  
  187.   /* Free memory for library base */
  188.   FreeMem((void *) ((ULONG) wbsb - wbsb->wbsb_Library.lib_NegSize),
  189.           wbsb->wbsb_Library.lib_NegSize + wbsb->wbsb_Library.lib_PosSize);
  190.  
  191.   DEBUGLOG(kprintf("Removing library...\n");)
  192.  
  193.  /* No, handler still active */
  194.  } else {
  195.  
  196.   DEBUGLOG(kprintf("Sending exit signal to hander.\n");)
  197.  
  198.   /* Send exit signal to handler */
  199.   Signal(&wbsb->wbsb_Process->pr_Task, SIGBREAKF_CTRL_C);
  200.  
  201.   /* Library still in use -> set delayed expunge flag */
  202.   wbsb->wbsb_Library.lib_Flags |= LIBF_DELEXP;
  203.  }
  204.  
  205.  /* Return library segment if expunge was successful */
  206.  return(rc);
  207. }
  208.  
  209. /* Reserved function, returns NULL */
  210. static ULONG LibraryReserved(void)
  211. {
  212.  return(0);
  213. }
  214.  
  215. /* Send message and wait for reply */
  216. static LONG DoMessage(struct MsgPort *p, struct Message *msg,
  217.                       struct MsgPort *rp)
  218. {
  219.  /* Initialize message */
  220.  msg->mn_ReplyPort = rp;
  221.  
  222.  /* Send message to handler */
  223.  PutMsg(p, msg);
  224.  
  225.  /* Wait for reply */
  226.  WaitPort(rp);
  227.  
  228.  /* Retrieve reply */
  229.  GetMsg(rp);
  230.  
  231.  /* Get return code */
  232.  return((LONG) msg->mn_Node.ln_Name);
  233. }
  234.  
  235. /* Library function: WBStartTagList */
  236. __geta4 static LONG WBStartTagList(__A0 struct TagItem *tags,
  237.                                    __A6 struct WBStartBase *wbsb)
  238. {
  239.  LONG rc  = RETURN_FAIL;
  240.  BYTE sig;
  241.  
  242.  /* Allocate signal for message port */
  243.  if ((sig = AllocSignal(-1)) >= 0) {
  244.  
  245.   DEBUGLOG(kprintf("Entering critical section.\n");)
  246.  
  247.   /*** ENTERING CRITICAL SECTION ***/
  248.   ObtainSemaphore(&wbsb->wbsb_Semaphore);
  249.  
  250.   /* Initialize reply port */
  251.   wbsb->wbsb_ReplyPort.mp_SigBit  = sig;
  252.   wbsb->wbsb_ReplyPort.mp_SigTask = FindTask(NULL);
  253.  
  254.   /* Is handler running? */
  255.   if (wbsb->wbsb_State == WBSTART_HANDLER_INACTIVE) {
  256.    struct Library *DOSBase;
  257.  
  258.    DEBUGLOG(kprintf("Starting handler.\n");)
  259.  
  260.    /* No, start it. First open DOS library */
  261.    if (DOSBase = OpenLibrary(DosName, 39)) {
  262.  
  263.     /* Create new process */
  264.     if (wbsb->wbsb_Process = CreateNewProc(WBStartHandlerTags)) {
  265.  
  266.      DEBUGLOG(kprintf("WBStartTagList: Process created.\n");)
  267.  
  268.      /* Send startup message */
  269.      if (DoMessage(&wbsb->wbsb_Process->pr_MsgPort, &wbsb->wbsb_Message,
  270.                    &wbsb->wbsb_ReplyPort)
  271.           == RETURN_OK) {
  272.  
  273.       DEBUGLOG(kprintf("WBStartTagList: Handler started.\n");)
  274.  
  275.       /* Handler is starting now */
  276.       wbsb->wbsb_State = WBSTART_HANDLER_RUNNING;
  277.      }
  278.     }
  279.  
  280.     /* Close DOS library */
  281.     CloseLibrary(DOSBase);
  282.    }
  283.   }
  284.  
  285.   /* Check that handler is really running */
  286.   if (wbsb->wbsb_Port) {
  287.  
  288.    /* Initialize message */
  289.    wbsb->wbsb_Message.mn_Node.ln_Name = (char *) tags;
  290.  
  291.    /* Send message to handler */
  292.    rc = DoMessage(wbsb->wbsb_Port, &wbsb->wbsb_Message, &wbsb->wbsb_ReplyPort);
  293.   }
  294.  
  295.   ReleaseSemaphore(&wbsb->wbsb_Semaphore);
  296.   /*** LEFT CRITICAL SECTION ***/
  297.  
  298.   DEBUGLOG(kprintf("Left critical section.\n");)
  299.  
  300.   /* Free signal */
  301.   FreeSignal(sig);
  302.  }
  303.  
  304.  return(rc);
  305. }
  306.