13 # include <sys/sysctl.h> 17 # include <mach-o/dyld.h> 25 #if PY_MAJOR_VERSION >= 3 28 # if PY_MINOR_VERSION < 5 29 # define Py_DecodeLocale _Py_char2wchar 35 #define MAX_NUM_POINTERS 24 46 __attribute__((__visibility__(
"default"), used))
52 uint16_t num_pointers;
56 void *pointers[MAX_NUM_POINTERS];
60 } blobinfo = {(uint64_t)-1};
63 # define WIN32_LEAN_AND_MEAN 66 extern void PyWinFreeze_ExeInit(
void);
67 extern void PyWinFreeze_ExeTerm(
void);
69 static struct _inittab extensions[] = {
73 #if PY_MAJOR_VERSION >= 3 78 #if defined(_WIN32) && PY_VERSION_HEX < 0x03060000 79 static int supports_code_page(UINT cp) {
86 if (cp != 0 && cp != 1252 && cp != 367 && cp != 437 && cp != 850 && cp != 819) {
87 const struct _frozen *moddef;
92 PyOS_snprintf(codec,
sizeof(codec),
"encodings.cp%u", (
unsigned int)cp);
94 moddef = PyImport_FrozenModules;
95 while (moddef->name) {
96 if (strcmp(moddef->name, codec) == 0) {
112 static void set_main_dir(
char *main_dir) {
113 if (blobinfo.num_pointers >= 10) {
114 if (blobinfo.num_pointers == 10) {
115 ++blobinfo.num_pointers;
116 blobinfo.pointers[10] = NULL;
118 if (blobinfo.pointers[10] == NULL) {
119 blobinfo.pointers[10] = main_dir;
128 static int mkdir_parent(
const wchar_t *path) {
130 wchar_t buffer[4096];
131 size_t buflen = wcslen(path);
132 if (buflen + 1 >= _countof(buffer)) {
135 wcscpy_s(buffer, _countof(buffer), path);
138 while (buflen-- > 0) {
139 if (buffer[buflen] ==
'/' || buffer[buflen] ==
'\\') {
144 if (buflen == (
size_t)-1 || buflen == 0) {
149 if (CreateDirectoryW(buffer, NULL) != 0) {
155 DWORD last_error = GetLastError();
156 if (last_error == ERROR_ALREADY_EXISTS) {
161 if (last_error == ERROR_PATH_NOT_FOUND) {
163 if (mkdir_parent(buffer)) {
165 if (CreateDirectoryW(buffer, NULL) != 0) {
174 static int mkdir_parent(
const char *path) {
177 size_t buflen = strlen(path);
178 if (buflen + 1 >=
sizeof(buffer)) {
181 strcpy(buffer, path);
184 while (buflen-- > 0) {
185 if (buffer[buflen] ==
'/') {
190 if (buflen == (
size_t)-1 || buflen == 0) {
194 if (mkdir(buffer, 0755) == 0) {
200 if (errno == EEXIST) {
205 if (errno == ENOENT || errno == EACCES) {
207 if (mkdir_parent(buffer)) {
209 if (mkdir(buffer, 0755) == 0) {
225 static int setup_logging(
const char *path,
int append) {
228 wchar_t pathw[MAX_PATH * 2];
230 if (path[0] ==
'~' && (path[1] == 0 || path[1] ==
'/' || path[1] ==
'\\')) {
235 if (!SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_PROFILE, NULL, 0, pathw))) {
238 offset = wcslen(pathw);
242 if (MultiByteToWideChar(CP_UTF8, 0, path, -1, pathw + offset,
243 (
int)(_countof(pathw) - offset)) == 0) {
247 DWORD access = append ? FILE_APPEND_DATA : (GENERIC_READ | GENERIC_WRITE);
248 int creation = append ? OPEN_ALWAYS : CREATE_ALWAYS;
249 HANDLE handle = CreateFileW(pathw, access, FILE_SHARE_DELETE | FILE_SHARE_READ,
250 NULL, creation, FILE_ATTRIBUTE_NORMAL, NULL);
252 if (handle == INVALID_HANDLE_VALUE) {
255 handle = CreateFileW(pathw, access, FILE_SHARE_DELETE | FILE_SHARE_READ,
256 NULL, creation, FILE_ATTRIBUTE_NORMAL, NULL);
259 if (handle == INVALID_HANDLE_VALUE) {
264 SetFilePointer(handle, 0, NULL, FILE_END);
267 SetStdHandle(STD_OUTPUT_HANDLE, handle);
268 SetStdHandle(STD_ERROR_HANDLE, handle);
273 if (_fileno(stdout) < 0) {
275 _wfreopen(L
"\\\\.\\NUL", L
"w", stdout);
278 if (_fileno(stderr) < 0) {
280 _wfreopen(L
"\\\\.\\NUL", L
"w", stderr);
285 int fd = _open_osfhandle((intptr_t)handle, _O_WRONLY | _O_TEXT | (append ? _O_APPEND : 0));
286 _dup2(fd, _fileno(stdout));
287 _dup2(fd, _fileno(stderr));
293 char buffer[PATH_MAX * 2];
295 if (path[0] ==
'~' && (path[1] == 0 || path[1] ==
'/')) {
300 const char *home_dir = getenv(
"HOME");
301 if (home_dir == NULL) {
302 home_dir = getpwuid(getuid())->pw_dir;
304 offset = strlen(home_dir);
305 assert(offset <
sizeof(buffer));
306 strncpy(buffer, home_dir,
sizeof(buffer));
310 strcpy(buffer + offset, path);
312 mode_t mode = O_CREAT | O_WRONLY | (append ? O_APPEND : O_TRUNC);
313 int fd = open(buffer, mode, 0644);
316 mkdir_parent(buffer);
317 fd = open(buffer, mode, 0644);
339 int Py_FrozenMain(
int argc,
wchar_t **argv)
341 int Py_FrozenMain(
int argc,
char **argv)
349 #if PY_MAJOR_VERSION >= 3 && !defined(WIN_UNICODE) 352 wchar_t **argv_copy = NULL;
354 wchar_t **argv_copy2 = NULL;
357 argv_copy = (
wchar_t **)alloca(
sizeof(
wchar_t *) * argc);
358 argv_copy2 = (
wchar_t **)alloca(
sizeof(
wchar_t *) * argc);
362 #if defined(MS_WINDOWS) && PY_VERSION_HEX >= 0x03040000 && PY_VERSION_HEX < 0x03060000 363 if (!supports_code_page(GetConsoleOutputCP()) ||
364 !supports_code_page(GetConsoleCP())) {
370 SetConsoleOutputCP(acp);
371 Py_SetStandardStreamEncoding(
"mbcs", NULL);
377 Py_NoUserSiteDirectory = 1;
379 if ((p = Py_GETENV(
"PYTHONINSPECT")) && *p !=
'\0')
381 if ((p = Py_GETENV(
"PYTHONUNBUFFERED")) && *p !=
'\0')
385 setbuf(stdin, (
char *)NULL);
386 setbuf(stdout, (
char *)NULL);
387 setbuf(stderr, (
char *)NULL);
390 #if PY_MAJOR_VERSION >= 3 && !defined(WIN_UNICODE) 391 oldloc = setlocale(LC_ALL, NULL);
392 setlocale(LC_ALL,
"");
393 for (i = 0; i < argc; i++) {
394 argv_copy[i] = Py_DecodeLocale(argv[i], NULL);
395 argv_copy2[i] = argv_copy[i];
397 fprintf(stderr,
"Unable to decode the command line argument #%i\n",
403 setlocale(LC_ALL, oldloc);
407 PyImport_ExtendInittab(extensions);
411 #if PY_MAJOR_VERSION >= 3 && !defined(WIN_UNICODE) 412 Py_SetProgramName(argv_copy[0]);
414 Py_SetProgramName(argv[0]);
420 PyWinFreeze_ExeInit();
423 #if defined(MS_WINDOWS) && PY_VERSION_HEX < 0x03040000 424 if (!supports_code_page(GetConsoleOutputCP()) ||
425 !supports_code_page(GetConsoleCP())) {
430 PyObject *sys_stream;
433 SetConsoleOutputCP(acp);
435 sys_stream = PySys_GetObject(
"stdin");
436 if (sys_stream && PyFile_Check(sys_stream)) {
437 PyFile_SetEncodingAndErrors(sys_stream,
"mbcs", NULL);
439 sys_stream = PySys_GetObject(
"stdout");
440 if (sys_stream && PyFile_Check(sys_stream)) {
441 PyFile_SetEncodingAndErrors(sys_stream,
"mbcs", NULL);
443 sys_stream = PySys_GetObject(
"stderr");
444 if (sys_stream && PyFile_Check(sys_stream)) {
445 PyFile_SetEncodingAndErrors(sys_stream,
"mbcs", NULL);
451 fprintf(stderr,
"Python %s\n%s\n",
452 Py_GetVersion(), Py_GetCopyright());
454 #if PY_MAJOR_VERSION >= 3 && !defined(WIN_UNICODE) 455 PySys_SetArgv(argc, argv_copy);
457 PySys_SetArgv(argc, argv);
460 #ifdef MACOS_APP_BUNDLE 462 char buffer[PATH_MAX];
463 uint32_t bufsize =
sizeof(buffer);
464 if (_NSGetExecutablePath(buffer, &bufsize) != 0) {
468 char resolved[PATH_MAX];
469 if (!realpath(buffer, resolved)) {
473 const char *dir = dirname(resolved);
474 sprintf(buffer,
"%s/../Frameworks", dir);
476 PyObject *sys_path = PyList_New(1);
477 #if PY_MAJOR_VERSION >= 3 478 PyList_SET_ITEM(sys_path, 0, PyUnicode_FromString(buffer));
480 PyList_SET_ITEM(sys_path, 0, PyString_FromString(buffer));
482 PySys_SetObject(
"path", sys_path);
487 sprintf(buffer,
"%s/../Resources", dir);
488 set_main_dir(buffer);
491 n = PyImport_ImportFrozenModule(
"__main__");
493 Py_FatalError(
"__main__ not frozen");
501 if (inspect && isatty((
int)fileno(stdin)))
502 sts = PyRun_AnyFile(stdin,
"<stdin>") != 0;
505 PyWinFreeze_ExeTerm();
509 #if PY_MAJOR_VERSION >= 3 && !defined(WIN_UNICODE) 512 for (i = 0; i < argc; i++) {
513 #if PY_MINOR_VERSION >= 4 514 PyMem_RawFree(argv_copy2[i]);
516 PyMem_Free(argv_copy2[i]);
528 static void *map_blob(off_t offset,
size_t size) {
533 wchar_t buffer[2048];
534 GetModuleFileNameW(NULL, buffer, 2048);
535 runtime = _wfopen(buffer, L
"rb");
536 #elif defined(__FreeBSD__) 537 size_t bufsize = 4096;
539 int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
541 if (sysctl(mib, 4, (
void *)buffer, &bufsize, NULL, 0) == -1) {
545 runtime = fopen(buffer,
"rb");
546 #elif defined(__APPLE__) 548 uint32_t bufsize =
sizeof(buffer);
549 if (_NSGetExecutablePath(buffer, &bufsize) != 0) {
552 runtime = fopen(buffer,
"rb");
555 ssize_t pathlen = readlink(
"/proc/self/exe", buffer,
sizeof(buffer) - 1);
557 perror(
"readlink(/proc/self/exe)");
560 buffer[pathlen] =
'\0';
561 runtime = fopen(buffer,
"rb");
565 if (blobinfo.version == 0) {
567 fseek(runtime, -8, SEEK_END);
568 end = ftell(runtime);
569 fread(&begin, 8, 1, runtime);
571 offset = (off_t)begin;
572 size = (size_t)(end - begin);
577 blob = (
void *)malloc(size);
578 assert(blob != NULL);
579 fseek(runtime, (
long)offset, SEEK_SET);
580 fread(blob, size, 1, runtime);
582 blob = (
void *)mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fileno(runtime), offset);
583 assert(blob != MAP_FAILED);
593 static void unmap_blob(
void *blob) {
598 munmap(blob, blobinfo.blob_size);
606 #if defined(_WIN32) && PY_MAJOR_VERSION >= 3 607 int wmain(
int argc,
wchar_t *argv[]) {
609 int main(
int argc,
char *argv[]) {
612 struct _frozen *moddef;
613 const char *log_filename;
628 if (blobinfo.version == 0 || blobinfo.blob_offset != 0) {
629 void *blob = map_blob((off_t)blobinfo.blob_offset, (
size_t)blobinfo.blob_size);
630 assert(blob != NULL);
633 if (blobinfo.version > 0 && blobinfo.num_pointers > 0) {
635 assert(blobinfo.num_pointers <= MAX_NUM_POINTERS);
636 for (i = 0; i < blobinfo.num_pointers; ++i) {
640 if (i == 0 || blobinfo.pointers[i] != 0) {
641 blobinfo.pointers[i] = (
void *)((uintptr_t)blobinfo.pointers[i] + (uintptr_t)blob);
644 if (blobinfo.num_pointers >= 12) {
645 log_filename = blobinfo.pointers[11];
648 blobinfo.pointers[0] = blob;
652 moddef = blobinfo.pointers[0];
653 while (moddef->name) {
654 moddef->name = (
char *)((uintptr_t)moddef->name + (uintptr_t)blob);
655 if (moddef->code != 0) {
656 moddef->code = (
unsigned char *)((uintptr_t)moddef->code + (uintptr_t)blob);
663 if (log_filename != NULL) {
664 setup_logging(log_filename, (blobinfo.flags & F_log_append) != 0);
668 if (blobinfo.codepage != 0) {
669 SetConsoleCP(blobinfo.codepage);
670 SetConsoleOutputCP(blobinfo.codepage);
675 PyImport_FrozenModules = blobinfo.pointers[0];
676 retval = Py_FrozenMain(argc, argv);
683 int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
wchar_t *lpCmdLine,
int nCmdShow) {
684 return wmain(__argc, __wargv);
686 #elif defined(_WIN32) 687 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
char *lpCmdLine,
int nCmdShow) {
688 return main(__argc, __argv);