#define _GNU_SOURCE #include #include #include #include #include #include static void fail(const char *message) { fprintf(stderr, "embedded PostgreSQL launcher: %s\n", message); exit(127); } static void join_path(char *destination, size_t capacity, const char *left, const char *right) { int length = snprintf(destination, capacity, "%s/%s", left, right); if (length < 0 || (size_t) length >= capacity) fail("installation path is too long"); } int main(int argc, char **argv) { char executable[PATH_MAX]; ssize_t executable_length = readlink("/proc/self/exe", executable, sizeof(executable) - 1); if (executable_length < 0) { perror("embedded PostgreSQL launcher: /proc/self/exe"); return 127; } executable[executable_length] = '\0'; char *tool = strrchr(executable, '/'); if (tool == NULL || tool[1] == '\0') fail("cannot determine the requested PostgreSQL tool"); tool++; char root[PATH_MAX]; if ((size_t) executable_length >= sizeof(root)) fail("installation path is too long"); memcpy(root, executable, (size_t) executable_length + 1); char *bin_separator = strrchr(root, '/'); if (bin_separator == NULL) fail("cannot determine the PostgreSQL installation directory"); *bin_separator = '\0'; char *root_separator = strrchr(root, '/'); if (root_separator == NULL) fail("cannot determine the PostgreSQL installation directory"); *root_separator = '\0'; char loader[PATH_MAX]; char library_path[PATH_MAX]; char real_tool[PATH_MAX]; join_path(loader, sizeof(loader), root, "lib/ld-musl-x86_64.so.1"); join_path(library_path, sizeof(library_path), root, "lib"); char real_tool_relative[PATH_MAX]; int relative_length = snprintf( real_tool_relative, sizeof(real_tool_relative), "libexec/%s", tool ); if (relative_length < 0 || (size_t) relative_length >= sizeof(real_tool_relative)) fail("tool path is too long"); join_path(real_tool, sizeof(real_tool), root, real_tool_relative); char **loader_argv = calloc((size_t) argc + 6, sizeof(char *)); if (loader_argv == NULL) { perror("embedded PostgreSQL launcher: calloc"); return 127; } loader_argv[0] = loader; loader_argv[1] = "--library-path"; loader_argv[2] = library_path; loader_argv[3] = "--argv0"; loader_argv[4] = executable; loader_argv[5] = real_tool; for (int index = 1; index < argc; index++) loader_argv[index + 5] = argv[index]; execv(loader, loader_argv); fprintf( stderr, "embedded PostgreSQL launcher: cannot execute %s: %s\n", real_tool, strerror(errno) ); return 127; }