File: dynlink.c

package info (click to toggle)
scheme48 1.8%2Bdfsg-1%2Bdeb7u1
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 14,984 kB
file content (117 lines) | stat: -rw-r--r-- 2,447 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
/* Copyright (c) 1993-2008 by Richard Kelsey and Jonathan Rees.
   See file COPYING. */

/*
 * Dynamically load external modules on machines that support it.
 */

#include "sysdep.h"

#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "scheme48.h"

#if defined(HAVE_DLOPEN)
 #include <dlfcn.h>
#else
#include "fake/dlfcn.h"
#endif

#if	defined(RTLD_NOW)
#define	DLOPEN_MODE	RTLD_NOW
#elif	defined(RTLD_LAZY)
#define	DLOPEN_MODE	(RTLD_LAZY)
#else
#define	DLOPEN_MODE	(1)
#endif

static s48_value
shared_object_dlopen(s48_value name, s48_value complete_name_p)
{
  S48_DECLARE_GC_PROTECT(1);
  void *handle;
  s48_value res;
  s48_value full_name;

  S48_GC_PROTECT_1(name);

  if (!S48_EQ(S48_FALSE, complete_name_p))
    {
      size_t len = strlen(s48_extract_byte_vector(name));
      full_name = s48_make_byte_vector(len + 4);
      memcpy(s48_extract_byte_vector(full_name),
	     s48_extract_byte_vector(name),
	     len);
      memcpy(s48_extract_byte_vector(full_name) + len,
	     ".so",
	     4);
    }
  else
    full_name = name;

  handle = dlopen(s48_extract_byte_vector(full_name), DLOPEN_MODE);
  if (handle == NULL)
    s48_raise_string_os_error((char *)dlerror());

  res = S48_MAKE_VALUE(void *);
  S48_UNSAFE_EXTRACT_VALUE(res, void *) = handle;

  S48_GC_UNPROTECT();

  return res;
}

static s48_value
shared_object_dlsym(s48_value handle, s48_value name)
{
  const char *error;
  void *entry;
  void *native_handle;
  s48_value res;
  char *native_name;
  
  native_handle = S48_EXTRACT_VALUE(handle, void *);

  native_name = s48_extract_byte_vector(name);

  entry = dlsym(native_handle, native_name);

  if (entry == NULL)
    s48_raise_string_os_error((char*)dlerror());

  res = S48_MAKE_VALUE(void *);
  S48_UNSAFE_EXTRACT_VALUE(res, void *) = entry;
  return res;
}

static s48_value
shared_object_dlclose(s48_value handle)
{
  void *native_handle = S48_EXTRACT_VALUE(handle, void *);
  
  if (dlclose(native_handle) < 0)
    s48_raise_string_os_error((char*)dlerror());
  return S48_UNSPECIFIC;
}

typedef void (*thunk)();

static s48_value
shared_object_call_thunk(s48_value value)
{
  thunk entry;

  entry = S48_EXTRACT_VALUE(value, thunk);
  entry();
  return S48_UNSPECIFIC;
}

void
s48_init_dynlink(void)
{
  S48_EXPORT_FUNCTION(shared_object_dlopen);
  S48_EXPORT_FUNCTION(shared_object_dlsym);
  S48_EXPORT_FUNCTION(shared_object_dlclose);
  S48_EXPORT_FUNCTION(shared_object_call_thunk);
}