diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index eaf3135e5..0352479fb 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,10 @@ +2006-04-11 Christopher Faylor + + * Makefile.in (DLL_OFILES): Add winf.o. + * spawn.cc: Move command line handling stuff into winf.cc. + * winf.h: New file. + * winf.cc: New file. + 2006-04-05 Christopher Faylor * fhandler_socket.cc: Move iptypes.h include after winsock2 since it diff --git a/winsup/cygwin/Makefile.in b/winsup/cygwin/Makefile.in index 665257c63..6d7857017 100644 --- a/winsup/cygwin/Makefile.in +++ b/winsup/cygwin/Makefile.in @@ -141,7 +141,7 @@ DLL_OFILES:=assert.o autoload.o bsdlib.o ctype.o cxx.o cygheap.o cygthread.o \ sigfe.o signal.o sigproc.o smallprint.o spawn.o strace.o strptime.o \ strsep.o strsig.o sync.o syscalls.o sysconf.o syslog.o termios.o thread.o \ timelocal.o timer.o times.o tty.o uinfo.o uname.o v8_regexp.o \ - v8_regerror.o v8_regsub.o wait.o wincap.o window.o \ + v8_regerror.o v8_regsub.o wait.o wincap.o window.o winf.o \ $(EXTRA_DLL_OFILES) $(EXTRA_OFILES) $(MALLOC_OFILES) $(MT_SAFE_OBJECTS) GMON_OFILES:=gmon.o mcount.o profil.o diff --git a/winsup/cygwin/lib/libcmain.c b/winsup/cygwin/lib/libcmain.c index b0c011999..da2a69839 100644 --- a/winsup/cygwin/lib/libcmain.c +++ b/winsup/cygwin/lib/libcmain.c @@ -13,7 +13,7 @@ details. */ #define SP " \t\n" -/* Allow apps which don't have a main work, as long as they define WinMain */ +/* Allow apps which don't have a main to work, as long as they define WinMain */ int main () { diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc index 8ac3ae039..9d358da0c 100644 --- a/winsup/cygwin/spawn.cc +++ b/winsup/cygwin/spawn.cc @@ -33,9 +33,7 @@ details. */ #include "registry.h" #include "environ.h" #include "cygtls.h" - -#define LINE_BUF_CHUNK (CYG_MAX_PATH * 2) -#define MAXWINCMDLEN 32767 +#include "winf.h" static suffix_info exe_suffixes[] = { @@ -239,138 +237,6 @@ iscmd (const char *argv0, const char *what) (n == 0 || isdirsep (argv0[n - 1])); } -class linebuf -{ - public: - size_t ix; - char *buf; - size_t alloced; - linebuf () : ix (0), buf (NULL), alloced (0) {} - ~linebuf () {if (buf) free (buf);} - void add (const char *what, int len) __attribute__ ((regparm (3))); - void add (const char *what) {add (what, strlen (what));} - void prepend (const char *what, int len); - void finish () __attribute__ ((regparm (1))); -}; - -void -linebuf::finish () -{ - if (!ix) - add ("", 1); - else - buf[--ix] = '\0'; -} - -void -linebuf::add (const char *what, int len) -{ - size_t newix = ix + len; - if (newix >= alloced || !buf) - { - alloced += LINE_BUF_CHUNK + newix; - buf = (char *) realloc (buf, alloced + 1); - } - memcpy (buf + ix, what, len); - ix = newix; - buf[ix] = '\0'; -} - -void -linebuf::prepend (const char *what, int len) -{ - int buflen; - size_t newix; - if ((newix = ix + len) >= alloced) - { - alloced += LINE_BUF_CHUNK + newix; - buf = (char *) realloc (buf, alloced + 1); - buf[ix] = '\0'; - } - if ((buflen = strlen (buf))) - memmove (buf + len, buf, buflen + 1); - else - buf[newix] = '\0'; - memcpy (buf, what, len); - ix = newix; -} - -class av -{ - char **argv; - int calloced; - public: - int argc; - bool win16_exe; - bool iscui; - av (): argv (NULL), iscui (false) {} - av (int ac_in, const char * const *av_in) : calloced (0), argc (ac_in), win16_exe (false), iscui (false) - { - argv = (char **) cmalloc (HEAP_1_ARGV, (argc + 5) * sizeof (char *)); - memcpy (argv, av_in, (argc + 1) * sizeof (char *)); - } - void *operator new (size_t, void *p) __attribute__ ((nothrow)) {return p;} - void set (int ac_in, const char * const *av_in) {new (this) av (ac_in, av_in);} - ~av () - { - if (argv) - { - for (int i = 0; i < calloced; i++) - if (argv[i]) - cfree (argv[i]); - cfree (argv); - } - } - int unshift (const char *what, int conv = 0); - operator char **() {return argv;} - void all_calloced () {calloced = argc;} - void replace0_maybe (const char *arg0) - { - /* Note: Assumes that argv array has not yet been "unshifted" */ - if (!calloced) - { - argv[0] = cstrdup1 (arg0); - calloced = true; - } - } - void dup_maybe (int i) - { - if (i >= calloced) - argv[i] = cstrdup1 (argv[i]); - } - void dup_all () - { - for (int i = calloced; i < argc; i++) - argv[i] = cstrdup1 (argv[i]); - } - int fixup (const char *, path_conv&, const char *); -}; - -int -av::unshift (const char *what, int conv) -{ - char **av; - av = (char **) crealloc (argv, (argc + 2) * sizeof (char *)); - if (!av) - return 0; - - argv = av; - memmove (argv + 1, argv, (argc + 1) * sizeof (char *)); - char buf[CYG_MAX_PATH]; - if (conv) - { - cygwin_conv_to_posix_path (what, buf); - char *p = strchr (buf, '\0') - 4; - if (p > buf && strcasematch (p, ".exe")) - *p = '\0'; - what = buf; - } - *argv = cstrdup1 (what); - calloced++; - argc++; - return 1; -} - struct pthread_cleanup { _sig_func_ptr oldint; @@ -507,65 +373,13 @@ spawn_guts (const char * prog_arg, const char *const *argv, { if (real_path.iscygexec ()) newargv.dup_all (); - else + else if (!one_line.fromargv (newargv, real_path)) { - for (int i = 0; i < newargv.argc; i++) - { - char *p = NULL; - const char *a; - - newargv.dup_maybe (i); - a = i ? newargv[i] : (char *) real_path; - int len = strlen (a); - if (len != 0 && !strpbrk (a, " \t\n\r\"")) - one_line.add (a, len); - else - { - one_line.add ("\"", 1); - /* Handle embedded special characters " and \. - A " is always preceded by a \. - A \ is not special unless it precedes a ". If it does, - then all preceding \'s must be doubled to avoid having - the Windows command line parser interpret the \ as quoting - the ". This rule applies to a string of \'s before the end - of the string, since cygwin/windows uses a " to delimit the - argument. */ - for (; (p = strpbrk (a, "\"\\")); a = ++p) - { - one_line.add (a, p - a); - /* Find length of string of backslashes */ - int n = strspn (p, "\\"); - if (!n) - one_line.add ("\\\"", 2); /* No backslashes, so it must be a ". - The " has to be protected with a backslash. */ - else - { - one_line.add (p, n); /* Add the run of backslashes */ - /* Need to double up all of the preceding - backslashes if they precede a quote or EOS. */ - if (!p[n] || p[n] == '"') - one_line.add (p, n); - p += n - 1; /* Point to last backslash */ - } - } - if (*a) - one_line.add (a); - one_line.add ("\"", 1); - } - one_line.add (" ", 1); - } - - one_line.finish (); - - if (one_line.ix >= MAXWINCMDLEN) - { - debug_printf ("command line too long (>32K), return E2BIG"); - set_errno (E2BIG); - res = -1; - goto out; - } + res = -1; + goto out; } + newargv.all_calloced (); moreinfo->argc = newargv.argc; moreinfo->argv = newargv; diff --git a/winsup/cygwin/winf.cc b/winsup/cygwin/winf.cc new file mode 100644 index 000000000..01c5cfb65 --- /dev/null +++ b/winsup/cygwin/winf.cc @@ -0,0 +1,148 @@ +/* winf.cc + + Copyright 2003, 2004, 2005, 2006 Red Hat, Inc. + +This software is a copyrighted work licensed under the terms of the +Cygwin license. Please consult the file "CYGWIN_LICENSE" for +details. */ + +#include "winsup.h" +#include +#include "cygerrno.h" +#include "security.h" +#include "sync.h" +#include "path.h" +#include "fhandler.h" +#include "dtable.h" +#include "cygheap.h" +#include "winf.h" +#include "sys/cygwin.h" + +void +linebuf::finish () +{ + if (!ix) + add ("", 1); + else + buf[--ix] = '\0'; +} + +void +linebuf::add (const char *what, int len) +{ + size_t newix = ix + len; + if (newix >= alloced || !buf) + { + alloced += LINE_BUF_CHUNK + newix; + buf = (char *) realloc (buf, alloced + 1); + } + memcpy (buf + ix, what, len); + ix = newix; + buf[ix] = '\0'; +} + +void +linebuf::prepend (const char *what, int len) +{ + int buflen; + size_t newix; + if ((newix = ix + len) >= alloced) + { + alloced += LINE_BUF_CHUNK + newix; + buf = (char *) realloc (buf, alloced + 1); + buf[ix] = '\0'; + } + if ((buflen = strlen (buf))) + memmove (buf + len, buf, buflen + 1); + else + buf[newix] = '\0'; + memcpy (buf, what, len); + ix = newix; +} + +bool +linebuf::fromargv (av& newargv, char *real_path) +{ + bool success = true; + for (int i = 0; i < newargv.argc; i++) + { + char *p = NULL; + const char *a; + + newargv.dup_maybe (i); + a = i ? newargv[i] : (char *) real_path; + int len = strlen (a); + if (len != 0 && !strpbrk (a, " \t\n\r\"")) + add (a, len); + else + { + add ("\"", 1); + /* Handle embedded special characters " and \. + A " is always preceded by a \. + A \ is not special unless it precedes a ". If it does, + then all preceding \'s must be doubled to avoid having + the Windows command line parser interpret the \ as quoting + the ". This rule applies to a string of \'s before the end + of the string, since cygwin/windows uses a " to delimit the + argument. */ + for (; (p = strpbrk (a, "\"\\")); a = ++p) + { + add (a, p - a); + /* Find length of string of backslashes */ + int n = strspn (p, "\\"); + if (!n) + add ("\\\"", 2); /* No backslashes, so it must be a ". + The " has to be protected with a backslash. */ + else + { + add (p, n); /* Add the run of backslashes */ + /* Need to double up all of the preceding + backslashes if they precede a quote or EOS. */ + if (!p[n] || p[n] == '"') + add (p, n); + p += n - 1; /* Point to last backslash */ + } + } + if (*a) + add (a); + add ("\"", 1); + } + add (" ", 1); + } + + finish (); + + if (ix >= MAXWINCMDLEN) + { + debug_printf ("command line too long (>32K), return E2BIG"); + set_errno (E2BIG); + success = false; + } + + return success; +} + +int +av::unshift (const char *what, int conv) +{ + char **av; + av = (char **) crealloc (argv, (argc + 2) * sizeof (char *)); + if (!av) + return 0; + + argv = av; + memmove (argv + 1, argv, (argc + 1) * sizeof (char *)); + char buf[CYG_MAX_PATH]; + if (conv) + { + cygwin_conv_to_posix_path (what, buf); + char *p = strchr (buf, '\0') - 4; + if (p > buf && strcasematch (p, ".exe")) + *p = '\0'; + what = buf; + } + *argv = cstrdup1 (what); + calloced++; + argc++; + return 1; +} diff --git a/winsup/cygwin/winf.h b/winsup/cygwin/winf.h new file mode 100644 index 000000000..3b7fec23b --- /dev/null +++ b/winsup/cygwin/winf.h @@ -0,0 +1,82 @@ +/* winf.h + + Copyright 2003, 2004, 2005 Red Hat, Inc. + +This software is a copyrighted work licensed under the terms of the +Cygwin license. Please consult the file "CYGWIN_LICENSE" for +details. */ + +#ifndef _WINF_H +#define _WINF_H + +#define MAXWINCMDLEN 32767 +#define LINE_BUF_CHUNK (CYG_MAX_PATH * 2) + +class av +{ + char **argv; + int calloced; + public: + int argc; + bool win16_exe; + bool iscui; + av (): argv (NULL), iscui (false) {} + av (int ac_in, const char * const *av_in) : calloced (0), argc (ac_in), win16_exe (false), iscui (false) + { + argv = (char **) cmalloc (HEAP_1_ARGV, (argc + 5) * sizeof (char *)); + memcpy (argv, av_in, (argc + 1) * sizeof (char *)); + } + void *operator new (size_t, void *p) __attribute__ ((nothrow)) {return p;} + void set (int ac_in, const char * const *av_in) {new (this) av (ac_in, av_in);} + ~av () + { + if (argv) + { + for (int i = 0; i < calloced; i++) + if (argv[i]) + cfree (argv[i]); + cfree (argv); + } + } + int unshift (const char *what, int conv = 0); + operator char **() {return argv;} + void all_calloced () {calloced = argc;} + void replace0_maybe (const char *arg0) + { + /* Note: Assumes that argv array has not yet been "unshifted" */ + if (!calloced) + { + argv[0] = cstrdup1 (arg0); + calloced = true; + } + } + void dup_maybe (int i) + { + if (i >= calloced) + argv[i] = cstrdup1 (argv[i]); + } + void dup_all () + { + for (int i = calloced; i < argc; i++) + argv[i] = cstrdup1 (argv[i]); + } + int fixup (const char *, path_conv&, const char *); +}; + +class linebuf +{ + public: + size_t ix; + char *buf; + size_t alloced; + linebuf () : ix (0), buf (NULL), alloced (0) {} + ~linebuf () {if (buf) free (buf);} + void add (const char *what, int len) __attribute__ ((regparm (3))); + void add (const char *what) {add (what, strlen (what));} + void prepend (const char *what, int len); + void finish () __attribute__ ((regparm (1))); + bool fromargv(av&, char *); + operator char *() {return buf;} +}; + +#endif /*_WINF_H*/