File: load.c

package info (click to toggle)
tcltrf 2.1.4-dfsg3-2
  • links: PTS
  • area: main
  • in suites: buster, stretch
  • size: 9,652 kB
  • ctags: 9,400
  • sloc: ansic: 73,138; sh: 3,155; tcl: 1,343; makefile: 182; exp: 22
file content (160 lines) | stat: -rw-r--r-- 4,432 bytes parent folder | download | duplicates (7)
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
/*
 * load.c --
 *
 *	general purpose loader for shared libraries.
 *	essentially the last 2 functions of 'imgInit.c'
 *	(see 'Img' library by Jan Nijtmans).
 *
 * Copyright (c) 1996 Jan Nijtmans (nijtmans.nici.kun.nl)
 * All rights reserved.
 *
 * CVS: $Id: load.c,v 1.5 1999/09/19 10:33:26 aku Exp $
 */

#include "transformInt.h"

#define Offset(type,field) ((unsigned long) (((char *) &((type *) 0)->field)))

/*
 *----------------------------------------------------------------------
 *
 * Trf_LoadLibrary --
 *
 *	This procedure is called to load a shared library into memory.
 *	If the extension is ".so" (e.g. Solaris, Linux) or ".sl" (HP-UX)
 *	it is possible that the extension is appended or replaced with
 *	a major version number. If the file cannot be found, the version
 *	numbers will be stripped off one by one. e.g.
 *
 *	HP-UX:	libtiff.3.4	Linux,Solaris:	libtiff.so.3.4
 *		libtiff.3			libtiff.so.3
 *		libtiff.sl			libtiff.so
 *
 * Results:
 *	TCL_OK if function succeeds. Otherwise TCL_ERROR while the
 *	interpreter will contain an error-message. The last parameter
 *	"num" contains the minimum number of symbols that is required
 *	by the application to succeed. Only the first <num> symbols
 *	will produce an error if they cannot be found.
 *
 * Side effects:
 *	At least <num> Library functions become available by the
 *	application.
 *
 *----------------------------------------------------------------------
 */

typedef struct Functions {
    VOID *handle;
    int (* first) _ANSI_ARGS_((void));
    int (* next) _ANSI_ARGS_((void));
} Functions;

/* MS defines something under this name, avoid the collision
 */

#define TRF_LOAD_FAILED ((VOID *) -114)

int
Trf_LoadLibrary (interp, libName, handlePtr, symbols, num)
    Tcl_Interp *interp;
    CONST char *libName;
    VOID **handlePtr;
    char **symbols;
    int num;
{
    VOID *handle = (VOID *) NULL;
    Functions *lib = (Functions *) handlePtr;
    char **p = (char **) &(lib->first);
    char **q = symbols;
    char buf[256];
    char *r;
    int length;

    if (lib->handle != NULL) {
      if (lib->handle == TRF_LOAD_FAILED) {
	Tcl_AppendResult (interp, "cannot open ", (char*) NULL);
	Tcl_AppendResult (interp, libName, (char*) NULL);
      }
      return (lib->handle != TRF_LOAD_FAILED) ? TCL_OK : TCL_ERROR;
    }

    length = strlen(libName);
    strcpy(buf,libName);
    handle = dlopen(buf, RTLD_NOW);

    while (handle == NULL) {
	if ((r = strrchr(buf,'.')) != NULL) {
	    if ((r[1] < '0') || (r[1] > '9')) {
	        Tcl_AppendResult (interp, "cannot open ", (char*) NULL);
	        Tcl_AppendResult (interp, libName, (char*) NULL);
	        Tcl_AppendResult (interp, ": ", (char*) NULL);
	        Tcl_AppendResult (interp, dlerror (), (char*) NULL);
		lib->handle = TRF_LOAD_FAILED;
		return TCL_ERROR;
	    }
	    length = r - buf;
	    *r = 0;
	}
	if (strchr(buf,'.') == NULL) {
	    strcpy(buf+length,".sl");
	    length += 3;
	}
	dlerror();
	handle = dlopen(buf, RTLD_NOW);
    }

    buf[0] = '_';
    while (*q) {
	*p = (char *) dlsym(handle,*q);
	if (*p == (char *)NULL) {
	    strcpy(buf+1,*q);
	    *p = (char *) dlsym(handle,buf);
	    if ((num > 0) && (*p == (char *)NULL)) {
	        Tcl_AppendResult (interp, "cannot open ", (char*) NULL);
	        Tcl_AppendResult (interp, libName, (char*) NULL);
	        Tcl_AppendResult (interp, ": symbol \"", (char*) NULL);
	        Tcl_AppendResult (interp, *q, (char*) NULL);
	        Tcl_AppendResult (interp, "\" not found", (char*) NULL);
		dlclose(handle);
		lib->handle = TRF_LOAD_FAILED;
		return TCL_ERROR;
	    }
	}
	q++; num--;
	p += (Offset(Functions, next) - Offset(Functions, first)) /
		sizeof(char *);
    }
    lib->handle = handle;

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Trf_LoadFailed --
 *
 *	Mark the loaded library as invalid. Remove it from memory
 *	if possible. It will no longer be used in the future.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Next time the same handle is used by TrfLoadLib, it will
 *	fail immediately, without trying to load it.
 *
 *----------------------------------------------------------------------
 */

void
Trf_LoadFailed (handlePtr)
    VOID **handlePtr;
{
    if ((*handlePtr != NULL) && (*handlePtr != TRF_LOAD_FAILED)) {
	/* Oops, still loaded. First remove it from menory */
	dlclose(*handlePtr);
    }
    *handlePtr = TRF_LOAD_FAILED;
}