PageRenderTime 27ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/tags/2.3.0/extras/vms.c

#
C | 422 lines | 292 code | 72 blank | 58 comment | 40 complexity | 2b5efb06671d61f783e03d550f6400e0 MD5 | raw file
Possible License(s): LGPL-2.1, AGPL-1.0
  1. #include <config.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <descrip.h>
  6. #include <starlet.h>
  7. #include <ssdef.h>
  8. #include <stsdef.h>
  9. #include <lnmdef.h>
  10. #include <libdef.h>
  11. #include <libfisdef.h>
  12. #include <lib$routines>
  13. #include <psldef.h>
  14. #include <rmsdef.h>
  15. #include <fabdef.h>
  16. #include <namdef.h>
  17. #include <unixlib.h>
  18. static int error_status = SS$_NORMAL;
  19. static char error_buffer[256];
  20. static char getenv_buffer[256];
  21. typedef struct
  22. {
  23. struct dsc$descriptor_s fnmdes;
  24. struct dsc$descriptor_s imgdes;
  25. struct dsc$descriptor_s symdes;
  26. char filename[NAM$C_MAXRSS];
  27. } vms_dl;
  28. int vms_dlsym (vms_dl *, void **, int);
  29. void * lt_dlsym (void *, const char *);
  30. int lt_dlinit (void)
  31. {
  32. return 0;
  33. }
  34. char translate_buffer[NAM$C_MAXRSS+1];
  35. int to_vms_callback(char *name, int type)
  36. {
  37. strcpy(translate_buffer, name);
  38. return 1;
  39. }
  40. void * lt_dlopen (const char *filename)
  41. {
  42. /*
  43. * Locates and validates a shareable image. If the caller supplies a
  44. * path as part of the image name, that's where we look. Note that this
  45. * includes cases where the image name is a logical name pointing to a full
  46. * file spec including path. If there is no path, we look at wherever the
  47. * logical name LTDL_LIBRARY_PATH points (if it exists); it'd normally be a
  48. * search list logical defined in lt_dladdsearchdir, so it could point to a
  49. * number of places. As a last resort we look in SYS$SHARE.
  50. */
  51. vms_dl *dh;
  52. int status;
  53. struct FAB imgfab;
  54. struct NAM imgnam;
  55. char defimg[NAM$C_MAXRSS+1];
  56. char *defpath;
  57. char local_fspec[NAM$C_MAXRSS+1];
  58. if (filename == NULL)
  59. {
  60. error_status = SS$_UNSUPPORTED;
  61. return NULL;
  62. }
  63. strcpy(local_fspec, filename);
  64. /*
  65. * The driver manager will handle a hard-coded path from a .ini file, but
  66. * only if it's an absolute path in unix syntax. To make those acceptable
  67. * to lib$find_image_symbol, we have to convert to VMS syntax. N.B. Because
  68. * of the static buffer, this is not thread-safe, but copying immediately to
  69. * local storage should limit the damage.
  70. */
  71. if (filename[0] == '/') {
  72. int num_translated = decc$to_vms(local_fspec, to_vms_callback, 0, 1);
  73. if (num_translated == 1) strcpy(local_fspec, translate_buffer);
  74. }
  75. dh = (vms_dl *)malloc (sizeof (vms_dl));
  76. memset( dh, 0, sizeof(vms_dl) );
  77. if (dh == NULL)
  78. {
  79. error_status = SS$_INSFMEM;
  80. return NULL;
  81. }
  82. imgfab = cc$rms_fab;
  83. imgfab.fab$l_fna = local_fspec;
  84. imgfab.fab$b_fns = (int) strlen (local_fspec);
  85. imgfab.fab$w_ifi = 0;
  86. /* If the logical name LTDL_LIBRARY_PATH does not exist, we'll depend
  87. * on the image name being a logical name or on the image residing in
  88. * SYS$SHARE.
  89. */
  90. if ( getvmsenv("LTDL_LIBRARY_PATH") == NULL )
  91. {
  92. strcpy( defimg, ".EXE" );
  93. }
  94. else
  95. {
  96. strcpy( defimg, "LTDL_LIBRARY_PATH:.EXE" );
  97. }
  98. imgfab.fab$l_dna = defimg;
  99. imgfab.fab$b_dns = strlen(defimg);
  100. imgfab.fab$l_fop = FAB$M_NAM;
  101. imgfab.fab$l_nam = &imgnam;
  102. imgnam = cc$rms_nam;
  103. imgnam.nam$l_esa = dh->filename;
  104. imgnam.nam$b_ess = NAM$C_MAXRSS;
  105. status = sys$parse (&imgfab);
  106. if (!($VMS_STATUS_SUCCESS(status)))
  107. {
  108. /* No luck with LTDL_LIBRARY_PATH; try SYS$SHARE */
  109. strcpy( defimg, "SYS$SHARE:.EXE" );
  110. imgfab.fab$b_dns = strlen(defimg);
  111. status = sys$parse (&imgfab);
  112. if (!($VMS_STATUS_SUCCESS(status)))
  113. {
  114. error_status = status;
  115. return NULL;
  116. }
  117. }
  118. dh->fnmdes.dsc$b_dtype = DSC$K_DTYPE_T;
  119. dh->fnmdes.dsc$b_class = DSC$K_CLASS_S;
  120. dh->fnmdes.dsc$a_pointer = imgnam.nam$l_name;
  121. dh->fnmdes.dsc$w_length = imgnam.nam$b_name;
  122. dh->imgdes.dsc$b_dtype = DSC$K_DTYPE_T;
  123. dh->imgdes.dsc$b_class = DSC$K_CLASS_S;
  124. dh->imgdes.dsc$a_pointer = dh->filename;
  125. dh->imgdes.dsc$w_length = imgnam.nam$b_esl;
  126. /*
  127. ** Attempt to load a symbol at this stage to
  128. ** validate that the shared file can be loaded
  129. */
  130. lt_dlsym (dh, "Fake_Symbol_Name");
  131. if (!((error_status ^ LIB$_KEYNOTFOU) & ~7)) error_status = SS$_NORMAL;
  132. if (!($VMS_STATUS_SUCCESS(error_status)))
  133. {
  134. free (dh);
  135. return NULL;
  136. }
  137. return dh;
  138. }
  139. int lt_dlclose (void *handle)
  140. {
  141. free (handle);
  142. return 0;
  143. }
  144. void * lt_dlsym (void *handle, const char *name)
  145. {
  146. vms_dl *dh;
  147. void *ptr;
  148. int status, flags;
  149. dh = (vms_dl *)handle;
  150. if (!dh) return NULL;
  151. dh->symdes.dsc$b_dtype = DSC$K_DTYPE_T;
  152. dh->symdes.dsc$b_class = DSC$K_CLASS_S;
  153. dh->symdes.dsc$a_pointer = (char *) name;
  154. dh->symdes.dsc$w_length = strlen (name);
  155. /* firstly attempt with flags set to 0 case insensitive */
  156. flags = 0;
  157. status = vms_dlsym (dh, &ptr, flags);
  158. if (!($VMS_STATUS_SUCCESS(status)))
  159. {
  160. /*
  161. ** Try again with mixed case flag set
  162. */
  163. flags = LIB$M_FIS_MIXEDCASE;
  164. status = vms_dlsym (dh, &ptr, flags);
  165. if (!($VMS_STATUS_SUCCESS(status)))
  166. {
  167. error_status = status;
  168. return NULL;
  169. }
  170. }
  171. return ptr;
  172. }
  173. int vms_dlsym (
  174. vms_dl *dh,
  175. void **ptr,
  176. int flags)
  177. {
  178. LIB$ESTABLISH (LIB$SIG_TO_RET);
  179. return LIB$FIND_IMAGE_SYMBOL (&dh->fnmdes, &dh->symdes, ptr, &dh->imgdes, flags);
  180. }
  181. const char *lt_dlerror (void)
  182. {
  183. struct dsc$descriptor desc;
  184. short outlen;
  185. int status;
  186. if (($VMS_STATUS_SUCCESS(error_status))) return NULL;
  187. desc.dsc$b_dtype = DSC$K_DTYPE_T;
  188. desc.dsc$b_class = DSC$K_CLASS_S;
  189. desc.dsc$a_pointer = error_buffer;
  190. desc.dsc$w_length = sizeof (error_buffer);
  191. status = sys$getmsg (error_status, &outlen, &desc, 15, 0);
  192. if ($VMS_STATUS_SUCCESS(status)) error_buffer[outlen] = '\0';
  193. else sprintf (error_buffer, "OpenVMS exit status %8X", error_status);
  194. error_status = SS$_NORMAL;
  195. return (error_buffer);
  196. }
  197. struct itemlist3 {
  198. unsigned short buflen;
  199. unsigned short item;
  200. void *buf;
  201. unsigned short *retlen;
  202. };
  203. int lt_dladdsearchdir (const char *search_dir)
  204. {
  205. /*
  206. * Adds a path to the list of paths where lt_dlopen will look for shareable images.
  207. * We do this via a user-mode search list logical, adding one more item to the end of
  208. * the list whenever called.
  209. */
  210. $DESCRIPTOR(lib_path_d, "LTDL_LIBRARY_PATH");
  211. $DESCRIPTOR( proc_table_d, "LNM$PROCESS_TABLE" );
  212. unsigned int status = 0;
  213. unsigned char accmode = 0, lnm_exists = 1;
  214. int index = 0, max_index = 0;
  215. struct itemlist3 trnlnmlst[4] = {{sizeof(accmode), LNM$_ACMODE, &accmode, 0},
  216. {sizeof(max_index), LNM$_MAX_INDEX, &max_index, 0},
  217. {0, 0, 0, 0},
  218. {0, 0, 0, 0}};
  219. struct itemlist3 *crelnmlst;
  220. struct eqvarray {
  221. char eqvname[256];
  222. };
  223. struct eqvarray *eqvlist;
  224. /* First just check to see whether the logical name exists and how many equivalence
  225. * names there are.
  226. */
  227. status = SYS$TRNLNM ( NULL,
  228. &proc_table_d,
  229. &lib_path_d,
  230. NULL,
  231. trnlnmlst);
  232. /* If the logical name doesn't exist or exists at a privilege mode or table I
  233. * can't even look at, then I'll want to proceed with creating my user-mode logical.
  234. */
  235. if ( status == SS$_NOLOGNAM || status == SS$_NOPRIV ) {
  236. status = SS$_NORMAL;
  237. lnm_exists = 0; /* skip further translation attempts */
  238. max_index = 0;
  239. }
  240. if (!$VMS_STATUS_SUCCESS(status)) {
  241. error_status = status;
  242. return -1;
  243. }
  244. /* Also skip further translation if the first translation exists in any mode other
  245. * than user mode; we want to stick user mode logicals in front of these.
  246. */
  247. if ( accmode != PSL$C_USER ) {
  248. lnm_exists = 0;
  249. max_index = 0;
  250. }
  251. /* Allocate an item list for logical name creation and an array of equivalence
  252. * name buffers.
  253. */
  254. crelnmlst = (struct itemlist3 *) malloc( sizeof(struct itemlist3) * (max_index + 3) );
  255. if (crelnmlst == NULL) { error_status = SS$_INSFMEM; return -1; }
  256. eqvlist = (struct eqvarray *) malloc( sizeof(struct eqvarray) * (max_index + 2) );
  257. if (eqvlist == NULL) { error_status = SS$_INSFMEM; return -1; }
  258. trnlnmlst[1].buflen = sizeof(index);
  259. trnlnmlst[1].item = LNM$_INDEX;
  260. trnlnmlst[1].buf = &index;
  261. trnlnmlst[1].retlen = NULL;
  262. trnlnmlst[2].buflen = sizeof(eqvlist[0].eqvname);
  263. trnlnmlst[2].item = LNM$_STRING;
  264. /* The loops iterates over the search list index, getting the translation
  265. * for each index and storing it in the item list for re-creation.
  266. */
  267. for (index = 0; index <= max_index && lnm_exists; index++ ) {
  268. /* Wire the input buffer for translation to the output buffer for creation */
  269. trnlnmlst[2].buf = &eqvlist[index].eqvname;
  270. crelnmlst[index].buf = &eqvlist[index].eqvname;
  271. trnlnmlst[2].retlen = &crelnmlst[index].buflen;
  272. status = SYS$TRNLNM ( NULL,
  273. &proc_table_d,
  274. &lib_path_d,
  275. NULL,
  276. trnlnmlst);
  277. if (!$VMS_STATUS_SUCCESS(status)) {
  278. error_status = status;
  279. free(crelnmlst);
  280. free(eqvlist);
  281. return -1;
  282. }
  283. /* If we come across a non-user-mode translation, back up and get out
  284. * because we don't want to recreate those in user mode.
  285. */
  286. if ( accmode != PSL$C_USER ) {
  287. index--;
  288. break;
  289. }
  290. crelnmlst[index].item = LNM$_STRING;
  291. crelnmlst[index].retlen = NULL;
  292. }
  293. /* At this point we have captured all the existing translations (if
  294. * any) and stored them in the item list for re-creation of the logical
  295. * name. All that's left is to add the new item to the end of the list
  296. * and terminate the list.
  297. */
  298. crelnmlst[index].buflen = strlen(search_dir);
  299. crelnmlst[index].item = LNM$_STRING;
  300. crelnmlst[index].buf = (char *) search_dir;
  301. crelnmlst[index].retlen = NULL;
  302. crelnmlst[index+1].buflen = 0;
  303. crelnmlst[index+1].item = 0;
  304. crelnmlst[index+1].buf = NULL;
  305. crelnmlst[index+1].retlen = NULL;
  306. accmode = PSL$C_USER;
  307. status = SYS$CRELNM( NULL,
  308. &proc_table_d,
  309. &lib_path_d,
  310. &accmode,
  311. crelnmlst );
  312. if (!$VMS_STATUS_SUCCESS(status)) {
  313. error_status = status;
  314. free(crelnmlst);
  315. free(eqvlist);
  316. return -1;
  317. }
  318. free(crelnmlst);
  319. free(eqvlist);
  320. error_status = SS$_NORMAL;
  321. return 0;
  322. }
  323. char * getvmsenv (char *symbol)
  324. {
  325. int status;
  326. unsigned short cbvalue;
  327. $DESCRIPTOR (logicalnametable, "LNM$FILE_DEV");
  328. struct dsc$descriptor_s logicalname;
  329. struct itemlist3 itemlist[2];
  330. logicalname.dsc$w_length = strlen (symbol);
  331. logicalname.dsc$b_dtype = DSC$K_DTYPE_T;
  332. logicalname.dsc$b_class = DSC$K_CLASS_S;
  333. logicalname.dsc$a_pointer = symbol;
  334. itemlist[0].buflen = sizeof (getenv_buffer) -1;
  335. itemlist[0].item = LNM$_STRING;
  336. itemlist[0].buf = getenv_buffer;
  337. itemlist[0].retlen = &cbvalue;
  338. itemlist[1].buflen = 0;
  339. itemlist[1].item = 0;
  340. itemlist[1].buf = 0;
  341. itemlist[1].retlen = 0;
  342. status = SYS$TRNLNM (0, &logicalnametable, &logicalname, 0, itemlist);
  343. if (!($VMS_STATUS_SUCCESS(status))) return NULL;
  344. if (cbvalue > 0)
  345. {
  346. getenv_buffer[cbvalue] = '\0';
  347. return getenv_buffer;
  348. }
  349. return NULL;
  350. }