1/* BEGIN LICENSE BLOCK 2 * Version: CMPL 1.1 3 * 4 * The contents of this file are subject to the Cisco-style Mozilla Public 5 * License Version 1.1 (the "License"); you may not use this file except 6 * in compliance with the License. You may obtain a copy of the License 7 * at www.eclipse-clp.org/license. 8 * 9 * Software distributed under the License is distributed on an "AS IS" 10 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 11 * the License for the specific language governing rights and limitations 12 * under the License. 13 * 14 * The Original Code is The ECLiPSe Constraint Logic Programming System. 15 * The Initial Developer of the Original Code is Cisco Systems, Inc. 16 * Portions created by the Initial Developer are 17 * Copyright (C) 2001 - 2006 Cisco Systems, Inc. All Rights Reserved. 18 * 19 * Contributor(s): ___________________________________. 20 * 21 * END LICENSE BLOCK 22 * 23 * ECLiPSe LIBRARY MODULE 24 * 25 * $Id: bip_pt.c,v 1.1 2006/09/23 01:53:18 snovello Exp $ 26 * 27 * 28 * IDENTIFICATION: bip_pt.c 29 * 30 * AUTHOR: Joachim Schimpf, IC-Parc 31 * 32 * CONTENTS: 33 * 34 * licence_checkout(+Feature, +Policy, +Version, +Path, -Message, -Status) 35 * licence_heartbeat(+Feature, +Minutes, -Reconnects, -FailedReconnects) 36 * licence_checkin(+Feature) 37 * licence_held(+Feature) 38 * 39 * DESCRIPTION: 40 * 41 * Interface to FLEXlm licence manager software 42 * 43 */ 44 45 46#define EC_EXTERNAL 47 48#ifdef _WIN32 49#include <windows.h> 50#define Winapi WINAPI 51#else 52#define Winapi 53#endif 54 55#ifdef _WIN32 56# include <stdlib.h> 57# define MAX_PATH_LEN _MAX_PATH 58#else 59#ifdef PATH_IN_LIMITS 60# include <limits.h> 61# define MAX_PATH_LEN PATH_MAX 62#else 63# include <sys/param.h> 64# define MAX_PATH_LEN MAXPATHLEN 65#endif 66#endif 67 68 69#include "external.h" 70 71int DLLEXP pteclipse_init(int flags); 72 73#ifdef HAVE_FLEXLM 74 75#undef PERROR /* lmpolicy.h contains a redefinition of this name */ 76 77#include "lmpolicy.h" 78 79 80/* The handle for the checked out 'eclipse' feature */ 81 82static LP_HANDLE *eclipse_lp_handle = 0; 83 84 85/* A list of all features checked out with licence_checkout/6 */ 86 87struct checked_out_feature { 88 dident feature; 89 dident version; 90 int policy; 91 LP_HANDLE *lp_handle; 92 struct checked_out_feature *next; 93}; 94 95static struct checked_out_feature * 96 checked_out_features = 0; 97 98 99#define MAX_FLEXLM_POLICIES 7 100 101static dident lm_policy_name[MAX_FLEXLM_POLICIES]; 102static int lm_policy_flag[MAX_FLEXLM_POLICIES]; 103 104static dident d_ok, d_warning; 105 106 107#define Get_Name_Did(v, t, d) \ 108 if (IsRef(t)) { Bip_Error(INSTANTIATION_FAULT); } \ 109 else if (IsAtom(t)) { d = (v).did; } \ 110 else if (IsString(t)) { d = ec_did(StringStart(v),0); } \ 111 else { Bip_Error(TYPE_ERROR); } 112 113 114 115static int 116p_licence_checkout(value vfeature, type tfeature, value vpol, type tpol, value vversion, type tversion, value vlicloc, type tlicloc, value vmsg, type tmsg, value vstat, type tstat) 117{ 118 LP_HANDLE *lp_handle; 119 char lic_path[MAX_PATH_LEN]; 120 char *licloc; 121 dident feature, version; 122 struct checked_out_feature *cof; 123 int policy = LM_MANUAL_HEARTBEAT; 124 Prepare_Requests; 125 126 Get_Name_Did(vfeature, tfeature, feature); 127 Get_Name_Did(vversion, tversion, version); 128 Get_Name(vlicloc, tlicloc, licloc); 129 Check_List(tpol); 130 Check_Ref(tmsg); 131 Check_Ref(tstat); 132 133#ifdef REQUIRE_LICENCE 134 /* do a heartbeat for the 'eclipse' feature */ 135 if (!eclipse_lp_handle || lp_heartbeat(eclipse_lp_handle, 0, 0)) 136 { 137 pword pw; 138 Make_String(&pw, "ECLiPSe licence check failed\n"); 139 Request_Unify_Pw(vmsg, tmsg, pw.val, pw.tag); 140 Request_Unify_Atom(vstat, tstat, d_.err); 141 Return_Unify; 142 } 143#endif 144 145 /* decode the policy option list */ 146 if (IsList(tpol)) 147 { 148 pword *car; 149 for(car=vpol.ptr;;) 150 { 151 int i; 152 pword *cdr = car+1; 153 Dereference_(car); 154 Check_Atom(car->tag); 155 for(i=0; i<MAX_FLEXLM_POLICIES; ++i) 156 { 157 if (lm_policy_name[i] == car->val.did) 158 policy |= lm_policy_flag[i]; 159 } 160 Dereference_(cdr); 161 if (IsList(cdr->tag)) 162 car = cdr->val.ptr; 163 else if IsNil(cdr->tag) 164 break; 165 else 166 { Bip_Error(TYPE_ERROR); } 167 } 168 } 169 else 170 { 171 policy |= LM_RESTRICTIVE; 172 } 173 174 /* We allow checking out multiple licences for the same feature, but only 175 * if they have the same version and policy. Because all checked out 176 * licences for one feature are then equivalent, we can use the feature 177 * name instead of a licence handle to identify it. When checking in, 178 * we just check in an arbitrary one. 179 */ 180 for(cof=checked_out_features; cof; cof = cof->next) 181 { 182 if (cof->feature == feature && 183 ! (cof->version == version && cof->policy == policy)) 184 { 185 pword pw; 186 Make_String(&pw, "Implementation restriction: Multiple checkout of the same\nfeature only allowed when version and policy are the same."); 187 Request_Unify_Pw(vmsg, tmsg, pw.val, pw.tag); 188 Request_Unify_Atom(vstat, tstat, d_.err); 189 Return_Unify; 190 } 191 } 192 193 /* fill in the default licence path, if necessary */ 194 if (*licloc == '\0') 195 { 196 char lic_path_canonical[MAX_PATH_LEN]; 197 strcpy(lic_path_canonical, DidName(d_.eclipse_home)); 198 strcat(lic_path_canonical, "/licence.dat"); 199 licloc = os_filename(lic_path_canonical, lic_path); 200 } 201 202 /* check out and return the results */ 203 if (lp_checkout(LPCODE, policy, DidName(feature), DidName(version), 204 1, licloc, &lp_handle)) 205 { 206 pword pw; 207 char *message = lp_errstring(lp_handle); 208 if (!message) /* shouldn't happen */ 209 message = ""; 210 Make_String(&pw, message); 211 Request_Unify_Pw(vmsg, tmsg, pw.val, pw.tag); 212 Request_Unify_Atom(vstat, tstat, d_.err); 213 } 214 else 215 { 216 char *message = lp_warning(lp_handle); 217 218 /* store the feature name and the checked out handle */ 219 cof = (struct checked_out_feature *) 220 malloc(sizeof(struct checked_out_feature)); 221 cof->feature = feature; 222 cof->version = version; 223 cof->policy = policy; 224 cof->lp_handle = lp_handle; 225 cof->next = checked_out_features; 226 checked_out_features = cof; 227 228 if (message) 229 { 230 pword pw; 231 Make_String(&pw, message); 232 Request_Unify_Pw(vmsg, tmsg, pw.val, pw.tag); 233 Request_Unify_Atom(vstat, tstat, d_warning); 234 } 235 else 236 { 237 Request_Unify_Atom(vstat, tstat, d_ok); 238 } 239 } 240 Return_Unify; 241} 242 243 244static int 245p_licence_held(value vfeature, type tfeature) 246{ 247 dident feature; 248 struct checked_out_feature *cof; 249 Get_Name_Did(vfeature, tfeature, feature); 250 251 for(cof=checked_out_features; cof; cof = cof->next) 252 { 253 if (cof->feature == feature) 254 { Succeed_; } 255 } 256 Fail_; 257} 258 259 260static int 261p_licence_checkin(value vfeature, type tfeature) 262{ 263 dident feature; 264 struct checked_out_feature *cof, **pcof; 265 Get_Name_Did(vfeature, tfeature, feature); 266 267 pcof = &checked_out_features; 268 for(cof=checked_out_features; cof; cof = cof->next) 269 { 270 if (cof->feature == feature) 271 { 272 lp_checkin(cof->lp_handle); 273 *pcof = cof->next; 274 free(cof); 275 break; 276 } 277 pcof = &cof->next; 278 } 279 Succeed_; 280} 281 282 283static int 284p_licence_heartbeat(value vfeature, type tfeature, value vminutes, type tminutes, value vrec, type trec, value vfrec, type tfrec) 285{ 286 struct checked_out_feature *cof; 287 dident feature; 288 int rec_total = 0, frec_total = 0, found = 0; 289 Prepare_Requests; 290 291 Get_Name_Did(vfeature, tfeature, feature); 292 Check_Integer(tminutes); 293 for(cof=checked_out_features; cof; cof = cof->next) 294 { 295 if (cof->feature == feature) 296 { 297 int rec; 298 found = 1; 299 frec_total += lp_heartbeat(cof->lp_handle, &rec, (int) vminutes.nint); 300 rec_total += rec; 301 } 302 } 303 if (found) 304 { 305 Request_Unify_Integer(vrec, trec, rec_total); 306 Request_Unify_Integer(vfrec, tfrec, frec_total); 307 Return_Unify; 308 } 309 Fail_; 310} 311 312 313/*ARGSUSED*/ 314int 315pteclipse_init(int flags) 316{ 317#ifdef REQUIRE_LICENCE 318 extern char ec_version[]; 319 char lic_path[MAX_PATH_LEN]; 320 321 strcpy(lic_path, DidName(d_.eclipse_home)); 322 strcpy(lic_path+strlen(lic_path), "/licence.dat"); 323 if (lp_checkout(LPCODE, LM_RESTRICTIVE|LM_MANUAL_HEARTBEAT, 324 "eclipse", ec_version, 1, lic_path, &eclipse_lp_handle)) 325 { 326 lp_perror(eclipse_lp_handle, "ECLiPSe"); 327 eclipse_lp_handle = 0; 328 Fail_; 329 } 330#endif 331 332 (void) ec_external(ec_did("licence_checkout", 6), p_licence_checkout, d_.kernel_sepia); 333 (void) ec_external(ec_did("licence_checkin", 1), p_licence_checkin, d_.kernel_sepia); 334 (void) ec_external(ec_did("licence_heartbeat", 4), p_licence_heartbeat, d_.kernel_sepia); 335 (void) ec_external(ec_did("licence_held", 1), p_licence_held, d_.kernel_sepia); 336 lm_policy_name[0] = ec_did("restrictive",0); lm_policy_flag[0] = LM_RESTRICTIVE; 337 lm_policy_name[1] = ec_did("queue",0); lm_policy_flag[1] = LM_QUEUE; 338 lm_policy_name[2] = ec_did("failsafe",0); lm_policy_flag[2] = LM_FAILSAFE; 339 lm_policy_name[3] = ec_did("lenient",0); lm_policy_flag[3] = LM_LENIENT; 340 lm_policy_name[4] = ec_did("retry_restrictive",0); lm_policy_flag[4] = LM_RETRY_RESTRICTIVE; 341 lm_policy_name[5] = ec_did("check_baddate",0); lm_policy_flag[5] = LM_CHECK_BADDATE; 342 lm_policy_name[6] = ec_did("flexlock",0); lm_policy_flag[6] = LM_FLEXLOCK; 343 d_warning = ec_did("warning", 0); 344 d_ok = ec_did("ok", 0); 345 Succeed_; 346} 347 348#else 349 350/*ARGSUSED*/ 351int 352pteclipse_init(int flags) 353{ 354 Bip_Error(UNIMPLEMENTED); 355} 356 357#endif 358 359