diff options
author | Jim Fulton <distutils-sig@python.org> | 2006-08-22 19:58:05 +0000 |
---|---|---|
committer | Jim Fulton <distutils-sig@python.org> | 2006-08-22 19:58:05 +0000 |
commit | cd84d4b5eb8113b416f6cb080b3445799ed2ff99 (patch) | |
tree | 5dbdd13cbb5d1ed57d237bd7b4567e7a75c735fc /launcher.c | |
parent | f744be10b9702c1056fda2e18cfa9e8cb99d331a (diff) | |
download | python-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-x | launcher.c | 88 |
1 files changed, 78 insertions, 10 deletions
@@ -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) { |