~ps10gel/ubuntu/xenial/trafficserver/6.2.0

« back to all changes in this revision

Viewing changes to proxy/Plugin.cc

  • Committer: Bazaar Package Importer
  • Author(s): Arno Toell
  • Date: 2011-01-13 11:49:18 UTC
  • Revision ID: james.westby@ubuntu.com-20110113114918-vu422h8dknrgkj15
Tags: upstream-2.1.5-unstable
ImportĀ upstreamĀ versionĀ 2.1.5-unstable

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/** @file
 
2
 
 
3
  Plugin init
 
4
 
 
5
  @section license License
 
6
 
 
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
 
14
 
 
15
      http://www.apache.org/licenses/LICENSE-2.0
 
16
 
 
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.
 
22
 */
 
23
 
 
24
#include <stdio.h>
 
25
// XXX: HP-UX ??? Not part of configure supported hosts
 
26
#if defined(hpux)
 
27
#include <dl.h>
 
28
#endif
 
29
#include "ink_platform.h"
 
30
#include "ink_file.h"
 
31
#include "Compatability.h"
 
32
#include "ParseRules.h"
 
33
#include "I_RecCore.h"
 
34
#include "I_Layout.h"
 
35
#include "InkAPIInternal.h"
 
36
#include "Main.h"
 
37
#include "Plugin.h"
 
38
#include "PluginDB.h"
 
39
#include "stats/Stats.h"
 
40
 
 
41
// HPUX:
 
42
//   LD_SHAREDCMD=ld -b
 
43
// SGI:
 
44
//   LD_SHAREDCMD=ld -shared
 
45
// OSF:
 
46
//   LD_SHAREDCMD=ld -shared -all -expect_unresolved "*"
 
47
// Solaris:
 
48
//   LD_SHAREDCMD=ld -G
 
49
 
 
50
 
 
51
static const char *plugin_dir = ".";
 
52
static const char *extensions_dir = ".";
 
53
static PluginDB *plugin_db = NULL;
 
54
 
 
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);
 
58
 
 
59
tsapi int
 
60
load_in_export_symbols(int j)
 
61
{
 
62
  int i = eight_bit_table[j];
 
63
  return i;
 
64
}
 
65
 
 
66
// Plugin registration vars
 
67
//
 
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
 
75
//      global pointer
 
76
//
 
77
DLL<PluginRegInfo> plugin_reg_list;
 
78
PluginRegInfo *plugin_reg_current = NULL;
 
79
 
 
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)
 
83
{ }
 
84
 
 
85
static void *
 
86
dll_open(char *fn, bool global)
 
87
{
 
88
  int global_flags = global ? RTLD_GLOBAL : 0;
 
89
 
 
90
  return (void *) dlopen(fn, RTLD_NOW | global_flags);
 
91
}
 
92
 
 
93
static void *
 
94
dll_findsym(void *dlp, const char *name)
 
95
{
 
96
  return (void *) dlsym(dlp, name);
 
97
}
 
98
 
 
99
static char *
 
100
dll_error(void *dlp)
 
101
{
 
102
  NOWARN_UNUSED(dlp);
 
103
  return (char *) dlerror();
 
104
}
 
105
 
 
106
static void
 
107
dll_close(void *dlp)
 
108
{
 
109
  dlclose(dlp);
 
110
}
 
111
 
 
112
 
 
113
static void
 
114
plugin_load(int argc, char *argv[], bool internal)
 
115
{
 
116
  char path[PATH_NAME_MAX + 1];
 
117
  void *handle;
 
118
  init_func_t init;
 
119
  lic_req_func_t lic_req;
 
120
  PluginRegInfo *plugin_reg_temp;
 
121
  const char *pdir = internal ? extensions_dir : plugin_dir;
 
122
 
 
123
  if (argc < 1) {
 
124
    return;
 
125
  }
 
126
  ink_filepath_make(path, sizeof(path), pdir, argv[0]);
 
127
 
 
128
  Note("loading plugin '%s'", path);
 
129
 
 
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);
 
134
      break;
 
135
    }
 
136
    plugin_reg_temp = (plugin_reg_temp->link).next;
 
137
  }
 
138
 
 
139
  handle = dll_open(path, (internal ? true : false));
 
140
  if (!handle) {
 
141
    Error("unable to load '%s': %s", path, dll_error(handle));
 
142
    abort();
 
143
  }
 
144
 
 
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]);
 
150
      dll_close(handle);
 
151
      abort();
 
152
    }
 
153
  }
 
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);
 
159
 
 
160
  init_func_w_handle_t inith = (init_func_w_handle_t) dll_findsym(handle, "TSPluginInitwDLLHandle");
 
161
  if (inith) {
 
162
    inith(handle, argc, argv);
 
163
    return;
 
164
  }
 
165
 
 
166
  init = (init_func_t) dll_findsym(handle, "TSPluginInit");
 
167
  if (!init) {
 
168
    Error("unable to find TSPluginInit function '%s': %s", path, dll_error(handle));
 
169
    dll_close(handle);
 
170
    abort();
 
171
  }
 
172
 
 
173
  init(argc, argv);
 
174
 
 
175
  plugin_reg_list.push(plugin_reg_current);
 
176
  plugin_reg_current = NULL;
 
177
  //dll_close(handle);
 
178
}
 
179
 
 
180
static char *
 
181
plugin_expand(char *arg)
 
182
{
 
183
  RecDataT data_type;
 
184
  char *str = NULL;
 
185
 
 
186
  if (*arg != '$') {
 
187
    return (char *) NULL;
 
188
  }
 
189
  // skip the $ character
 
190
  arg += 1;
 
191
 
 
192
  if (RecGetRecordDataType(arg, &data_type) != REC_ERR_OKAY) {
 
193
    goto not_found;
 
194
  }
 
195
 
 
196
  switch (data_type) {
 
197
  case RECD_STRING:
 
198
    {
 
199
      RecString str_val;
 
200
      if (RecGetRecordString_Xmalloc(arg, &str_val) != REC_ERR_OKAY) {
 
201
        goto not_found;
 
202
      }
 
203
      return (char *) str_val;
 
204
      break;
 
205
    }
 
206
  case RECD_FLOAT:
 
207
    {
 
208
      RecFloat float_val;
 
209
      if (RecGetRecordFloat(arg, &float_val) != REC_ERR_OKAY) {
 
210
        goto not_found;
 
211
      }
 
212
      str = (char *) xmalloc(128);
 
213
      snprintf(str, 128, "%f", (float) float_val);
 
214
      return str;
 
215
      break;
 
216
    }
 
217
  case RECD_INT:
 
218
    {
 
219
      RecInt int_val;
 
220
      if (RecGetRecordInt(arg, &int_val) != REC_ERR_OKAY) {
 
221
        goto not_found;
 
222
      }
 
223
      str = (char *) xmalloc(128);
 
224
      snprintf(str, 128, "%ld", (long int) int_val);
 
225
      return str;
 
226
      break;
 
227
    }
 
228
  case RECD_COUNTER:
 
229
    {
 
230
      RecCounter count_val;
 
231
      if (RecGetRecordCounter(arg, &count_val) != REC_ERR_OKAY) {
 
232
        goto not_found;
 
233
      }
 
234
      str = (char *) xmalloc(128);
 
235
      snprintf(str, 128, "%ld", (long int) count_val);
 
236
      return str;
 
237
      break;
 
238
    }
 
239
  default:
 
240
    goto not_found;
 
241
    break;
 
242
  }
 
243
 
 
244
 
 
245
not_found:
 
246
  Warning("plugin.config: unable to find parameter %s", arg);
 
247
  return NULL;
 
248
}
 
249
 
 
250
 
 
251
int
 
252
plugins_exist(const char *config_dir)
 
253
{
 
254
  char path[PATH_NAME_MAX + 1];
 
255
  char line[1024], *p;
 
256
  int fd;
 
257
  int plugin_count = 0;
 
258
 
 
259
  ink_filepath_make(path, sizeof(path), config_dir, "plugin.config");
 
260
  fd = open(path, O_RDONLY);
 
261
  if (fd < 0) {
 
262
    Warning("unable to open plugin config file '%s': %d, %s", path, errno, strerror(errno));
 
263
    return 0;
 
264
  }
 
265
  while (ink_file_fd_readline(fd, sizeof(line) - 1, line) > 0) {
 
266
    p = line;
 
267
    // strip leading white space and test for comment or blank line
 
268
    while (*p && ParseRules::is_wslfcr(*p))
 
269
      ++p;
 
270
    if ((*p == '\0') || (*p == '#'))
 
271
      continue;
 
272
    plugin_count++;
 
273
  }
 
274
  close(fd);
 
275
  return plugin_count;
 
276
}
 
277
 
 
278
void
 
279
plugin_init(const char *config_dir, bool internal)
 
280
{
 
281
  char path[PATH_NAME_MAX + 1];
 
282
  char line[1024], *p;
 
283
  char *argv[64];
 
284
  char *vars[64];
 
285
  int argc;
 
286
  int fd;
 
287
  int i;
 
288
  static bool INIT_ONCE = true;
 
289
 
 
290
  if (INIT_ONCE) {
 
291
    api_init();
 
292
    init_inkapi_stat_system();
 
293
    char *cfg = NULL;
 
294
 
 
295
    plugin_dir = TSPluginDirGet();
 
296
 
 
297
    RecGetRecordString_Xmalloc("proxy.config.plugin.extensions_dir", (char**)&cfg);
 
298
    if (cfg != NULL) {
 
299
      extensions_dir = Layout::get()->relative(cfg);
 
300
      xfree(cfg);
 
301
      cfg = NULL;
 
302
    }
 
303
    ink_filepath_make(path, sizeof(path), config_dir, "plugin.db");
 
304
    plugin_db = new PluginDB(path);
 
305
    INIT_ONCE = false;
 
306
  }
 
307
 
 
308
  ink_assert(plugin_db);
 
309
 
 
310
  if (internal == false) {
 
311
    ink_filepath_make(path, sizeof(path), config_dir, "plugin.config");
 
312
  } else {
 
313
    ink_filepath_make(path, sizeof(path), config_dir, "extensions.config");
 
314
  }
 
315
 
 
316
  fd = open(path, O_RDONLY);
 
317
  if (fd < 0) {
 
318
    /* secret extensions dont complain */
 
319
    if (internal == false) {
 
320
      Warning("unable to open plugin config file '%s': %d, %s", path, errno, strerror(errno));
 
321
    }
 
322
    return;
 
323
  }
 
324
 
 
325
  while (ink_file_fd_readline(fd, sizeof(line) - 1, line) > 0) {
 
326
    argc = 0;
 
327
    p = line;
 
328
 
 
329
    // strip leading white space and test for comment or blank line
 
330
    while (*p && ParseRules::is_wslfcr(*p))
 
331
      ++p;
 
332
    if ((*p == '\0') || (*p == '#'))
 
333
      continue;
 
334
 
 
335
    // not comment or blank, so rip line into tokens
 
336
    while (1) {
 
337
      while (*p && ParseRules::is_wslfcr(*p))
 
338
        ++p;
 
339
      if ((*p == '\0') || (*p == '#'))
 
340
        break;                  // EOL
 
341
 
 
342
      if (*p == '\"') {
 
343
        p += 1;
 
344
 
 
345
        argv[argc++] = p;
 
346
 
 
347
        while (*p && (*p != '\"')) {
 
348
          p += 1;
 
349
        }
 
350
        if (*p == '\0') {
 
351
          break;
 
352
        }
 
353
        *p++ = '\0';
 
354
      } else {
 
355
        argv[argc++] = p;
 
356
 
 
357
        while (*p && !ParseRules::is_wslfcr(*p) && (*p != '#')) {
 
358
          p += 1;
 
359
        }
 
360
        if ((*p == '\0') || (*p == '#')) {
 
361
          break;
 
362
        }
 
363
        *p++ = '\0';
 
364
      }
 
365
    }
 
366
 
 
367
    for (i = 0; i < argc; i++) {
 
368
      vars[i] = plugin_expand(argv[i]);
 
369
      if (vars[i]) {
 
370
        argv[i] = vars[i];
 
371
      }
 
372
    }
 
373
 
 
374
    plugin_load(argc, argv, internal);
 
375
 
 
376
    for (i = 0; i < argc; i++) {
 
377
      if (vars[i]) {
 
378
        xfree(vars[i]);
 
379
      }
 
380
    }
 
381
  }
 
382
 
 
383
  close(fd);
 
384
}
 
385