lm_client.h in the /lmgr/machind directory for the CONFIG struct definition.
Checks the / and the /etc directories for any files which have dates in the future. On Windows and Windows NT systems, “\” and the Windows home directory are scanned. If no files have dates in the future, returns 0, otherwise returns 1. lc_baddate() allows a “grace period” of 24 hours, i.e. it will not report on files which are only 24 hours in the future.
lc_baddate() can be used in your client code, or in a daemon initialization routine to deny access on systems with dates that are set back.
![]() | Note: This function is available on UNIX and Windows/NT systems only. |
(int) status - 0 | OK, all files have dates in the past. | |
<> 0 | Error - some files have dates in the future. |
Checks in the licenses of the specified feature. For TCP clients, the daemon will detect the fact that the client exited, and return any licenses that were checked out back to the available pool. For TCP, this call is used if the application has need of a feature for a period of time, then no longer needs it. For UDP, this call is essential to free a license, otherwise, the server has to timeout the license. The second parameter is used for TCP clients to tell FLEXlm to keep the connection open to the server for cases where another feature will be needed shortly after this one is released. If the communications protocol is TCP, there is no appreciable time delay incurred in returning the license if the program exits rather than returning the license via lc_checkin. However if UDP is used, the licenses will not be returned to the pool for LM_A_UDP_TIMEOUT seconds.
status = lc_checkin(job, feature,keep_conn)(LM_HANDLE *) job |
| |
(char *) feature | The feature name to be checked in. | |
(int) keep_conn | If non-zero, means “Keep connection to server”; if 0, drops TCP connection. Unused for UDP. |
LM_CODE(key, ...) status = lc_checkout(job, feature, version, num_licenses, flag, key, dup_group) |
Checks out one (or more) license(s) of the specified feature and, for counted licenses, keeps the daemon up-to-date on the status of the process using the license(s). If the process that calls lc_checkout (via TCP) exits in any manner, then the checked out license will be returned for re-use by another user. [1] Place the call to lc_checkout in a part of your code that is active whenever the user is using the feature. If flag is specified as LM_CO_WAIT, then the process will wait until the number of licenses requested for this feature are available. The license file must specify a version that is greater than or equal to the version in the lc_checkout call.
If the license file is counted, that is, if the number of users specified on the FEATURE line is more than 0, lc_checkout will request the license from a license server. If the number of users on the FEATURE line is 0, it will grant permission based on the contents of the license file only—hostid, version, expiration date, etc.
(LM_HANDLE *) job |
| |
(char *) feature | The ASCII feature name desired. | |
(char *) version | The version of the feature desired in floating point format, 3 decimal places max, e.g.: “12345.123”. This value must be <= the version number in the license file for the checkout to succeed. |
![]() | Note: letters are not allowed in versions; “v1.0” is illegal. |
![]() | Note: Before FLEXlm v4.0, the version argument for lc_checkout() is of type double. |
(int) num_licenses |
| |
(int) flag | The checkout option flag. |
Possible values for flag are:
Requests for licenses from “duplicates” can either be “grouped”, or not “grouped”. Grouping duplicates allows license requests from separate processes to use a single license if the process's USER, HOST, DISPLAY, and/or VENDOR_DEFINED field are the same. The dup_group parameter allows you to select what to compare to constitute a group from the set {USER HOST DISPLAY VENDOR}. Any of the four fields that are not set to compare will automatically “match”; thus not setting any of the four fields yields a site license, since all users on all hosts on all displays are the same as far as the comparison is concerned. The following illustrates the use of the duplicate grouping capability:
dup_group value Meaning
The first client that checks out the feature specifies the duplicate grouping for the feature. (The duplicate grouping value is reset whenever all licenses are checked back in.) Any subsequent client that attempts to check out the feature with a different duplicate grouping mask will be rejected and an error reflecting this will appear in the lmgrd Debug log file.
Computes the license key for a FLEXlm feature line. lc_crypt() is one of the FLEXlm standard encryption routines, along with lc_crypstr(). It takes its input parameters and creates the license key that appears in the license file. Vendors generally will not call lc_crypt() directly, unless they are writing a custom license generation program, in which case create_lic.c should be used as a guide.
The CONFIG * parameter should be a pointer to a struct that has been correctly filled in. To do so, first make sure it is set to zeroes with memset(&conf, 0, sizeof(conf)). Then fill in each item in the struct, using the definition as it appears in lm_client.h, and noting that many items are now optional, and do not need setting.
The sdate parameter can be obtained by calling l_bin_date() with the date string, e.g.
l_bin_date("1-jan-93"); |
To obtain the start date from a license file license key (The 20-character code on the FEATURE line), use l_extract_date():
char code[21]; l_extract_date(code); |
The last, VENDORCODE * argument must be set up as in the following example:
![]() | Note: This use of VENDOR_KEY5 is new to FLEXlm v4.0, and is a security precaution taken mostly for dynamic linking environments, which allow access to arguments of FLEXlm functions. |
Generates license file as a string with license keys filled in. This new function is used by the lmcrypter command, and for some vendors will be an easier interface than lc_crypt() for generating licenses. You pass a string, which is a whole, valid license file, with one exception: each 20-character code must be replaced with a single `0' (zero).
If flag has LM_CRYPT_ONLY set, then the function returns the 20-character code for the first FEATURE, INCREMENT, PACKAGE, or UPGRADE line in the file. If !(flag & LM_CRYPT_ONLY), then the whole file is returned as a string, with valid 20-character codes. If flag has LM_CRYPT_FORCE set, then every line will have the 20-character code re-computed, even if the code is not set to `0' If LM_CRYPT_FORCE is set, and if a line already has a 20-character code, the start-date will be taken from the current code.
Comment lines are retained in the return_str output.
return_str and errors are malloc'd by lc_cryptstr(), and not reused by FLEXlm, so it is the responsibility of the programmer to free the space returned if needed.
If you want to specify a start-date, then, in place of a `0' in the 20-character code, use the following syntax:
start:dd-mmm-yyy. |
Since different errors can occur on every line of the input str, lc_cryptstr must be able to report all these errors independently, and does so via the errors parameter. Most reported errors will result in no generated license key, but some act as warnings, and license keys are still generated. Here is an example of error reporting:
Input: |
|
Error reported:
stdin:line 1:Bad version number - must be floating point number, with no letters |
With this error, no 20-character license key is generated and return_str will be the same as the input str.
![]() | Note: Before calling lc_cryptstr(), add the following code: |
LM_CODE(code, ENCRYPTION_CODE_1, ENCRYPTION_CODE_2, VENDOR_KEY1, VENDOR_KEY2, VENDOR_KEY3, VENDOR_KEY4, VENDOR_KEY5); VENDORCODE vc; [...] (void) memcpy((char *)&vc, (char *)&code, sizeof(vc)); vc.data[0] ^= VENDOR_KEY5; vc.data[1] ^= VENDOR_KEY5; lc_cryptstr(job, ., &vc, ..); /* for example */ |
Drops the connection to the server. A count of “logical” connections is maintained, and if other features are active, the connection is maintained, unless flag is non-zero.
(LM_HANDLE *) job | From lc_init() | |
(int) flag | 0 - Return system's idea of value. |
Returns the FLEXlm error string for the most recent FLEXlm error, along with the major and minor error number. If a UNIX error is involved, the UNIX error description will also be included in the message, along with the UNIX errno.
No such feature exists (-5,116) Cannot find license file, (-1,73:2), No such file or directory |
(LM_HANDLE *) job |
| |
(int) floating | If non-zero, list only floating features. | |
(void) (*dupaction)() |
|
(char **) list | List of features. list is a pointer to a NULL-terminated array of feature string pointers. Both the pointers and the string data are malloc'd; this memory is freed upon a subsequent call to lc_feat_list(). Do not free this data. If NULL, an error has occurred. |
The dupaction() callback routine is called with two parameters:
(*dupaction)(feature, daemon) |
where: | is the: | |
(char *) feature | feature name | |
(char *) daemon |
|
Computes the FEATURESET code for the specified daemon, if codes is NULL. If codes is a pointer to a char *, the pointer is set to an array of 20-character license keys for each FEATURE line for this daemon.
(LM_HANDLE *) job |
| |
(char *) daemon |
| |
(VENDORCODE *) code | ||
(char **) codes | Concatenated license keys (returned). If a pointer to a char * is passed, this gets set to a string which is a concatenation of the 20-character license keys for each FEATURE line for this vendor daemon—to be used for calculating a checksum using your own checksum algorithm. |
LM_HANDLE *job job = lc_first_job(job); while (job) { /*processing*/ job = lc_next_job(job); } |
lc_first_job() and lc_next_job() are used to walk the list of jobs. This only works properly if all calls to lc_init() have a pointer to the current job as the first parameter.
Flushes the in-memory license file data. lc_flush_config() could be used in an application that wished to change the license file location (see lc_set_attr()) while running. A license creation program that creates several license files while running is an example of such a program.
![]() | Note: Do not use lc_flush_config() after a successful checkout—this can result in a core dump. Applications cannot reread the license file after a successful checkout. For this reason this function has limited utility. |
lc_free_job() frees the memory associated with a job, which has been allocated by lc_init(). This call is only needed by an application that uses a large number of jobs over its lifetime.
Retrieves a FLEXlm attribute. The key describes which attribute to retrieve, and the value is a pointer to the value for the attribute. See lm_attr.h for key constants and value types.
![]() | Note: value must be a pointer to the correct attribute type, and should be cast to a (short *). |
![]() | Note: Types of char * are handled a little differently than other types. Types of int or short are declared, and a pointer to the declared variable is passed as an argument. Types of char * are declared as char *, and the variable itself is passed. |
(short *) value | Value of the attribute (cast to appropriate type). | |
(int) status | 0 - OK, <>0, error. |
Gets the license file data for a given feature. FLEXlm allows multiple valid FEATURE and INCREMENT lines (of the same feature name) in a license file. lc_get_config() will return the first, and lc_next_config() retrieves the rest, or lc_next_config() can also find the first and remaining.
(struct config *) config |
|
The most recently set FLEXlm error is obtainable via lc_get_errno(). This can be used after any FLEXlm function.
lm_client.h in the /lmgr/machind directory
lc_get_dlist() gets a list of all vendor daemons from the current license file. The DAEMON structure returned should be freed when it is no longer required with a call to lc_free_daemon_list(daemon).
ls_master.h in the /lmgr/machind directory for description of DAEMON struct.
Returns the hostid for the local host. lc_gethostid() is simply a call to lc_getid_type(default_hostid_type);
lm_client.h in the /lmgr/machind directory for the definition of the HOSTID struct
(HOSTID *) hid |
|
lm_client.h in the /lmgr/machind directory for definition of HOSTID struct.
Returns information about the local host.
Some typical results when benchmark is set:
Sun 3/50, OS 3.5: 28 Sun Sparcstation 1+, OS 4.0.3: 101 Next OS V1: 68 |
The number in the vendor_speed field is the manufacturer's stated integer MIP performance (or 0, if no value is available).
(LM_HANDLE *) job |
| |
(int) benchmark |
|
Informs FLEXlm when the process is idle. lc_idle() enables the end-user feature inactivity TIMEOUT to allow idle licenses to be reclaimed. Use of lc_idle() is recommended for end-users to take advantage of the TIMEOUT option. lc_idle() also affects vendor daemon timeout of UDP clients.
lc_idle() can be used to bracket a portion of the application code that prompts for user input, so that when the user is not using the application, the FLEXlm daemon can detect the fact that the application is idle. lc_idle only sets a flag internally in the application. It is therefore safe to call as often as necessary.
A typical use would be:
lc_idle(1);/* Process is idle now */ ... get input from user... lc_idle(0);/* Process is no longer idle */ |
None.
#include "lm_code.h" LM_CODE(code, ENCRYPTION_CODE_1, ENCRYPTION_CODE_2, VENDOR_KEY1, VENDOR_KEY2, VENDOR_KEY3, VENDOR_KEY4, VENDOR_KEY5); LM_HANDLE *job = (LM_HANDLE *)NULL; status = lc_init(job, VENDOR_NAME, &code, &job) |
Initializes FLEXlm and creates a license “job.” Subsequent calls to lc_init() create new license jobs. Each license job is independent.
![]() | Note: lc_init() MUST be the first FLEXlm call you make in your application. Do NOT call lc_set_attr() or lc_get_attr() before calling lc_init(). |
(LM_HANDLE *) job |
| |
(char *) vendor_id |
| |
(VENDORCODE *) vendor_key |
|
pointer to (LM_HANDLE *) job |
| |
(int) status | Value of lc_get_errno() after initialization is complete, 0 if successful. |
Verifies that the specified user is a license administrator. A “license administrator” is a member of the “lmadmin” group. If there is no lmadmin group in the /etc/groups file, then anyone in group 0 is a license administrator.
Returns pathname of FLEXlm license file. This function does not support the colon-separated list in the LM_LICENSE_FILE environment variable — it only reports on the first file in the list. Use lc_get_attr(LM_A_LF_LIST,...) for full list.
(char *) path | Path of the license file that FLEXlm will use. Note—This returned string must not be modified by the caller. | |
(char *)NULL | No license file set |
lm_comm.h in the /lmgr/machind directory
lm_client.h in the /lmgr/machind directory for the definition of LM_SERVER struct.
Returns the next line in the license file matching “feature.” The search is started from “pos”.
(LM_HANDLE *) job |
| |
(char *) feature | The desired feature line. | |
(long *) pos | Position to start search. | |
(0L to start at first entry). |
(struct config *) config |
| |
(long *) pos | Updated to next license file entry. |
Prints a FLEXlm error message, in the same format as the UNIX routine perror(), e.g.:
"string": FLEXlm error-string |
If a UNIX error has also occurred, it will be included in the message.
On Windows and Windows NT systems, a message box of type MB_OK will be displayed with the FLEXlm error message. If the last error was a system error, rather than a FLEXlm error, then the error string above will be a UNIX,Windows, or Windows NT error string. The FLEXlm error messages are available by calling lc_errstring().
(LM_HANDLE *) job |
| |
(char *) string | The first part of the error message, as above. |
Removes the specified user's license for feature. This is used by the lmremove command, and has the same restrictions regarding lmadmin group. lc_remove normally is only used when the client's system has had a hard crash, and the server does not detect the client node failure. If lc_remove is called on a healthy client, the license will be re-checked out by the client with its next heartbeat.
(LM_HANDLE *) job |
| |
(char *) feature | Remove the license for this feature. | |
(char *) user | User name to remove. | |
(char *) host | User's host name to remove. | |
(char *) display | User's display name to remove. |
(int) status | 0 - OK, !=0, error status |
Error Returns
Sets a FLEXlm attribute. The key describes which attribute to set, and the value is the value for the attribute. See the header file lm_attr.h for key constants and value types.
The FLEXlm error is settable via lc_set_errno(). This should not normally be used, since the error should be set by the FLEXlm libraries.
(LM_HANDLE *) job |
| |
(int) error | See lm_client.h in the /lmgr/machind directory for a list of possible FLEXlm error codes. |
lm_client.h in the /lmgr/machind directory
(LM_HANDLE *) job |
| |
(int) prompt | <> 0 => ask if server should be shut down. | |
(int) print | <> 0 => prints which nodes are shut down. |
lc_startup() starts lmgrd from within your program. lc_startup() does not report the success of the lmgrd process. lc_startup() calls the appropriate system() call given its arguments, and is unable to detect success of the system() call, since the process is started in the background.
![]() | Note: lc_startup() is available on UNIX systems only. lc_startup() works for non-redundant servers only, and only if the application is running on the license server node. |
(LM_HANDLE *) job |
| |
(char *) lmgrd_path |
| |
(char *) logfile | The daemon log file location. (Passing a NULL string or a NULL pointer will cause the Debug log file to go to stdout, which is probably not what you want.). If the first character is `+', then the logfile will be appended, if it exists. If the logfile does not exist, it will be created. | |
(char *) license_file |
|
Returns the status of the requested feature.
This call is used primarily when QUEUEing for a license. Normally QUEUEing is done in the following manner:
rc = lc_checkout(....LM_CO_NOWAIT,...); if (rc && lc_get_errno(job) == LM_MAXUSERS) { printf("Waiting for license..."); rc = lc_checkout(....LM_CO_WAIT,...); } |
However, in this example the application must wait in the lc_checkout call. If the application needs to continue doing processing, you can use lc_status() to periodically check on the status. This might be coded in the following manner:
(int) status | Status of this feature (in this process): | |
0 | feature is checked out by this process. | |
< 0 | error |
This routine is called by vendors that cannot tolerate the use of interval timers by FLEXlm. The purpose of lc_timer is twofold:
Ensure the vendor daemon is continually running — otherwise an end-user may kill the license server when all licenses are in use, restart the server, and obtain unauthorized licenses.
Keep license server informed that the client is still using its license — otherwise the license-server may timeout the client, and drop its license.
If no FLEXlm timers are used, then lc_timer must be called periodically. To avoid FLEXlm's use of timers, call lc_set_attr(LM_A_CHECK_INTERVAL, -1), and lc_set_attr(LM_A_RETRY_INTERVAL, -1).
If the default timer is left installed, lc_timer() is called by the FLEXlm-installed timer. lc_timer() also performs all the reconnection functions, so it is important to keep calling lc_timer(), even if your reconnection handler is called.
lc_timer() must not be called more than once per minute, or it will generate unnecessary networking delays. That is, when used correctly, no delays should occur. Alternatively lc_timer() must be called often enough to avoid the application losing its license — the vendor daemon will time out clients due to either UDP timeout or the end-user TIMEOUT option. The application must ensure that LM_A_UDP_TIMEOUT and ls_minimum_user_timeout are both large enough that the application will not inadvertently lose its license. In general, it is a good idea to lc_timer() once every 5 minutes, although occasional lapses are relatively harmless.
lc_timer() sends a heartbeat to the server. It then reads the response from the previously sent heartbeat. The first heartbeat is sent when the application first connects to the server, usually in lc_checkout(). In this manner, there is normally no delay in lc_timer().
If lc_timer() is unable to read a response from the server, it attempts to reconnect to the server. If the application has set an LM_A_USER_RECONNECT function, this function will also get called. If this reconnect fails, then an internal flag is set and subsequent calls to lc_timer() will attempt reconnection. These attempts are made for LM_A_RETRY_COUNT times. If a reconnection occurs before LM_A_RETRY_COUNT attempts, the LM_A_USER_RECONNECT_DONE routine, if specified, will be called. If a reconnection fails to occur after LM_A_RETRY_COUNT attempts, the LM_A_USER_EXITCALL routine, if specified, will be called. If LM_A_USER_EXITCALL is not specified, the application will exit with the error message, “Lost license, cannot reconnect” to stderr.
If lc_timer() is not called for an extended period, then the application may lose its license. This can happen for two reasons: the application is communicating via UDP or the end-user has set a TIMEOUT for this feature in the end-user options file. In both cases, the server has a timeout associated with the license which gets invoked if lc_timer() is not called within the timeout interval. Make sure that LM_A_UDP_TIMEOUT is large enough to accommodate your usage of lc_timer(). Similarly, make sure ls_minimum_user_timeout in ls_vendor.c is large enough so that users will not timeout applications that are in use.
If the license is inadvertently released, the next lc_timer() will automatically re-checkout the license, if there's still a license available.
Provides a list of who is using the feature, including information about the user of the license. This is used by lmstat -a.
If successful, pointer to an LM_USERS structure.
If unsuccessful:
(LM_USERS *)NULL |
Reserved licenses are indicated by the lm_isres() macro (defined in lm_client.h). In this case, the “name” contains the entity that the reservation is for.
The LM_USERS structure is obtained from dynamic memory — it is freed upon a subsequent call to lc_userlist(). Do not free this memory.
![]() | Note: lc_userlist() will return no information about users of node-locked, unlimited-use licenses, or demo licenses. |
![]() | Note: This is a potentially expensive function call. With many active users, this call can generate a lot of network activity, and therefore should not be used too often. |
lm_client.h in the /lmgr/machind directory for LM_USER struct definition.
Sends a message to the vendor daemon and returns a result string. There must be a connection established to the vendor daemon before lc_vsend() will work. You can establish a connection with either lc_checkout() or lc_userlist().
You must set up a processing routine in your vendor daemon to receive the message from lc_vsend() and send the reply. This routine is specified in ls_vendor.c in the variable ls_vendor_msg.
(LM_HANDLE *) job |
| |
(char *) send_str |
|
(char *) rcv_str | String returned by ls_vendor_msg() in your vendor daemon. | |
(char *)NULL | if unsuccessful |
LM_CODE(code, ENCRYPTION_CODE_1, ENCRYPTION_CODE_2, VENDOR_KEY1, VENDOR_KEY2, VENDOR_KEY3, VENDOR_KEY4, VENDOR_KEY5); |
LM_CODE is a macro defined in lm_client.h which is used to declare the variable code which is the argument necessary for many other FLEXlm calls. This must be included at the head of any source files which make FLEXlm calls requiring the code argument.
![]() | Note: VENDOR_KEY5 is used when calling lc_crypt() or lc_cryptstr(). The data[0] and data[1] elements of the code variable created by LM_CODE must be XOR'd with VENDOR_KEY5 before calling these two functions. |
[1] For TCP clients, the resulting checkin is immediate, but for UDP clients, if the client dies or exits and is not able to call lc_checkin, the license server has to timeout the client, and this takes LM_A_UDP_TIMEOUT seconds.