1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4
5//
6// A simple CoreCLR host that runs a managed binary with the same name as this executable but with the *.dll extension
7// The dll binary must contain a main entry point.
8//
9
10#include <coreruncommon.h>
11#include <string>
12#include <string.h>
13#include <sys/stat.h>
14
15// Display the help text
16void DisplayUsage()
17{
18 fprintf(
19 stderr,
20 "Runs executables on CoreCLR\n\n"
21 "Usage: <program> [OPTIONS] [ARGUMENTS]\n"
22 "Runs <program>.dll on CoreCLR.\n\n"
23 "Options:\n"
24 "-_c path to libcoreclr.so and the managed CLR assemblies.\n"
25 "-_h show this help message. \n");
26}
27
28// Parse the command line arguments
29bool ParseArguments(
30 const int argc,
31 const char* argv[],
32 const char** clrFilesPath,
33 int* managedAssemblyArgc,
34 const char*** managedAssemblyArgv)
35{
36 bool success = true;
37
38 *clrFilesPath = nullptr;
39 *managedAssemblyArgv = nullptr;
40 *managedAssemblyArgc = 0;
41
42 for (int i = 1; i < argc; i++)
43 {
44 // Check for options. Options to the Unix coreconsole are prefixed with '-_' to match the convention
45 // used in the Windows version of coreconsole.
46 if (strncmp(argv[i], "-_", 2) == 0)
47 {
48 // Path to the libcoreclr.so and the managed CLR assemblies
49 if (strcmp(argv[i], "-_c") == 0)
50 {
51 i++;
52 if (i < argc)
53 {
54 *clrFilesPath = argv[i];
55 }
56 else
57 {
58 fprintf(stderr, "Option %s: missing path\n", argv[i - 1]);
59 success = false;
60 break;
61 }
62 }
63 else if (strcmp(argv[i], "-_h") == 0)
64 {
65 DisplayUsage();
66 success = false;
67 break;
68 }
69 else
70 {
71 fprintf(stderr, "Unknown option %s\n", argv[i]);
72 success = false;
73 break;
74 }
75 }
76 else
77 {
78 // We treat everything starting from the first non-option argument as arguments
79 // to the managed assembly.
80 *managedAssemblyArgc = argc - i;
81 if (*managedAssemblyArgc != 0)
82 {
83 *managedAssemblyArgv = &argv[i];
84 }
85
86 break;
87 }
88 }
89
90 return success;
91}
92
93int main(const int argc, const char* argv[])
94{
95 // Make sure we have a full path for argv[0].
96 std::string entryPointExecutablePath;
97
98 if (!GetEntrypointExecutableAbsolutePath(entryPointExecutablePath))
99 {
100 perror("Could not get full path to current executable");
101 return -1;
102 }
103
104 // We will try to load the managed assembly with the same name as this executable
105 // but with the .dll extension.
106 std::string programPath(entryPointExecutablePath);
107 programPath.append(".dll");
108 const char* managedAssemblyAbsolutePath = programPath.c_str();
109
110 // Check if the specified managed assembly file exists
111 struct stat sb;
112 if (stat(managedAssemblyAbsolutePath, &sb) == -1)
113 {
114 perror("Managed assembly not found");
115 return -1;
116 }
117
118 // Verify that the managed assembly path points to a file
119 if (!S_ISREG(sb.st_mode))
120 {
121 fprintf(stderr, "The specified managed assembly is not a file\n");
122 return -1;
123 }
124
125 const char* clrFilesPath;
126 const char** managedAssemblyArgv;
127 int managedAssemblyArgc;
128
129 if (!ParseArguments(
130 argc,
131 argv,
132 &clrFilesPath,
133 &managedAssemblyArgc,
134 &managedAssemblyArgv
135 ))
136 {
137 // Invalid command line
138 return -1;
139 }
140
141 std::string clrFilesAbsolutePath;
142 if(!GetClrFilesAbsolutePath(entryPointExecutablePath.c_str(), clrFilesPath, clrFilesAbsolutePath))
143 {
144 return -1;
145 }
146
147 int exitCode = ExecuteManagedAssembly(
148 entryPointExecutablePath.c_str(),
149 clrFilesAbsolutePath.c_str(),
150 managedAssemblyAbsolutePath,
151 managedAssemblyArgc,
152 managedAssemblyArgv);
153
154 return exitCode;
155}
156