nwlib.c
Go to the documentation of this file.
1 /***************************************************************************
2  * _ _ ____ _
3  * Project ___| | | | _ \| |
4  * / __| | | | |_) | |
5  * | (__| |_| | _ <| |___
6  * \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2016, 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 = malloc(sizeof(libdata_t));
190 
191  if(app_data) {
192  memset(app_data, 0, sizeof(libdata_t));
193 
194  app_data->tenbytes = malloc(10);
195  app_data->lock = NXMutexAlloc(0, 0, &liblock);
196 
197  if(!app_data->tenbytes || !app_data->lock) {
198  if(app_data->lock)
199  NXMutexFree(app_data->lock);
200 
201  free(app_data);
202  app_data = (libdata_t *) NULL;
203  err = ENOMEM;
204  }
205 
206  if(app_data) {
207  /*
208  * Here we burn in the application data that we were trying to get
209  * by calling get_app_data(). Next time we call the first function,
210  * we'll get this data we're just now setting. We also go on here to
211  * establish the per-thread data for the calling thread, something
212  * we'll have to do on each application thread the first time
213  * it calls us.
214  */
215  err = set_app_data(gLibId, app_data);
216 
217  if(err) {
218  free(app_data);
219  app_data = (libdata_t *) NULL;
220  err = ENOMEM;
221  }
222  else {
223  /* create key for thread-specific data... */
224  err = NXKeyCreate(DisposeThreadData, (void *) NULL, &key);
225 
226  if(err) /* (no more keys left?) */
227  key = -1;
228 
229  app_data->perthreadkey = key;
230  }
231  }
232  }
233  }
234 
235  NXUnlock(gLibLock);
236  }
237 
238  if(app_data) {
239  key = app_data->perthreadkey;
240 
241  if(key != -1 /* couldn't create a key? no thread data */
242  && !(err = NXKeyGetValue(key, (void **) &thread_data))
243  && !thread_data) {
244  /*
245  * Allocate the per-thread data for the calling thread. Regardless of
246  * whether there was already application data or not, this may be the
247  * first call by a new thread. The fact that we allocation 20 bytes on
248  * a pointer is not very important, this just helps to demonstrate that
249  * we can have arbitrarily complex per-thread data.
250  */
251  thread_data = malloc(sizeof(libthreaddata_t));
252 
253  if(thread_data) {
254  thread_data->_errno = 0;
255  thread_data->twentybytes = malloc(20);
256 
257  if(!thread_data->twentybytes) {
258  free(thread_data);
259  thread_data = (libthreaddata_t *) NULL;
260  err = ENOMEM;
261  }
262 
263  err = NXKeySetValue(key, thread_data);
264  if(err) {
265  free(thread_data->twentybytes);
266  free(thread_data);
267  thread_data = (libthreaddata_t *) NULL;
268  }
269  }
270  }
271  }
272 
273  if(appData)
274  *appData = app_data;
275 
276  if(threadData)
277  *threadData = thread_data;
278 
279  return err;
280 }
281 
282 int DisposeLibraryData(void *data)
283 {
284  if(data) {
285  void *tenbytes = ((libdata_t *) data)->tenbytes;
286 
287  free(tenbytes);
288  free(data);
289  }
290 
291  return 0;
292 }
293 
294 void DisposeThreadData(void *data)
295 {
296  if(data) {
297  void *twentybytes = ((libthreaddata_t *) data)->twentybytes;
298 
299  free(twentybytes);
300  free(data);
301  }
302 }
303 
304 #else /* __NOVELL_LIBC__ */
305 /* For native CLib-based NLM seems we can do a bit more simple. */
306 #include <nwthread.h>
307 
308 int main(void)
309 {
310  /* initialize any globals here... */
311 
312  /* do this if any global initializing was done
313  SynchronizeStart();
314  */
315  ExitThread(TSR_THREAD, 0);
316  return 0;
317 }
318 
319 #endif /* __NOVELL_LIBC__ */
320 
321 #else /* NETWARE */
322 
323 #ifdef __POCC__
324 # pragma warn(disable:2024) /* Disable warning #2024: Empty input file */
325 #endif
326 
327 #endif /* NETWARE */
#define free(ptr)
Definition: curl_memory.h:130
int main(void)
Definition: 10-at-a-time.c:112
pthread_mutex_t lock
#define malloc(size)
Definition: curl_memory.h:124
TFSIMD_FORCE_INLINE const tfScalar & y() const
char buffer[]
Definition: unit1308.c:48
TFSIMD_FORCE_INLINE const tfScalar & x() const
TFSIMD_FORCE_INLINE const tfScalar & z() const
#define ENOMEM
int key
Definition: unit1602.c:56
Definition: debug.c:29


rc_tagdetect_client
Author(s): Monika Florek-Jasinska , Raphael Schaller
autogenerated on Sat Feb 13 2021 03:42:16