5
@section license License
7
Licensed to the Apache Software Foundation (ASF) under one
8
or more contributor license agreements. See the NOTICE file
9
distributed with this work for additional information
10
regarding copyright ownership. The ASF licenses this file
11
to you under the Apache License, Version 2.0 (the
12
"License"); you may not use this file except in compliance
13
with the License. You may obtain a copy of the License at
15
http://www.apache.org/licenses/LICENSE-2.0
17
Unless required by applicable law or agreed to in writing, software
18
distributed under the License is distributed on an "AS IS" BASIS,
19
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20
See the License for the specific language governing permissions and
21
limitations under the License.
25
// XXX: HP-UX ??? Not part of configure supported hosts
29
#include "ink_platform.h"
31
#include "Compatability.h"
32
#include "ParseRules.h"
33
#include "I_RecCore.h"
35
#include "InkAPIInternal.h"
39
#include "stats/Stats.h"
44
// LD_SHAREDCMD=ld -shared
46
// LD_SHAREDCMD=ld -shared -all -expect_unresolved "*"
51
static const char *plugin_dir = ".";
52
static const char *extensions_dir = ".";
53
static PluginDB *plugin_db = NULL;
55
typedef void (*init_func_t) (int argc, char *argv[]);
56
typedef void (*init_func_w_handle_t) (void *handle, int argc, char *argv[]);
57
typedef int (*lic_req_func_t) (void);
60
load_in_export_symbols(int j)
62
int i = eight_bit_table[j];
66
// Plugin registration vars
68
// plugin_reg_list has an entry for each plugin
69
// we've successfully been able to load
70
// plugin_reg_current is used to associate the
71
// plugin we're in the process of loading with
72
// it struct. We need this global pointer since
73
// the API doesn't have any plugin context. Init
74
// is single threaded so we can get away with the
77
DLL<PluginRegInfo> plugin_reg_list;
78
PluginRegInfo *plugin_reg_current = NULL;
80
PluginRegInfo::PluginRegInfo()
81
: plugin_registered(false), plugin_path(NULL), sdk_version(PLUGIN_SDK_VERSION_UNKNOWN),
82
plugin_name(NULL), vendor_name(NULL), support_email(NULL)
86
dll_open(char *fn, bool global)
88
int global_flags = global ? RTLD_GLOBAL : 0;
90
return (void *) dlopen(fn, RTLD_NOW | global_flags);
94
dll_findsym(void *dlp, const char *name)
96
return (void *) dlsym(dlp, name);
103
return (char *) dlerror();
114
plugin_load(int argc, char *argv[], bool internal)
116
char path[PATH_NAME_MAX + 1];
119
lic_req_func_t lic_req;
120
PluginRegInfo *plugin_reg_temp;
121
const char *pdir = internal ? extensions_dir : plugin_dir;
126
ink_filepath_make(path, sizeof(path), pdir, argv[0]);
128
Note("loading plugin '%s'", path);
130
plugin_reg_temp = plugin_reg_list.head;
131
while (plugin_reg_temp) {
132
if (strcmp(plugin_reg_temp->plugin_path, path) == 0) {
133
Warning("multiple loading of plugin %s", path);
136
plugin_reg_temp = (plugin_reg_temp->link).next;
139
handle = dll_open(path, (internal ? true : false));
141
Error("unable to load '%s': %s", path, dll_error(handle));
145
lic_req = (lic_req_func_t) dll_findsym(handle, "TSPluginLicenseRequired");
146
if (lic_req && lic_req() != 0) {
147
PluginDB::CheckLicenseResult result = plugin_db->CheckLicense(argv[0]);
148
if (result != PluginDB::license_ok) {
149
Error("unable to load '%s': %s", path, PluginDB::CheckLicenseResultStr[result]);
154
// Allocate a new registration structure for the
155
// plugin we're starting up
156
ink_assert(plugin_reg_current == NULL);
157
plugin_reg_current = new PluginRegInfo;
158
plugin_reg_current->plugin_path = xstrdup(path);
160
init_func_w_handle_t inith = (init_func_w_handle_t) dll_findsym(handle, "TSPluginInitwDLLHandle");
162
inith(handle, argc, argv);
166
init = (init_func_t) dll_findsym(handle, "TSPluginInit");
168
Error("unable to find TSPluginInit function '%s': %s", path, dll_error(handle));
175
plugin_reg_list.push(plugin_reg_current);
176
plugin_reg_current = NULL;
181
plugin_expand(char *arg)
187
return (char *) NULL;
189
// skip the $ character
192
if (RecGetRecordDataType(arg, &data_type) != REC_ERR_OKAY) {
200
if (RecGetRecordString_Xmalloc(arg, &str_val) != REC_ERR_OKAY) {
203
return (char *) str_val;
209
if (RecGetRecordFloat(arg, &float_val) != REC_ERR_OKAY) {
212
str = (char *) xmalloc(128);
213
snprintf(str, 128, "%f", (float) float_val);
220
if (RecGetRecordInt(arg, &int_val) != REC_ERR_OKAY) {
223
str = (char *) xmalloc(128);
224
snprintf(str, 128, "%ld", (long int) int_val);
230
RecCounter count_val;
231
if (RecGetRecordCounter(arg, &count_val) != REC_ERR_OKAY) {
234
str = (char *) xmalloc(128);
235
snprintf(str, 128, "%ld", (long int) count_val);
246
Warning("plugin.config: unable to find parameter %s", arg);
252
plugins_exist(const char *config_dir)
254
char path[PATH_NAME_MAX + 1];
257
int plugin_count = 0;
259
ink_filepath_make(path, sizeof(path), config_dir, "plugin.config");
260
fd = open(path, O_RDONLY);
262
Warning("unable to open plugin config file '%s': %d, %s", path, errno, strerror(errno));
265
while (ink_file_fd_readline(fd, sizeof(line) - 1, line) > 0) {
267
// strip leading white space and test for comment or blank line
268
while (*p && ParseRules::is_wslfcr(*p))
270
if ((*p == '\0') || (*p == '#'))
279
plugin_init(const char *config_dir, bool internal)
281
char path[PATH_NAME_MAX + 1];
288
static bool INIT_ONCE = true;
292
init_inkapi_stat_system();
295
plugin_dir = TSPluginDirGet();
297
RecGetRecordString_Xmalloc("proxy.config.plugin.extensions_dir", (char**)&cfg);
299
extensions_dir = Layout::get()->relative(cfg);
303
ink_filepath_make(path, sizeof(path), config_dir, "plugin.db");
304
plugin_db = new PluginDB(path);
308
ink_assert(plugin_db);
310
if (internal == false) {
311
ink_filepath_make(path, sizeof(path), config_dir, "plugin.config");
313
ink_filepath_make(path, sizeof(path), config_dir, "extensions.config");
316
fd = open(path, O_RDONLY);
318
/* secret extensions dont complain */
319
if (internal == false) {
320
Warning("unable to open plugin config file '%s': %d, %s", path, errno, strerror(errno));
325
while (ink_file_fd_readline(fd, sizeof(line) - 1, line) > 0) {
329
// strip leading white space and test for comment or blank line
330
while (*p && ParseRules::is_wslfcr(*p))
332
if ((*p == '\0') || (*p == '#'))
335
// not comment or blank, so rip line into tokens
337
while (*p && ParseRules::is_wslfcr(*p))
339
if ((*p == '\0') || (*p == '#'))
347
while (*p && (*p != '\"')) {
357
while (*p && !ParseRules::is_wslfcr(*p) && (*p != '#')) {
360
if ((*p == '\0') || (*p == '#')) {
367
for (i = 0; i < argc; i++) {
368
vars[i] = plugin_expand(argv[i]);
374
plugin_load(argc, argv, internal);
376
for (i = 0; i < argc; i++) {