⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tgiglob.c

📁 《Web编程专家指南》
💻 C
字号:

/*
 *  Task  Gateway  Interface
 *  A. Montefusco
 *  June 10, 1995
 *
 *
 */

#pragma option -zR_SHAREDATA
#pragma option -zS_SHAREGROUP
#pragma option -zT_SHARECLASS

#include <string.h>
#ifdef _DEBUG
#include <stdio.h>
#endif
#define  INCL_DOSSEMAPHORES
#define  INCL_DOSPROCESS
#define  INCL_DOSMEMMGR
#include <os2.h>
#include "debug.h"
#include "tgi.h"
#include "tgiglob.h"

/*
 *  Shared DLL variables
 *  
 *  Each task using the DLL shares these data
 */


int    nClient = 0;

HMTX   hGlobMutex = NULLHANDLE;

extern HMTX  hLocMutex;

int            nMod = 0;
TGI_MODULE     modTab  [MAX_MOD]  = { "", 0, 0   };

int            nInst = 0;
PROC_INSTANCE  instTab [MAX_INST] = { 0, 0, 0, 0 };

static VOID APIENTRY  _UnloadModule (void);
static void          *_AllocTgiData (TGI_DATA *pData);


long   _TgiRunning (void)
{
   if (hGlobMutex == NULLHANDLE) {
      return TGI_NOT_RUN;
   } else {
      return TGI_OK;
   } /* endif */
}


long   _LockData (void)
{
   if (hGlobMutex == NULLHANDLE) 
      return TGI_NOT_RUN;
   else {
      APIRET  krc;

      if (hLocMutex == NULLHANDLE) {
         hLocMutex = hGlobMutex;

         krc = DosOpenMutexSem (NULL, &hLocMutex);
         TRACE(fprintf (stderr, "DosOpenMutexSem: %d\n", krc););

         if (krc)
            return TGI_LOC_OPEN_SEM;
      }
 
      krc = DosRequestMutexSem (hLocMutex, SEM_INDEFINITE_WAIT);
      TRACE(fprintf (stderr, "DosRequestMutexSem: %d\n", krc););

      if (krc)
         return TGI_REQUEST;
   }
   return TGI_OK;
}

long   _UnLockData (void)
{
   if (hGlobMutex == NULLHANDLE) 
      return TGI_NOT_RUN;
   else {

      if (DosReleaseMutexSem (hLocMutex)) return TGI_LOC_RELEASE_SEM;

   }
   return TGI_OK;
}


long   _InitModule (void)
{
   APIRET  krc;

   if (hGlobMutex == NULLHANDLE) {
      int  i;

      krc = DosCreateMutexSem (0, &hGlobMutex, DC_SEM_SHARED, TRUE);
      TRACE(fprintf (stderr, "DosCreateMutexSem: %d\n", krc););

      // to simulate side effect of first missing _LockData in the server task
      hLocMutex = hGlobMutex;

      krc = DosOpenMutexSem (NULL, &hLocMutex);
      TRACE(fprintf (stderr, "DosOpenMutexSem: %d\n", krc););

      if (krc)
         return TGI_LOC_OPEN_SEM;


      // init all globals data here ....
      for (i=0; i<MAX_MOD; ++i) {

         modTab [i].szName[0]     = '\0';
         modTab [i].pNextInstance = NULL;
         modTab [i].pFn           = NULL;

      } /* endfor */

      /*
       *  Deinit module automatically
       */
      DosExitList (EXLST_ADD, (PFNEXITLIST)_UnloadModule);

      return _UnLockData ();
   } else {
      return TGI_ALREADY_INIT;
   } 
}


static VOID APIENTRY _UnloadModule (void)
{
   if (hGlobMutex != NULLHANDLE) {
      int   i;

      _LockData ();

      // unlock all waiting instances 
   
      for (i=0; i<MAX_MOD; ++i) 
         if (modTab[i].szName[i] != '\0') {

            PROC_INSTANCE  *pInst = modTab [i].pNextInstance;
      
            while (pInst != NULL) {
      
               APIRET  krc;
               ULONG   ulPostCt;
               HEV     hInst = pInst->hInstAva;
      
               krc = DosOpenEventSem (NULL, &hInst);
               TRACE(fprintf (stderr, "DosOpenEventSem: %d\n", krc););
      
               krc = DosPostEventSem (hInst);
               TRACE(fprintf (stderr, "DosPostEventSem: %d\n", krc););
      
               krc = DosCloseEventSem (hInst);
               TRACE(fprintf (stderr, "DosCloseEventSem: %d\n", krc););
      
               pInst = pInst->pNext;
            } 
         }
      DosEnterCritSec ();
      DosReleaseMutexSem (hGlobMutex);
      DosCloseMutexSem (hGlobMutex);
      hGlobMutex = NULLHANDLE;
      DosExitCritSec ();

   } /* endif */
}




/*
 *  Module table management
 *
 */


TGI_MODULE  * _GetFreeMod (void)
{
   int   i;

   for (i=0; i<MAX_MOD; ++i) 
      if (modTab [i].szName[0] == '\0') {
         modTab [i].pNextInstance = NULL; 
         modTab [i].pFn           = NULL; 
         nMod++;
         return &(modTab [i]);
      }

   return NULL;
}

/*
 *   Instance list is scanned and all instaces are freed
 */

long  _DeleteMod (TGI_MODULE *pMod)
{
   int   i;

   for (i=0; i<MAX_MOD; ++i) 
      if (pMod == &(modTab [i])) {

         PROC_INSTANCE  *pInst = modTab [i].pNextInstance;
   
         while (pInst != NULL) {

            PROC_INSTANCE *pTmp = pInst->pNext;

            _DeleteInst (pInst) ;

            pInst = pTmp;
         } 

         modTab[i].szName[i] = '\0';
         modTab [i].pNextInstance = NULL; 
         modTab [i].pFn           = NULL; 
         nMod--;
         return TGI_OK;
      }

   return TGI_MOD_NOT_FOUND;
}


/*
 *  search in module table for pszName
 */

long  _SearchModule (char *pszName, TGI_MODULE **ppMod)
{
   int   i;

   for (i=0; i<MAX_MOD; ++i) 
      if (!strcmp(modTab[i].szName, pszName)) {
         if (ppMod) *ppMod = &(modTab [i]);
         return TGI_OK;
      }
   if (ppMod) *ppMod = NULL;
   return TGI_MOD_NOT_FOUND;
}


/*
 *  Instance table management
 *
 */


PROC_INSTANCE  * _GetFreeInst (void)
{
   int   i;

   for (i=0; i<MAX_INST; ++i)
      if (instTab [i].hInstAva == 0) {
         memset (&(instTab [i]), 0, sizeof(instTab [i]));
         nInst++;
         return &(instTab [i]);
      }

   return NULL;
}


long  _DeleteInst (PROC_INSTANCE *pInst)
{
   int   i;

   for (i=0; i<MAX_INST; ++i)
      if (pInst == &(instTab [i])) {
         memset (&(instTab [i]), 0, sizeof(instTab [i]));
         nInst--;
         return TGI_OK;
      }

   return TGI_INST_NOT_FOUND;
}


/*
 *   Used by server to unlock a instance
 *
 */

long    _UnlockModuleInstance (char *pszName, TGI_DATA *pData)
{
   long  rc;
   TGI_MODULE *pMod;

   _LockData ();
   TRACE(fprintf (stderr, "_UnlockModuleInstance: accessing to global data\n"););

   if ((rc = _SearchModule (pszName, &pMod)) == TGI_OK) {

      /*
       * module found 
       * search a free instance down to the list
       */

      PROC_INSTANCE  *pInst   = pMod->pNextInstance  ;
      void           *pShrMem = _AllocTgiData (pData) ;

      if (pShrMem != NULL) {

         rc = TGI_MODULE_BUSY;
   
         while (pInst != NULL) {
   
            APIRET  krc;
            ULONG   ulPostCt;
            HEV     hInst = pInst->hInstAva;
   
            krc = DosOpenEventSem (NULL, &hInst);
            TRACE(fprintf (stderr, "DosOpenEventSem: %d\n", krc););
   
            krc = DosQueryEventSem (hInst, &ulPostCt);
            TRACE(fprintf (stderr, "DosQueryEventSem: %d\n", krc););
   
            if ((krc == 0) && (ulPostCt == 0)) {
               HMBX            hMbx;
               unsigned int    msgLen;

               // create a mailbox for callback data
               sprintf (pInst->szMbxName, "%p", pInst);
               MbxCreate (pInst->szMbxName, Local, &hMbx);
   
               // initialize pointer to shared memory object
               // that contains callback data
               pInst->pTgiData = (TGI_DATA *) pShrMem;

               // create instance termination semaphore
               pInst->hInstEnded = NULLHANDLE;
               DosCreateEventSem (NULL, &(pInst->hInstEnded), 
                                  DC_SEM_SHARED, FALSE);
   
               // unlock client thread 
               _UnLockData ();
   
               krc = DosPostEventSem (hInst);
               TRACE(fprintf (stderr, "DosPostEventSem: %d\n", krc););
   
               //  extract data from the queue
               // and send them to client
               for (;;) {
                  char  buf [MAX_BIF_LEN];

                  msgLen = sizeof(buf);

                  if ( (MbxGetMsg (hMbx, buf, &msgLen) == MLBX_OK)
                        && (msgLen != 0)
                        && (pData->pSrvFn != NULL) ) {

                     pData->pSrvFn (buf, msgLen, pData->pSrvCbData);

                  } else

                     break;
               } 
               MbxClose (hMbx);

               _LockData ();

               // wait for the external routine termination
               if (!krc) 
                  DosWaitEventSem (pInst->hInstEnded, SEM_INDEFINITE_WAIT);
               
               DosCloseEventSem (pInst->hInstEnded);
   
               pInst = NULL;
               rc = TGI_OK;
   
            } else {
   
               pInst = pInst->pNext;
   
            } /* endif */
   
            krc = DosCloseEventSem (hInst);
            TRACE(fprintf (stderr, "DosCloseEventSem: %d\n", krc););
         } 

         DosFreeMem (pShrMem);

      } else {
         rc = TGI_NO_MEM;
      } /* endif */
   } 
   _UnLockData ();

   return rc;
}

/*
 *  Used by server to built a shared memory block initialized with
 *  request's data
 */

void   *_AllocTgiData (TGI_DATA *pData)
{
   int   len = sizeof (TGI_DATA)                +
               strlen (pData->pszPathInfo ) + 1 +
               strlen (pData->pszQueryInfo) + 1 +
               strlen (pData->pszFormData ) + 1 +
               strlen (pData->pszRedirFile) + 1 ;
   void *pMem;

   APIRET  krc = DosAllocSharedMem (&pMem, NULL, len, PAG_COMMIT   |
                                                      OBJ_GETTABLE |
                                                      PAG_READ     |
                                                      PAG_WRITE
                                   );
   TRACE(fprintf (stderr, "DosAllocSharedMem: %d\n", krc););

   if (!krc) {
      TGI_DATA  *pNew = (TGI_DATA *) pMem;

      pNew->pszPathInfo  = (char *)pMem + sizeof(TGI_DATA);
      pNew->pszQueryInfo = pNew->pszPathInfo + strlen (pData->pszPathInfo)  + 1;
      pNew->pszFormData  = pNew->pszQueryInfo+ strlen (pData->pszQueryInfo) + 1;
      pNew->pszRedirFile = pNew->pszFormData + strlen (pData->pszFormData)  + 1;
                                                       
      strcpy (pNew->pszPathInfo , pData->pszPathInfo );
      strcpy (pNew->pszQueryInfo, pData->pszQueryInfo);
      strcpy (pNew->pszFormData , pData->pszFormData );
      strcpy (pNew->pszRedirFile, pData->pszRedirFile);

      return pMem;

   } else {
      return NULL;
   } /* endif */
}



/*
 *  Error message table
 *
 */

typedef struct {
   long   errCode;
   char  *pszMsg;
} TGI_ERROR;

TGI_ERROR ErrTab [] = {

  { TGI_OK              , "No error              " },
  { TGI_EXIT            , "Exiting               " },
  { TGI_UNLOCK          , "Unlock client         " },
  { TGI_NOT_RUN         , "TGI not running       " },
  { TGI_LOC_OPEN_SEM    , "TGI_LOC_OPEN_SEM      " },
  { TGI_REQUEST         , "TGI_REQUEST           " },
  { TGI_ALREADY_INIT    , "TGI_ALREADY_INIT      " },
  { TGI_LOC_RELEASE_SEM , "TGI_LOC_RELEASE_SEM   " },
  { TGI_TOO_MANY_MOD    , "TGI_TOO_MANY_MOD      " },
  { TGI_BAD_PARAM       , "TGI_BAD_PARAM         " },
  { TGI_UNLOCK_OK       , "TGI_UNLOCK_OK         " },
  { TGI_MOD_NOT_FOUND   , "TGI_MOD_NOT_FOUND     " },
  { TGI_BAD_INSTANCE    , "TGI_BAD_INSTANCE      " },
  { TGI_SEM_CREATE      , "TGI_SEM_CREATE        " },
  { TGI_UNLOCK_ERROR    , "TGI_UNLOCK_ERROR      " },
  { TGI_MOD_ALREADY_REG , "Module already registe" },
  { TGI_INST_NOT_FOUND  , "TGI_INST_NOT_FOUND    " },
  { TGI_MODULE_BUSY     , "No free instance found" },
  { TGI_NOT_INIT        , "TGI not initialized   " },
  { TGI_NO_MEM          , "Insufficient memory   " },
  { TGI_MLBX_OPEN       , "Callback mailbox open " }
};


char  *TgiStrError ( long tgiErr )
{
   int   i;

   for (i=0; i<(sizeof(ErrTab)/sizeof(ErrTab[0])); ++i)
      if (ErrTab [i].errCode == tgiErr)
         return ErrTab [i].pszMsg;
      
   return "Unknow error code";
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -