PageRenderTime 28ms CodeModel.GetById 29ms RepoModel.GetById 1ms app.codeStats 0ms

/nw/nwlib.c

https://gitlab.com/generic-library/ssh2
C | 304 lines | 187 code | 56 blank | 61 comment | 27 complexity | b46e18506944946a058ba8a6cb42e760 MD5 | raw file
  1. /*********************************************************************
  2. * Universal NetWare library stub. *
  3. * written by Ulrich Neuman and given to OpenSource copyright-free. *
  4. * Extended for CLIB support by Guenter Knauf. *
  5. *********************************************************************/
  6. #ifdef NETWARE /* Novell NetWare */
  7. #include <stdlib.h>
  8. #ifdef __NOVELL_LIBC__
  9. /* For native LibC-based NLM we need to register as a real lib. */
  10. #include <errno.h>
  11. #include <string.h>
  12. #include <library.h>
  13. #include <netware.h>
  14. #include <screen.h>
  15. #include <nks/thread.h>
  16. #include <nks/synch.h>
  17. typedef struct
  18. {
  19. int _errno;
  20. void *twentybytes;
  21. } libthreaddata_t;
  22. typedef struct
  23. {
  24. int x;
  25. int y;
  26. int z;
  27. void *tenbytes;
  28. NXKey_t perthreadkey; /* if -1, no key obtained... */
  29. NXMutex_t *lock;
  30. } libdata_t;
  31. int gLibId = -1;
  32. void *gLibHandle = (void *) NULL;
  33. rtag_t gAllocTag = (rtag_t) NULL;
  34. NXMutex_t *gLibLock = (NXMutex_t *) NULL;
  35. /* internal library function prototypes... */
  36. int DisposeLibraryData ( void * );
  37. void DisposeThreadData ( void * );
  38. int GetOrSetUpData ( int id, libdata_t **data, libthreaddata_t **threaddata );
  39. int _NonAppStart( void *NLMHandle,
  40. void *errorScreen,
  41. const char *cmdLine,
  42. const char *loadDirPath,
  43. size_t uninitializedDataLength,
  44. void *NLMFileHandle,
  45. int (*readRoutineP)( int conn,
  46. void *fileHandle, size_t offset,
  47. size_t nbytes,
  48. size_t *bytesRead,
  49. void *buffer ),
  50. size_t customDataOffset,
  51. size_t customDataSize,
  52. int messageCount,
  53. const char **messages )
  54. {
  55. NX_LOCK_INFO_ALLOC(liblock, "Per-Application Data Lock", 0);
  56. #ifndef __GNUC__
  57. #pragma unused(cmdLine)
  58. #pragma unused(loadDirPath)
  59. #pragma unused(uninitializedDataLength)
  60. #pragma unused(NLMFileHandle)
  61. #pragma unused(readRoutineP)
  62. #pragma unused(customDataOffset)
  63. #pragma unused(customDataSize)
  64. #pragma unused(messageCount)
  65. #pragma unused(messages)
  66. #endif
  67. /*
  68. ** Here we process our command line, post errors (to the error screen),
  69. ** perform initializations and anything else we need to do before being able
  70. ** to accept calls into us. If we succeed, we return non-zero and the NetWare
  71. ** Loader will leave us up, otherwise we fail to load and get dumped.
  72. */
  73. gAllocTag = AllocateResourceTag(NLMHandle,
  74. "<library-name> memory allocations", AllocSignature);
  75. if (!gAllocTag) {
  76. OutputToScreen(errorScreen, "Unable to allocate resource tag for "
  77. "library memory allocations.\n");
  78. return -1;
  79. }
  80. gLibId = register_library(DisposeLibraryData);
  81. if (gLibId < -1) {
  82. OutputToScreen(errorScreen, "Unable to register library with kernel.\n");
  83. return -1;
  84. }
  85. gLibHandle = NLMHandle;
  86. gLibLock = NXMutexAlloc(0, 0, &liblock);
  87. if (!gLibLock) {
  88. OutputToScreen(errorScreen, "Unable to allocate library data lock.\n");
  89. return -1;
  90. }
  91. return 0;
  92. }
  93. /*
  94. ** Here we clean up any resources we allocated. Resource tags is a big part
  95. ** of what we created, but NetWare doesn't ask us to free those.
  96. */
  97. void _NonAppStop( void )
  98. {
  99. (void) unregister_library(gLibId);
  100. NXMutexFree(gLibLock);
  101. }
  102. /*
  103. ** This function cannot be the first in the file for if the file is linked
  104. ** first, then the check-unload function's offset will be nlmname.nlm+0
  105. ** which is how to tell that there isn't one. When the check function is
  106. ** first in the linked objects, it is ambiguous. For this reason, we will
  107. ** put it inside this file after the stop function.
  108. **
  109. ** Here we check to see if it's alright to ourselves to be unloaded. If not,
  110. ** we return a non-zero value. Right now, there isn't any reason not to allow
  111. ** it.
  112. */
  113. int _NonAppCheckUnload( void )
  114. {
  115. return 0;
  116. }
  117. int GetOrSetUpData(int id, libdata_t **appData, libthreaddata_t **threadData)
  118. {
  119. int err;
  120. libdata_t *app_data;
  121. libthreaddata_t *thread_data;
  122. NXKey_t key;
  123. NX_LOCK_INFO_ALLOC(liblock, "Application Data Lock", 0);
  124. err = 0;
  125. thread_data = (libthreaddata_t *) NULL;
  126. /*
  127. ** Attempt to get our data for the application calling us. This is where we
  128. ** store whatever application-specific information we need to carry in support
  129. ** of calling applications.
  130. */
  131. app_data = (libdata_t *) get_app_data(id);
  132. if (!app_data) {
  133. /*
  134. ** This application hasn't called us before; set up application AND per-thread
  135. ** data. Of course, just in case a thread from this same application is calling
  136. ** us simultaneously, we better lock our application data-creation mutex. We
  137. ** also need to recheck for data after we acquire the lock because WE might be
  138. ** that other thread that was too late to create the data and the first thread
  139. ** in will have created it.
  140. */
  141. NXLock(gLibLock);
  142. if (!(app_data = (libdata_t *) get_app_data(id))) {
  143. app_data = (libdata_t *) malloc(sizeof(libdata_t));
  144. if (app_data) {
  145. memset(app_data, 0, sizeof(libdata_t));
  146. app_data->tenbytes = malloc(10);
  147. app_data->lock = NXMutexAlloc(0, 0, &liblock);
  148. if (!app_data->tenbytes || !app_data->lock) {
  149. if (app_data->lock)
  150. NXMutexFree(app_data->lock);
  151. free(app_data);
  152. app_data = (libdata_t *) NULL;
  153. err = ENOMEM;
  154. }
  155. if (app_data) {
  156. /*
  157. ** Here we burn in the application data that we were trying to get by calling
  158. ** get_app_data(). Next time we call the first function, we'll get this data
  159. ** we're just now setting. We also go on here to establish the per-thread data
  160. ** for the calling thread, something we'll have to do on each application
  161. ** thread the first time it calls us.
  162. */
  163. err = set_app_data(gLibId, app_data);
  164. if (err) {
  165. free(app_data);
  166. app_data = (libdata_t *) NULL;
  167. err = ENOMEM;
  168. }
  169. else {
  170. /* create key for thread-specific data... */
  171. err = NXKeyCreate(DisposeThreadData, (void *) NULL, &key);
  172. if (err) /* (no more keys left?) */
  173. key = -1;
  174. app_data->perthreadkey = key;
  175. }
  176. }
  177. }
  178. }
  179. NXUnlock(gLibLock);
  180. }
  181. if (app_data) {
  182. key = app_data->perthreadkey;
  183. if (key != -1 /* couldn't create a key? no thread data */
  184. && !(err = NXKeyGetValue(key, (void **) &thread_data))
  185. && !thread_data) {
  186. /*
  187. ** Allocate the per-thread data for the calling thread. Regardless of whether
  188. ** there was already application data or not, this may be the first call by a
  189. ** a new thread. The fact that we allocation 20 bytes on a pointer is not very
  190. ** important, this just helps to demonstrate that we can have arbitrarily
  191. ** complex per-thread data.
  192. */
  193. thread_data = (libthreaddata_t *) malloc(sizeof(libthreaddata_t));
  194. if (thread_data) {
  195. thread_data->_errno = 0;
  196. thread_data->twentybytes = malloc(20);
  197. if (!thread_data->twentybytes) {
  198. free(thread_data);
  199. thread_data = (libthreaddata_t *) NULL;
  200. err = ENOMEM;
  201. }
  202. if ((err = NXKeySetValue(key, thread_data))) {
  203. free(thread_data->twentybytes);
  204. free(thread_data);
  205. thread_data = (libthreaddata_t *) NULL;
  206. }
  207. }
  208. }
  209. }
  210. if (appData)
  211. *appData = app_data;
  212. if (threadData)
  213. *threadData = thread_data;
  214. return err;
  215. }
  216. int DisposeLibraryData( void *data )
  217. {
  218. if (data) {
  219. void *tenbytes = ((libdata_t *) data)->tenbytes;
  220. if (tenbytes)
  221. free(tenbytes);
  222. free(data);
  223. }
  224. return 0;
  225. }
  226. void DisposeThreadData( void *data )
  227. {
  228. if (data) {
  229. void *twentybytes = ((libthreaddata_t *) data)->twentybytes;
  230. if (twentybytes)
  231. free(twentybytes);
  232. free(data);
  233. }
  234. }
  235. #else /* __NOVELL_LIBC__ */
  236. /* For native CLib-based NLM seems we can do a bit more simple. */
  237. #include <nwthread.h>
  238. int main ( void )
  239. {
  240. /* initialize any globals here... */
  241. /* do this if any global initializing was done
  242. SynchronizeStart();
  243. */
  244. ExitThread (TSR_THREAD, 0);
  245. return 0;
  246. }
  247. #endif /* __NOVELL_LIBC__ */
  248. #endif /* NETWARE */