Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
c985d08e
Commit
c985d08e
authored
Jul 25, 2013
by
Vinay Sajip
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Closes #18491: Added script-wrapper functionality to launcher source (but not to executable).
parent
7c8cd257
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
138 additions
and
34 deletions
+138
-34
PC/launcher.c
PC/launcher.c
+138
-34
No files found.
PC/launcher.c
View file @
c985d08e
...
...
@@ -20,6 +20,27 @@
#define SKIP_PREFIX
#define SEARCH_PATH
/* Error codes */
#define RC_NO_STD_HANDLES 100
#define RC_CREATE_PROCESS 101
#define RC_BAD_VIRTUAL_PATH 102
#define RC_NO_PYTHON 103
#define RC_NO_MEMORY 104
/*
* SCRIPT_WRAPPER is used to choose between two variants of an executable built
* from this source file. If not defined, the PEP 397 Python launcher is built;
* if defined, a script launcher of the type used by setuptools is built, which
* looks for a script name related to the executable name and runs that script
* with the appropriate Python interpreter.
*
* SCRIPT_WRAPPER should be undefined in the source, and defined in a VS project
* which builds the setuptools-style launcher.
*/
#if defined(SCRIPT_WRAPPER)
#define RC_NO_SCRIPT 105
#endif
/* Just for now - static definition */
static
FILE
*
log_fp
=
NULL
;
...
...
@@ -32,32 +53,6 @@ skip_whitespace(wchar_t * p)
return
p
;
}
/*
* This function is here to simplify memory management
* and to treat blank values as if they are absent.
*/
static
wchar_t
*
get_env
(
wchar_t
*
key
)
{
/* This is not thread-safe, just like getenv */
static
wchar_t
buf
[
256
];
DWORD
result
=
GetEnvironmentVariableW
(
key
,
buf
,
256
);
if
(
result
>
255
)
{
/* Large environment variable. Accept some leakage */
wchar_t
*
buf2
=
(
wchar_t
*
)
malloc
(
sizeof
(
wchar_t
)
*
(
result
+
1
));
GetEnvironmentVariableW
(
key
,
buf2
,
result
);
return
buf2
;
}
if
(
result
==
0
)
/* Either some error, e.g. ERROR_ENVVAR_NOT_FOUND,
or an empty environment variable. */
return
NULL
;
return
buf
;
}
static
void
debug
(
wchar_t
*
format
,
...)
{
...
...
@@ -100,11 +95,40 @@ error(int rc, wchar_t * format, ... )
#if !defined(_WINDOWS)
fwprintf
(
stderr
,
L"%s
\n
"
,
message
);
#else
MessageBox
(
NULL
,
message
,
TEXT
(
"Python Launcher is sorry to say ..."
),
MB_OK
);
MessageBox
(
NULL
,
message
,
TEXT
(
"Python Launcher is sorry to say ..."
),
MB_OK
);
#endif
ExitProcess
(
rc
);
}
/*
* This function is here to simplify memory management
* and to treat blank values as if they are absent.
*/
static
wchar_t
*
get_env
(
wchar_t
*
key
)
{
/* This is not thread-safe, just like getenv */
static
wchar_t
buf
[
BUFSIZE
];
DWORD
result
=
GetEnvironmentVariableW
(
key
,
buf
,
BUFSIZE
);
if
(
result
>=
BUFSIZE
)
{
/* Large environment variable. Accept some leakage */
wchar_t
*
buf2
=
(
wchar_t
*
)
malloc
(
sizeof
(
wchar_t
)
*
(
result
+
1
));
if
(
buf2
=
NULL
)
{
error
(
RC_NO_MEMORY
,
L"Could not allocate environment buffer"
);
}
GetEnvironmentVariableW
(
key
,
buf2
,
result
);
return
buf2
;
}
if
(
result
==
0
)
/* Either some error, e.g. ERROR_ENVVAR_NOT_FOUND,
or an empty environment variable. */
return
NULL
;
return
buf
;
}
#if defined(_WINDOWS)
#define PYTHON_EXECUTABLE L"pythonw.exe"
...
...
@@ -115,11 +139,6 @@ error(int rc, wchar_t * format, ... )
#endif
#define RC_NO_STD_HANDLES 100
#define RC_CREATE_PROCESS 101
#define RC_BAD_VIRTUAL_PATH 102
#define RC_NO_PYTHON 103
#define MAX_VERSION_SIZE 4
typedef
struct
{
...
...
@@ -457,6 +476,51 @@ locate_python(wchar_t * wanted_ver)
return
result
;
}
#if defined(SCRIPT_WRAPPER)
/*
* Check for a script located alongside the executable
*/
#if defined(_WINDOWS)
#define SCRIPT_SUFFIX L"-script.pyw"
#else
#define SCRIPT_SUFFIX L"-script.py"
#endif
static
wchar_t
wrapped_script_path
[
MAX_PATH
];
/* Locate the script being wrapped.
*
* This code should store the name of the wrapped script in
* wrapped_script_path, or terminate the program with an error if there is no
* valid wrapped script file.
*/
static
void
locate_wrapped_script
()
{
wchar_t
*
p
;
size_t
plen
;
DWORD
attrs
;
plen
=
GetModuleFileNameW
(
NULL
,
wrapped_script_path
,
MAX_PATH
);
p
=
wcsrchr
(
wrapped_script_path
,
L'.'
);
if
(
p
==
NULL
)
{
debug
(
L"GetModuleFileNameW returned value has no extension: %s
\n
"
,
wrapped_script_path
);
error
(
RC_NO_SCRIPT
,
L"Wrapper name '%s' is not valid."
,
wrapped_script_path
);
}
wcsncpy_s
(
p
,
MAX_PATH
-
(
p
-
wrapped_script_path
)
+
1
,
SCRIPT_SUFFIX
,
_TRUNCATE
);
attrs
=
GetFileAttributesW
(
wrapped_script_path
);
if
(
attrs
==
INVALID_FILE_ATTRIBUTES
)
{
debug
(
L"File '%s' non-existent
\n
"
,
wrapped_script_path
);
error
(
RC_NO_SCRIPT
,
L"Script file '%s' is not present."
,
wrapped_script_path
);
}
debug
(
L"Using wrapped script file '%s'
\n
"
,
wrapped_script_path
);
}
#endif
/*
* Process creation code
*/
...
...
@@ -863,7 +927,7 @@ typedef struct {
}
BOM
;
/*
* Strictly, we don't need to handle UTF-16 an
f
UTF-32, since Python itself
* Strictly, we don't need to handle UTF-16 an
d
UTF-32, since Python itself
* doesn't. Never mind, one day it might - there's no harm leaving it in.
*/
static
BOM
BOMs
[]
=
{
...
...
@@ -1250,6 +1314,11 @@ process(int argc, wchar_t ** argv)
VS_FIXEDFILEINFO
*
file_info
;
UINT
block_size
;
int
index
;
#if defined(SCRIPT_WRAPPER)
int
newlen
;
wchar_t
*
newcommand
;
wchar_t
*
av
[
2
];
#endif
wp
=
get_env
(
L"PYLAUNCH_DEBUG"
);
if
((
wp
!=
NULL
)
&&
(
*
wp
!=
L'\0'
))
...
...
@@ -1329,7 +1398,40 @@ process(int argc, wchar_t ** argv)
}
command
=
skip_me
(
GetCommandLineW
());
debug
(
L"Called with command line: %s"
,
command
);
debug
(
L"Called with command line: %s
\n
"
,
command
);
#if defined(SCRIPT_WRAPPER)
/* The launcher is being used in "script wrapper" mode.
* There should therefore be a Python script named <exename>-script.py in
* the same directory as the launcher executable.
* Put the script name into argv as the first (script name) argument.
*/
/* Get the wrapped script name - if the script is not present, this will
* terminate the program with an error.
*/
locate_wrapped_script
();
/* Add the wrapped script to the start of command */
newlen
=
wcslen
(
wrapped_script_path
)
+
wcslen
(
command
)
+
2
;
/* ' ' + NUL */
newcommand
=
malloc
(
sizeof
(
wchar_t
)
*
newlen
);
if
(
!
newcommand
)
{
error
(
RC_NO_MEMORY
,
L"Could not allocate new command line"
);
}
else
{
wcscpy_s
(
newcommand
,
newlen
,
wrapped_script_path
);
wcscat_s
(
newcommand
,
newlen
,
L" "
);
wcscat_s
(
newcommand
,
newlen
,
command
);
debug
(
L"Running wrapped script with command line '%s'
\n
"
,
newcommand
);
read_commands
();
av
[
0
]
=
wrapped_script_path
;
av
[
1
]
=
NULL
;
maybe_handle_shebang
(
av
,
newcommand
);
/* Returns if no shebang line - pass to default processing */
command
=
newcommand
;
valid
=
FALSE
;
}
#else
if
(
argc
<=
1
)
{
valid
=
FALSE
;
p
=
NULL
;
...
...
@@ -1357,6 +1459,8 @@ installed", &p[1]);
}
}
}
#endif
if
(
!
valid
)
{
ip
=
locate_python
(
L""
);
if
(
ip
==
NULL
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment