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>