File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / curl / lib / nwlib.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Jun 3 10:01:15 2020 UTC (4 years, 1 month ago) by misho
Branches: curl, MAIN
CVS tags: v7_70_0p4, HEAD
curl

    1: /***************************************************************************
    2:  *                                  _   _ ____  _
    3:  *  Project                     ___| | | |  _ \| |
    4:  *                             / __| | | | |_) | |
    5:  *                            | (__| |_| |  _ <| |___
    6:  *                             \___|\___/|_| \_\_____|
    7:  *
    8:  * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
    9:  *
   10:  * This software is licensed as described in the file COPYING, which
   11:  * you should have received as part of this distribution. The terms
   12:  * are also available at https://curl.haxx.se/docs/copyright.html.
   13:  *
   14:  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
   15:  * copies of the Software, and permit persons to whom the Software is
   16:  * furnished to do so, under the terms of the COPYING file.
   17:  *
   18:  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
   19:  * KIND, either express or implied.
   20:  *
   21:  ***************************************************************************/
   22: 
   23: #include "curl_setup.h"
   24: 
   25: #ifdef NETWARE /* Novell NetWare */
   26: 
   27: #ifdef __NOVELL_LIBC__
   28: /* For native LibC-based NLM we need to register as a real lib. */
   29: #include <library.h>
   30: #include <netware.h>
   31: #include <screen.h>
   32: #include <nks/thread.h>
   33: #include <nks/synch.h>
   34: 
   35: #include "curl_memory.h"
   36: /* The last #include file should be: */
   37: #include "memdebug.h"
   38: 
   39: typedef struct
   40: {
   41:   int     _errno;
   42:   void    *twentybytes;
   43: } libthreaddata_t;
   44: 
   45: typedef struct
   46: {
   47:   int         x;
   48:   int         y;
   49:   int         z;
   50:   void        *tenbytes;
   51:   NXKey_t     perthreadkey;   /* if -1, no key obtained... */
   52:   NXMutex_t   *lock;
   53: } libdata_t;
   54: 
   55: int         gLibId      = -1;
   56: void        *gLibHandle = (void *) NULL;
   57: rtag_t      gAllocTag   = (rtag_t) NULL;
   58: NXMutex_t   *gLibLock   = (NXMutex_t *) NULL;
   59: 
   60: /* internal library function prototypes... */
   61: int  DisposeLibraryData(void *);
   62: void DisposeThreadData(void *);
   63: int  GetOrSetUpData(int id, libdata_t **data, libthreaddata_t **threaddata);
   64: 
   65: 
   66: int _NonAppStart(void        *NLMHandle,
   67:                  void        *errorScreen,
   68:                  const char  *cmdLine,
   69:                  const char  *loadDirPath,
   70:                  size_t      uninitializedDataLength,
   71:                  void        *NLMFileHandle,
   72:                  int         (*readRoutineP)(int conn,
   73:                                              void *fileHandle, size_t offset,
   74:                                              size_t nbytes,
   75:                                              size_t *bytesRead,
   76:                                              void *buffer),
   77:                   size_t      customDataOffset,
   78:                   size_t      customDataSize,
   79:                   int         messageCount,
   80:                   const char  **messages)
   81: {
   82:   NX_LOCK_INFO_ALLOC(liblock, "Per-Application Data Lock", 0);
   83: 
   84: #ifndef __GNUC__
   85: #pragma unused(cmdLine)
   86: #pragma unused(loadDirPath)
   87: #pragma unused(uninitializedDataLength)
   88: #pragma unused(NLMFileHandle)
   89: #pragma unused(readRoutineP)
   90: #pragma unused(customDataOffset)
   91: #pragma unused(customDataSize)
   92: #pragma unused(messageCount)
   93: #pragma unused(messages)
   94: #endif
   95: 
   96:   /*
   97:    * Here we process our command line, post errors (to the error screen),
   98:    * perform initializations and anything else we need to do before being able
   99:    * to accept calls into us. If we succeed, we return non-zero and the NetWare
  100:    * Loader will leave us up, otherwise we fail to load and get dumped.
  101:    */
  102:   gAllocTag = AllocateResourceTag(NLMHandle,
  103:                                   "<library-name> memory allocations",
  104:                                   AllocSignature);
  105: 
  106:   if(!gAllocTag) {
  107:     OutputToScreen(errorScreen, "Unable to allocate resource tag for "
  108:                    "library memory allocations.\n");
  109:     return -1;
  110:   }
  111: 
  112:   gLibId = register_library(DisposeLibraryData);
  113: 
  114:   if(gLibId < -1) {
  115:     OutputToScreen(errorScreen, "Unable to register library with kernel.\n");
  116:     return -1;
  117:   }
  118: 
  119:   gLibHandle = NLMHandle;
  120: 
  121:   gLibLock = NXMutexAlloc(0, 0, &liblock);
  122: 
  123:   if(!gLibLock) {
  124:     OutputToScreen(errorScreen, "Unable to allocate library data lock.\n");
  125:     return -1;
  126:   }
  127: 
  128:   return 0;
  129: }
  130: 
  131: /*
  132:  * Here we clean up any resources we allocated. Resource tags is a big part
  133:  * of what we created, but NetWare doesn't ask us to free those.
  134:  */
  135: void _NonAppStop(void)
  136: {
  137:   (void) unregister_library(gLibId);
  138:   NXMutexFree(gLibLock);
  139: }
  140: 
  141: /*
  142:  * This function cannot be the first in the file for if the file is linked
  143:  * first, then the check-unload function's offset will be nlmname.nlm+0
  144:  * which is how to tell that there isn't one. When the check function is
  145:  * first in the linked objects, it is ambiguous. For this reason, we will
  146:  * put it inside this file after the stop function.
  147:  *
  148:  * Here we check to see if it's alright to ourselves to be unloaded. If not,
  149:  * we return a non-zero value. Right now, there isn't any reason not to allow
  150:  * it.
  151:  */
  152: int _NonAppCheckUnload(void)
  153: {
  154:     return 0;
  155: }
  156: 
  157: int GetOrSetUpData(int id, libdata_t **appData,
  158:                    libthreaddata_t **threadData)
  159: {
  160:   int                 err;
  161:   libdata_t           *app_data;
  162:   libthreaddata_t *thread_data;
  163:   NXKey_t             key;
  164:   NX_LOCK_INFO_ALLOC(liblock, "Application Data Lock", 0);
  165: 
  166:   err         = 0;
  167:   thread_data = (libthreaddata_t *) NULL;
  168: 
  169:   /*
  170:    * Attempt to get our data for the application calling us. This is where we
  171:    * store whatever application-specific information we need to carry in
  172:    * support of calling applications.
  173:    */
  174:   app_data = (libdata_t *) get_app_data(id);
  175: 
  176:   if(!app_data) {
  177:     /*
  178:      * This application hasn't called us before; set up application AND
  179:      * per-thread data. Of course, just in case a thread from this same
  180:      * application is calling us simultaneously, we better lock our application
  181:      * data-creation mutex. We also need to recheck for data after we acquire
  182:      * the lock because WE might be that other thread that was too late to
  183:      * create the data and the first thread in will have created it.
  184:      */
  185:     NXLock(gLibLock);
  186: 
  187:     app_data = (libdata_t *) get_app_data(id);
  188:     if(!app_data) {
  189:       app_data = calloc(1, sizeof(libdata_t));
  190: 
  191:       if(app_data) {
  192:         app_data->tenbytes = malloc(10);
  193:         app_data->lock     = NXMutexAlloc(0, 0, &liblock);
  194: 
  195:         if(!app_data->tenbytes || !app_data->lock) {
  196:           if(app_data->lock)
  197:             NXMutexFree(app_data->lock);
  198:           free(app_data->tenbytes);
  199:           free(app_data);
  200:           app_data = (libdata_t *) NULL;
  201:           err      = ENOMEM;
  202:         }
  203: 
  204:         if(app_data) {
  205:           /*
  206:            * Here we burn in the application data that we were trying to get
  207:            * by calling get_app_data(). Next time we call the first function,
  208:            * we'll get this data we're just now setting. We also go on here to
  209:            * establish the per-thread data for the calling thread, something
  210:            * we'll have to do on each application thread the first time
  211:            * it calls us.
  212:            */
  213:           err = set_app_data(gLibId, app_data);
  214: 
  215:           if(err) {
  216:             if(app_data->lock)
  217:               NXMutexFree(app_data->lock);
  218:             free(app_data->tenbytes);
  219:             free(app_data);
  220:             app_data = (libdata_t *) NULL;
  221:             err      = ENOMEM;
  222:           }
  223:           else {
  224:             /* create key for thread-specific data... */
  225:             err = NXKeyCreate(DisposeThreadData, (void *) NULL, &key);
  226: 
  227:             if(err)                /* (no more keys left?) */
  228:               key = -1;
  229: 
  230:             app_data->perthreadkey = key;
  231:           }
  232:         }
  233:       }
  234:     }
  235: 
  236:     NXUnlock(gLibLock);
  237:   }
  238: 
  239:   if(app_data) {
  240:     key = app_data->perthreadkey;
  241: 
  242:     if(key != -1 /* couldn't create a key? no thread data */
  243:         && !(err = NXKeyGetValue(key, (void **) &thread_data))
  244:         && !thread_data) {
  245:       /*
  246:        * Allocate the per-thread data for the calling thread. Regardless of
  247:        * whether there was already application data or not, this may be the
  248:        * first call by a new thread. The fact that we allocation 20 bytes on
  249:        * a pointer is not very important, this just helps to demonstrate that
  250:        * we can have arbitrarily complex per-thread data.
  251:        */
  252:       thread_data = malloc(sizeof(libthreaddata_t));
  253: 
  254:       if(thread_data) {
  255:         thread_data->_errno      = 0;
  256:         thread_data->twentybytes = malloc(20);
  257: 
  258:         if(!thread_data->twentybytes) {
  259:           free(thread_data);
  260:           thread_data = (libthreaddata_t *) NULL;
  261:           err         = ENOMEM;
  262:         }
  263: 
  264:         err = NXKeySetValue(key, thread_data);
  265:         if(err) {
  266:           free(thread_data->twentybytes);
  267:           free(thread_data);
  268:           thread_data = (libthreaddata_t *) NULL;
  269:         }
  270:       }
  271:     }
  272:   }
  273: 
  274:   if(appData)
  275:     *appData = app_data;
  276: 
  277:   if(threadData)
  278:     *threadData = thread_data;
  279: 
  280:   return err;
  281: }
  282: 
  283: int DisposeLibraryData(void *data)
  284: {
  285:   if(data) {
  286:     void *tenbytes = ((libdata_t *) data)->tenbytes;
  287: 
  288:     free(tenbytes);
  289:     free(data);
  290:   }
  291: 
  292:   return 0;
  293: }
  294: 
  295: void DisposeThreadData(void *data)
  296: {
  297:   if(data) {
  298:     void *twentybytes = ((libthreaddata_t *) data)->twentybytes;
  299: 
  300:     free(twentybytes);
  301:     free(data);
  302:   }
  303: }
  304: 
  305: #else /* __NOVELL_LIBC__ */
  306: /* For native CLib-based NLM seems we can do a bit more simple. */
  307: #include <nwthread.h>
  308: 
  309: int main(void)
  310: {
  311:   /* initialize any globals here... */
  312: 
  313:   /* do this if any global initializing was done
  314:   SynchronizeStart();
  315:   */
  316:   ExitThread(TSR_THREAD, 0);
  317:   return 0;
  318: }
  319: 
  320: #endif /* __NOVELL_LIBC__ */
  321: 
  322: #else /* NETWARE */
  323: 
  324: #ifdef __POCC__
  325: #  pragma warn(disable:2024)  /* Disable warning #2024: Empty input file */
  326: #endif
  327: 
  328: #endif /* NETWARE */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>