Annotation of embedaddon/curl/lib/nwlib.c, revision 1.1.1.1

1.1       misho       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>