/*************************************************************************** $name: Library.c $version: 1.0 $date_modified: 102400 $description: Demonstrates use of library.h interfaces $owner: NKS Product Manager Copyright (c) 2000 Novell, Inc. All Rights Reserved. THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND TREATIES. USE AND REDISTRIBUTION OF THIS WORK IS SUBJECT TO THE LICENSE AGREEMENT ACCOMPANYING THE SOFTWARE DEVELOPMENT KIT (SDK) THAT CONTAINS THIS WORK. PURSUANT TO THE SDK LICENSE AGREEMENT, NOVELL HEREBY GRANTS TO DEVELOPER A ROYALTY-FREE, NON-EXCLUSIVE LICENSE TO INCLUDE NOVELL'S SAMPLE CODE IN ITS PRODUCT. NOVELL GRANTS DEVELOPER WORLDWIDE DISTRIBUTION RIGHTS TO MARKET, DISTRIBUTE, OR SELL NOVELL'S SAMPLE CODE AS A COMPONENT OF DEVELOPER'S PRODUCTS. NOVELL SHALL HAVE NO OBLIGATIONS TO DEVELOPER OR DEVELOPER'S CUSTOMERS WITH RESPECT TO THIS CODE. ****************************************************************************/ #include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <library.h> #include <nks/synch.h> #include <nks/thread.h> /* this NLM must be linked with the TSR flag */ #define APP_DATA_SIG 'AppD' typedef struct { unsigned long signature; // helps us recognize ourselves in the debugger void *memblock; // our memory for client applications } app_data_t; int gLibCookie; char gLibraryName[50]; NXMutex_t *gAppDataLock; NXSema_t *gLibrarySleepSemaphore; app_data_t *get_our_data( int cookie ); void cleanup_library( void ); int LibraryEntryPoint( void ); int cleanup ( app_data_t *data ) { data->signature = 'DppA'; // reverse of signature: means freed free(data->memblock); free(data); return 0; } void cleanup_library( void ) { if (unregister_library(gLibCookie)) printf("%s could not deregister itself at unload!\n", gLibraryName); NXMutexFree(gAppDataLock); } void main ( int argc, char **argv ) { NX_LOCK_INFO_ALLOC(lockInfo, "Per-application Data Lock", 0); strcpy(gLibraryName, argv[0]); gAppDataLock = NXMutexAlloc(0, NULL, &lockInfo); if (!gAppDataLock) { printf("% was unable to allocate its data instancing lock.\n", gLibraryName); exit(-1); } gLibrarySleepSemaphore = NXSemaAlloc(1, NULL); if (!gLibrarySleepSemaphore) { printf("% was unable to allocate its sleep semaphore.\n", gLibraryName); exit(-2); } // library initialization code... gLibCookie = register_library(cleanup); if (gLibCookie == -1) { char msg[80]; sprintf(msg, "%s failed to register as a library", gLibraryName); perror(msg); exit(-1); } atexit(cleanup_library); NXSemaWait(gLibrarySleepSemaphore); } app_data_t *get_our_data ( int cookie ) { size_t size; app_data_t *data; /* ** Start by getting our associated data for the caller. If not there, then this ** is a new application calling us. Allocate its per-application data and ** associate it. Failure to set it sets 'errno' to EINVAL (unknown library ** cookie), ENOCONTEXT (caller has no available VM context) or ENOMEM (library ** support cannot be allocated for the calling application). Remember, these ** calls are made not by the library implementing this code, but by the ** application calling the library. We could use get_app_type() to influence ** what sort of data we allocated and how much, but cleanup() must be able to ** dispose of each kind blindly and accurately. */ if (data = (app_data_t *) get_app_data(cookie)) return data; if (!(data = (app_data_t *) malloc(sizeof(app_data_t))) || !(data->memblock = malloc(size=rand()))) { errno = ENOMEM; return (app_data_t *) NULL; } if (set_app_data(cookie, data)) { free(data->memblock); free(data); return (app_data_t *) NULL; } data->signature = APP_DATA_SIG; memset(data->memblock, 0, size); return data; } int LibraryEntryPoint( void ) { app_data_t *data; if (!(data = get_our_data(gLibCookie))) return -1; /* ** This is a sample library entry point that implements functionality that ** applications might want. At this point, ... ** 'data' is now valid and can be used for whatever it is used for by the ** library in implementing this functionality for the calling application. */ return 0; } void DownLibrary( void ) { /* ** This is a sample entry point that, if called, would result in the library ** coming down if and only if the symbols it exports (what libraries do more ** than anything else, of course) are no longer in use. Another way to bring ** it down would be to drop it hard at the System Console by downing it ** explicitly. */ NXSemaPost(gLibrarySleepSemaphore); }