diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 0b3e91362..5c4c3e009 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,24 @@ +2013-07-19 Christopher Faylor + + * common.din: Export GetCommandLine{A,W}. + * kernel32.cc: Add includes needed for GetCommandLine functions. + (ucmd): New function. + (cygwin_GetCommandLineW): Ditto. + (cygwin_GetCommandLineA): Ditto. + * spawn.cc (child_info_spawn::worker): Rename one_line -> cmd. Use + linebuf_wcs macro to generate a wide character version of the + line buffer. Remove duplicate printing of command line. Don't access + members of linebuf directly. + * winf.h: Use pragma once. + (linebuf): Make storage private. + (linebuf::operator size_t): New operator. Return size of buf. + (linebuf::operator wchar_t): New operator. + (linebuf::wcs): New function. + (lb_wcs): New macro. + * include/cygwin/version.h: Bump API minor number to 268. + + * strfuncs.cc: Clarify descriptive file comment. + 2013-07-19 Corinna Vinschen * cygtls.cc (_cygtls::remove): Close cw_timer handle, thus avoiding diff --git a/winsup/cygwin/common.din b/winsup/cygwin/common.din index e5f4eada7..c068911ae 100644 --- a/winsup/cygwin/common.din +++ b/winsup/cygwin/common.din @@ -457,6 +457,8 @@ gammaf NOSIGFE gammaf_r NOSIGFE gcvt SIGFE gcvtf SIGFE +GetCommandLineA@0 = cygwin_GetCommandLineA@0 NOSIGFE +GetCommandLineW@0 = cygwin_GetCommandLineW@0 NOSIGFE get_avphys_pages SIGFE get_current_dir_name SIGFE get_nprocs SIGFE diff --git a/winsup/cygwin/include/cygwin/version.h b/winsup/cygwin/include/cygwin/version.h index ae91d8f8d..8ab8c0c17 100644 --- a/winsup/cygwin/include/cygwin/version.h +++ b/winsup/cygwin/include/cygwin/version.h @@ -437,12 +437,13 @@ details. */ 266: Export arc4random, arc4random_addrandom, arc4random_buf, arc4random_stir, arc4random_uniform. 267: Export rawmemchr. + 268: Export GetCommandLineA, GetCommandLineW */ /* Note that we forgot to bump the api for ualarm, strtoll, strtoull */ #define CYGWIN_VERSION_API_MAJOR 0 -#define CYGWIN_VERSION_API_MINOR 267 +#define CYGWIN_VERSION_API_MINOR 268 /* There is also a compatibity version number associated with the shared memory regions. It is incremented when incompatible diff --git a/winsup/cygwin/kernel32.cc b/winsup/cygwin/kernel32.cc index 6eeb2dc43..9a5dc832e 100644 --- a/winsup/cygwin/kernel32.cc +++ b/winsup/cygwin/kernel32.cc @@ -1,6 +1,6 @@ /* kernel32.cc: Win32 replacement functions. - Copyright 2008, 2009, 2010, 2011, 2012 Red Hat, Inc. + Copyright 2008, 2009, 2010, 2011, 2012, 2013 Red Hat, Inc. This file is part of Cygwin. @@ -11,6 +11,15 @@ details. */ #include "winsup.h" #include "shared_info.h" #include "ntdll.h" +#include "cygerrno.h" +#include "security.h" +#include "path.h" +#include "fhandler.h" +#include "dtable.h" +#include "cygheap.h" +#include "tls_pbuf.h" +#include "winf.h" +#include "sys/cygwin.h" /* Implement CreateEvent/OpenEvent so that named objects are always created in Cygwin shared object namespace. */ @@ -402,3 +411,43 @@ OpenFileMappingA (DWORD dwDesiredAccess, BOOL bInheritHandle, LPCSTR lpName) } return OpenFileMappingW (dwDesiredAccess, bInheritHandle, lpName ? name : NULL); } + +/* The external functions below wrap Windows functions of the same name + and provide a Windows interface to Cygwin functionality. */ + +/* Construct a unicode version of the Cygwin command line from __argv) */ +static UNICODE_STRING * +ucmd () +{ + static UNICODE_STRING wcmd; + if (!wcmd.Buffer) + { + linebuf cmd; + path_conv real_path (__argv[0]); + av newargv (__argc, __argv); + cmd.fromargv (newargv, real_path.get_win32 (), true); + RtlInitUnicodeString (&wcmd, cmd); + } + return &wcmd; +} + +/* Cygwin replacement for GetCommandLineA. Returns a concatenated wide string + representing the argv list, constructed using roughly the same mechanism as + child_info_spawn::worker */ +extern "C" LPWSTR WINAPI +cygwin_GetCommandLineW (void) +{ + return ucmd ()->Buffer; +} + +/* Cygwin replacement for GetCommandLineA. Returns a concatenated string + representing the argv list, constructed using roughly the same mechanism + as child_info_spawn::worker */ +extern "C" LPSTR WINAPI +cygwin_GetCommandLineA (void) +{ + static ANSI_STRING cmd; + if (!cmd.Buffer) + RtlUnicodeStringToAnsiString (&cmd, ucmd (), TRUE); + return cmd.Buffer; +} diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc index b2e1c04bd..23217401c 100644 --- a/winsup/cygwin/spawn.cc +++ b/winsup/cygwin/spawn.cc @@ -319,7 +319,7 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv, } av newargv; - linebuf one_line; + linebuf cmd; PWCHAR envblock = NULL; path_conv real_path; bool reset_sendsig = false; @@ -387,16 +387,16 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv, (iscmd (argv[0], "command.com") || iscmd (argv[0], "cmd.exe"))) { real_path.check (prog_arg); - one_line.add ("\""); + cmd.add ("\""); if (!real_path.error) - one_line.add (real_path.get_win32 ()); + cmd.add (real_path.get_win32 ()); else - one_line.add (argv[0]); - one_line.add ("\""); - one_line.add (" "); - one_line.add (argv[1]); - one_line.add (" "); - one_line.add (argv[2]); + cmd.add (argv[0]); + cmd.add ("\""); + cmd.add (" "); + cmd.add (argv[1]); + cmd.add (" "); + cmd.add (argv[2]); real_path.set_path (argv[0]); null_app_name = true; } @@ -407,7 +407,7 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv, moreinfo->argc = newargv.argc; moreinfo->argv = newargv; } - else if (!one_line.fromargv (newargv, real_path.get_win32 (), + else if (!cmd.fromargv (newargv, real_path.get_win32 (), real_path.iscygexec ())) { res = -1; @@ -423,11 +423,6 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv, else VerifyHandle (moreinfo->myself_pinfo); } - WCHAR wone_line[one_line.ix + 1]; - if (one_line.ix) - sys_mbstowcs (wone_line, one_line.ix + 1, one_line.buf); - else - wone_line[0] = L'\0'; PROCESS_INFORMATION pi; pi.hProcess = pi.hThread = NULL; @@ -539,8 +534,6 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv, goto out; } } - syscall_printf ("null_app_name %d (%W, %.9500W)", null_app_name, - runpath, wone_line); cygbench ("spawn-worker"); @@ -626,7 +619,7 @@ loop: && !::cygheap->user.setuid_to_restricted)) { rc = CreateProcessW (runpath, /* image name - with full path */ - wone_line, /* what was passed to exec */ + lb_wcs (cmd), /* what was passed to exec */ &sec_none_nih, /* process security attrs */ &sec_none_nih, /* thread security attrs */ TRUE, /* inherit handles from parent */ @@ -689,7 +682,7 @@ loop: rc = CreateProcessAsUserW (::cygheap->user.primary_token (), runpath, /* image name - with full path */ - wone_line, /* what was passed to exec */ + lb_wcs (cmd), /* what was passed to exec */ &sec_none_nih, /* process security attrs */ &sec_none_nih, /* thread security attrs */ TRUE, /* inherit handles from parent */ @@ -763,7 +756,7 @@ loop: /* We print the original program name here so the user can see that too. */ syscall_printf ("pid %d, prog_arg %s, cmd line %.9500s)", - rc ? cygpid : (unsigned int) -1, prog_arg, one_line.buf); + rc ? cygpid : (unsigned int) -1, prog_arg, (const char *) cmd); /* Name the handle similarly to proc_subproc. */ ProtectHandle1 (pi.hProcess, childhProc); diff --git a/winsup/cygwin/strfuncs.cc b/winsup/cygwin/strfuncs.cc index 9e5aa0304..d80f2ec6f 100644 --- a/winsup/cygwin/strfuncs.cc +++ b/winsup/cygwin/strfuncs.cc @@ -1,4 +1,4 @@ -/* strfuncs.cc: misc funcs that don't belong anywhere else +/* strfuncs.cc: string functions Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Red Hat, Inc. diff --git a/winsup/cygwin/winf.h b/winsup/cygwin/winf.h index 3dd63b5e0..d7488c360 100644 --- a/winsup/cygwin/winf.h +++ b/winsup/cygwin/winf.h @@ -6,9 +6,7 @@ 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 - +#pragma once /* Hack for Cygwin processes. If the Windows command line length gets slightly bigger than this value, the stack position is suddenly moved up by 64K for no apparent reason, which results in subsequent forks failing. Since Cygwin @@ -67,10 +65,10 @@ class av class linebuf { - public: size_t ix; char *buf; size_t alloced; + public: linebuf () : ix (0), buf (NULL), alloced (0) {} ~linebuf () {if (buf) free (buf);} void __reg3 add (const char *, int); @@ -78,7 +76,31 @@ class linebuf void prepend (const char *, int); void __reg2 finish (bool); bool __reg3 fromargv(av&, const char *, bool);; - operator char *() {return buf;} + operator size_t () const { return ix + 1; } + operator const char * () const { return buf; } + operator wchar_t * () + { + size_t n = ix + 1; + /* Note that this malloc'ed buffer is not freed by the destructor. + It is up to the caller to do (or not do) that. */ + wchar_t *wbuf = (wchar_t *) malloc (sizeof (wchar_t) * n); + return wcs (wbuf, n); + } + wchar_t *wcs (wchar_t *wbuf, size_t n) + { + if (n == 1) + wbuf[0] = L'\0'; + else + sys_mbstowcs (wbuf, n, buf); + return wbuf; + } }; -#endif /*_WINF_H*/ +/* Return a temporary buffer representing the wide character version + of a linebuf command line. */ +#define lb_wcs(__x) \ +({ \ + wchar_t __wbuf[(size_t) __x]; \ + __x.wcs (__wbuf, sizeof (__wbuf) / sizeof (__wbuf[0])); \ + __wbuf; \ +})