Annotation of embedaddon/curl/lib/nwlib.c, revision 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>