summaryrefslogtreecommitdiff
path: root/launcher.c
diff options
context:
space:
mode:
authorJim Fulton <distutils-sig@python.org>2006-08-22 19:58:05 +0000
committerJim Fulton <distutils-sig@python.org>2006-08-22 19:58:05 +0000
commitcd84d4b5eb8113b416f6cb080b3445799ed2ff99 (patch)
tree5dbdd13cbb5d1ed57d237bd7b4567e7a75c735fc /launcher.c
parentf744be10b9702c1056fda2e18cfa9e8cb99d331a (diff)
downloadpython-setuptools-git-cd84d4b5eb8113b416f6cb080b3445799ed2ff99.tar.gz
Added quoting of script arguments and extended the quoting logic to
handle embedded quotes. Added support for passing a single argument on the shebang line to pass things like -O and -i. Fixed bug in handling trailing whitespace in Python command. --HG-- branch : setuptools-0.6 extra : convert_revision : svn%3A6015fed2-1504-0410-9fe1-9d1591cc4771/sandbox/branches/setuptools-0.6%4051487
Diffstat (limited to 'launcher.c')
-rwxr-xr-xlauncher.c88
1 files changed, 78 insertions, 10 deletions
diff --git a/launcher.c b/launcher.c
index 1bb1097f..79dbbbd4 100755
--- a/launcher.c
+++ b/launcher.c
@@ -33,22 +33,80 @@ int fail(char *format, char *data) {
fprintf(stderr, format, data);
return 2;
}
+
char *quoted(char *data) {
- char *result = calloc(strlen(data)+3,sizeof(char));
- strcat(result,"\""); strcat(result,data); strcat(result,"\"");
+ int i, l = strlen(data), nb;
+ /* We allocate twice as much space as needed to deal with worse-case
+ of having to escape everything. */
+ char *result = calloc(l*2+3, sizeof(char));
+ char *presult = result;
+
+ *presult++ = '"';
+ for (nb=0, i=0; i < l; i++)
+ {
+ if (data[i] == '\\')
+ nb += 1;
+ else if (data[i] == '"')
+ {
+ for (; nb > 0; nb--)
+ *presult++ = '\\';
+ *presult++ = '\\';
+ }
+ else
+ nb = 0;
+ *presult++ = data[i];
+ }
+ for (; nb > 0; nb--) /* Deal w trailing slashes */
+ *presult++ = '\\';
+
+ *presult++ = '"';
+ *presult++ = 0;
return result;
}
+char *getpyopt(char *python)
+{
+ /* Search a Python command string, read from a #! line for an
+ option. An option must be separated from an executable name by
+ one or more spaces. An option consistes of a hyphen followed by
+ one or more letters.
+ */
+ static char *letters =
+ "abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ ;
+ char *p = python + strlen(python) - 1;
+ if (strchr(letters, *p) == NULL)
+ return NULL; /* Path doen't end with a letter. Odd. */
+ while (p > python && strchr(letters, *p) != NULL)
+ p--;
+ if (p == python || *p != '-')
+ return NULL; /* Can't be an option */
+ p--;
+ if (p > python && isspace(*p))
+ { /* BINGO, we have an option */
+ char *pyopt = p+1;
+ /* strip trailing spaces from remainder of python command */
+ while (p > python && isspace(*p))
+ *p-- = '\0';
+ return pyopt;
+ }
+ else
+ return NULL;
+}
+
int run(int argc, char **argv, int is_gui) {
char python[256]; /* python executable's filename*/
+ char *pyopt; /* Python option */
char script[256]; /* the script's filename */
HINSTANCE hPython; /* DLL handle for python executable */
int scriptf; /* file descriptor for script file */
- char **newargs; /* argument array for exec */
+ char **newargs, **newargsp; /* argument array for exec */
char *ptr, *end; /* working pointers for string manipulation */
+ int i; /* loop counter */
/* compute script name from our .exe name*/
GetModuleFileName(NULL, script, sizeof(script));
@@ -73,13 +131,16 @@ int run(int argc, char **argv, int is_gui) {
*ptr='\\'; /* convert slashes to avoid LoadLibrary crashes... */
}
- *ptr = '\0';
+ *ptr-- = '\0';
while (ptr>python && isspace(*ptr)) *ptr-- = '\0'; /* strip trailing sp */
if (strncmp(python, "#!", 2)) {
/* default to python.exe if no #! header */
strcpy(python, "#!python.exe");
}
+ /* Check for Python options */
+ pyopt = getpyopt(python);
+
/* At this point, the python buffer contains "#!pythonfilename" */
/* Using spawnv() can fail strangely if you e.g. find the Cygwin
@@ -94,12 +155,19 @@ int run(int argc, char **argv, int is_gui) {
/* printf("Python executable: %s\n", python); */
- /* Argument array needs to be argc+1 for args, plus 1 for null sentinel */
- newargs = (char **)calloc(argc+2, sizeof(char *));
- newargs[0] = quoted(python);
- newargs[1] = quoted(script);
- memcpy(newargs+2, argv+1, (argc-1)*sizeof(char *));
- newargs[argc+1] = NULL;
+ /* Argument array needs to be
+ argc+1 for python executable,
+ plus 1 for possible python opts,
+ plus 1 for null sentinel */
+ newargs = (char **)calloc(argc+3, sizeof(char *));
+ newargsp = newargs;
+ *newargsp++ = quoted(python);
+ if (pyopt)
+ *newargsp++ = pyopt;
+ *newargsp++ = quoted(script);
+ for (i = 1; i < argc; i++)
+ *newargsp++ = quoted(argv[i]);
+ *newargsp++ = NULL;
/* printf("args 0: %s\nargs 1: %s\n", newargs[0], newargs[1]); */
if (is_gui) {