File indexing completed on 2025-05-11 08:24:16
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038 #ifdef HAVE_CONFIG_H
0039 #include "config.h"
0040 #endif
0041
0042 #include <pthread.h>
0043 #include <stdarg.h>
0044 #include <stdlib.h>
0045 #include <stdio.h>
0046 #include <string.h>
0047
0048 #include <rtems/libio_.h>
0049
0050 #include <dlfcn.h>
0051 #include <rtems/rtl/rap.h>
0052 #include <rtems/rtl/rtl.h>
0053
0054 #include "rtl-find-file.h"
0055
0056
0057
0058
0059
0060 typedef struct rtems_rap_data_s
0061 {
0062 pthread_once_t once;
0063 rtems_mutex lock;
0064 rtems_chain_control apps;
0065 int last_errno;
0066 char last_error[64];
0067 } rtems_rap_data;
0068
0069
0070
0071
0072
0073 typedef struct rtems_rap_app
0074 {
0075 rtems_chain_node node;
0076 const char* name;
0077 void* handle;
0078 } rtems_rap_app;
0079
0080
0081
0082
0083 #if (RTL_GLUE(__USER_LABEL_PREFIX__, 1) == RTL_GLUE(_, 1))
0084 #define RTL_ENTRY_POINT "_rtems"
0085 #else
0086 #define RTL_ENTRY_POINT "rtems"
0087 #endif
0088
0089
0090
0091
0092 static rtems_rap_data rap_ = { .once = PTHREAD_ONCE_INIT };
0093
0094
0095
0096
0097 static bool rap_verbose;
0098
0099
0100
0101
0102 typedef int (*rtems_rap_entry)(int argc, const char* argv[]);
0103
0104
0105
0106
0107 static void rtems_rap_unlock (void);
0108
0109 static void
0110 rtems_rap_data_init (void)
0111 {
0112
0113
0114
0115 rtems_mutex_init (&rap_.lock, "RAP");
0116
0117
0118
0119
0120 rtems_chain_initialize_empty (&rap_.apps);
0121 }
0122
0123 static rtems_rap_data*
0124 rtems_rap_lock (void)
0125 {
0126 pthread_once (&rap_.once, rtems_rap_data_init);
0127 rtems_mutex_lock (&rap_.lock);
0128
0129 return &rap_;
0130 }
0131
0132 static void
0133 rtems_rap_unlock (void)
0134 {
0135 rtems_mutex_unlock (&rap_.lock);
0136 }
0137
0138 static rtems_rap_app*
0139 rtems_rap_check_handle (void* handle)
0140 {
0141 rtems_rap_app* app;
0142 rtems_chain_node* node;
0143
0144 app = handle;
0145 node = rtems_chain_first (&rap_.apps);
0146
0147 while (!rtems_chain_is_tail (&rap_.apps, node))
0148 {
0149 rtems_rap_app* check = (rtems_rap_app*) node;
0150 if (check == app)
0151 return app;
0152 node = rtems_chain_next (node);
0153 }
0154
0155 return NULL;
0156 }
0157
0158 static rtems_rap_app*
0159 rtems_rap_app_alloc (void)
0160 {
0161 rtems_rap_app* app = malloc (sizeof (rtems_rap_app));
0162 memset (app, 0, sizeof (rtems_rap_app));
0163 rtems_chain_append (&rap_.apps, &app->node);
0164 return app;
0165 }
0166
0167 static void
0168 rtems_rap_app_free (rtems_rap_app* app)
0169 {
0170 if (app->handle)
0171 {
0172 dlclose (app->handle);
0173 app->handle = NULL;
0174 }
0175
0176 if (!rtems_chain_is_node_off_chain (&app->node))
0177 rtems_chain_extract (&app->node);
0178 }
0179
0180 static bool
0181 rtems_rap_match_name (rtems_rap_app* app, const char* name)
0182 {
0183 const char* a;
0184
0185
0186
0187
0188
0189
0190 if (strncmp (app->name, name, strlen (name)) == 0)
0191 return true;
0192
0193 a = app->name + strlen (app->name) - 1;
0194
0195 while (a >= app->name)
0196 {
0197 if (rtems_filesystem_is_delimiter (*a))
0198 {
0199 const char* n = name;
0200
0201 ++a;
0202
0203 while (*a && *n)
0204 {
0205 if (*a == '.')
0206 {
0207 if (*n == '\0')
0208 return true;
0209 }
0210
0211 ++a;
0212 ++n;
0213 }
0214
0215 return false;
0216 }
0217
0218 --a;
0219 }
0220
0221 return false;
0222 }
0223
0224 static void
0225 rtems_rap_get_rtl_error (void)
0226 {
0227 rap_.last_errno =
0228 rtems_rtl_get_error (rap_.last_error, sizeof (rap_.last_error));
0229 }
0230
0231 static void
0232 rtems_rap_set_error (int error, const char* format, ...)
0233 {
0234 rtems_rap_data* rap = rtems_rap_lock ();
0235 va_list ap;
0236 va_start (ap, format);
0237 rap->last_errno = error;
0238 vsnprintf (rap->last_error, sizeof (rap->last_error), format, ap);
0239 rtems_rap_unlock ();
0240 va_end (ap);
0241 }
0242
0243 bool
0244 rtems_rap_load (const char* name, int mode, int argc, const char* argv[])
0245 {
0246 rtems_rap_data* rap = rtems_rap_lock ();
0247
0248 if (!rap)
0249 return false;
0250
0251 if (rap_verbose)
0252 printf ("rap: loading '%s'\n", name);
0253
0254
0255
0256
0257 if (!rtems_rap_find (name))
0258 {
0259 rtems_rap_app* app;
0260 rtems_rap_entry init;
0261 rtems_rap_entry fini;
0262 size_t size = 0;
0263 int r;
0264
0265
0266
0267
0268 app = rtems_rap_app_alloc ();
0269 if (app == NULL)
0270 {
0271 rtems_rap_set_error (ENOMEM, "no memory for application");
0272 rtems_rap_unlock ();
0273 return false;
0274 }
0275
0276
0277
0278
0279 if (!rtems_rtl_find_file (name, getenv ("PATH"), &app->name, &size))
0280 {
0281 rtems_rap_set_error (ENOENT, "file not found");
0282 rtems_rap_app_free (app);
0283 rtems_rap_unlock ();
0284 return false;
0285 }
0286
0287 app->handle = dlopen (app->name, RTLD_NOW | mode);
0288 if (!app->handle)
0289 {
0290 rtems_rap_get_rtl_error ();
0291 rtems_rap_app_free (app);
0292 rtems_rap_unlock ();
0293 return false;
0294 }
0295
0296 init = dlsym (app->handle, RTL_ENTRY_POINT);
0297 if (!init)
0298 {
0299 rtems_rap_get_rtl_error ();
0300 rtems_rap_app_free (app);
0301 rtems_rap_unlock ();
0302 return false;
0303 }
0304
0305 fini = dlsym (app->handle, RTL_ENTRY_POINT);
0306 if (!fini)
0307 {
0308 rtems_rap_get_rtl_error ();
0309 rtems_rap_app_free (app);
0310 rtems_rap_unlock ();
0311 return false;
0312 }
0313
0314 r = init (argc, argv);
0315 if (r != 0)
0316 {
0317 rtems_rap_set_error (r, "init call failure");
0318 rtems_rap_app_free (app);
0319 rtems_rap_unlock ();
0320 return false;
0321 }
0322 }
0323
0324 rtems_rap_unlock ();
0325
0326 return true;
0327 }
0328
0329 bool
0330 rtems_rap_unload (const char* name)
0331 {
0332 rtems_rap_app* app;
0333 rtems_rap_entry fini;
0334 int r;
0335
0336 rtems_rap_lock ();
0337
0338 app = rtems_rap_find (name);
0339
0340 if (rap_verbose)
0341 printf ("rap: unloading '%s'\n", name);
0342
0343 if (!app)
0344 {
0345 rtems_rap_set_error (ENOENT, "invalid handle");
0346 rtems_rap_unlock ();
0347 return false;
0348 }
0349
0350 fini = dlsym (app->handle, RTL_ENTRY_POINT);
0351 if (!fini)
0352 {
0353 rtems_rap_get_rtl_error ();
0354 rtems_rap_unlock ();
0355 return false;
0356 }
0357
0358 r = fini (0, NULL);
0359 if (r != 0)
0360 {
0361 rtems_rap_set_error (r, "fini failure");
0362 rtems_rap_unlock ();
0363 return false;
0364 }
0365
0366 rtems_rap_app_free (app);
0367 rtems_rap_unlock ();
0368
0369 return true;
0370 }
0371
0372 void*
0373 rtems_rap_find (const char* name)
0374 {
0375 rtems_rap_data* rap = rtems_rap_lock ();
0376 rtems_chain_node* node;
0377
0378 node = rtems_chain_first (&rap->apps);
0379
0380 while (!rtems_chain_is_tail (&rap->apps, node))
0381 {
0382 rtems_rap_app* app = (rtems_rap_app*) node;
0383 if (rtems_rap_match_name (app, name))
0384 {
0385 rtems_rap_unlock ();
0386 return app;
0387 }
0388 node = rtems_chain_next (node);
0389 }
0390
0391 rtems_rap_unlock ();
0392
0393 return NULL;
0394 }
0395
0396 bool
0397 rtems_rap_iterate (rtems_rap_iterator iterator)
0398 {
0399 rtems_rap_data* rap = rtems_rap_lock ();
0400 rtems_chain_node* node;
0401 bool result = true;
0402
0403 node = rtems_chain_first (&rap->apps);
0404
0405 while (!rtems_chain_is_tail (&rap->apps, node))
0406 {
0407 rtems_rap_app* app = (rtems_rap_app*) node;
0408 result = iterator (app);
0409 if (!result)
0410 break;
0411 node = rtems_chain_next (node);
0412 }
0413
0414 rtems_rap_unlock ();
0415
0416 return result;
0417 }
0418
0419 const char*
0420 rtems_rap_name (void* handle)
0421 {
0422 rtems_rap_app* app = rtems_rap_check_handle (handle);
0423 if (app)
0424 return app->name;
0425 return NULL;
0426 }
0427
0428 void*
0429 rtems_rap_dl_handle (void* handle)
0430 {
0431 rtems_rap_app* app = rtems_rap_check_handle (handle);
0432 if (app)
0433 return app->handle;
0434 return NULL;
0435 }
0436
0437 int
0438 rtems_rap_get_error (char* message, size_t max_message)
0439 {
0440 rtems_rap_data* rap = rtems_rap_lock ();
0441 int last_errno = rap->last_errno;
0442 strlcpy (message, rap->last_error, max_message);
0443 rtems_rap_unlock ();
0444 return last_errno;
0445 }