X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/1d7d10d1fc36b8bba908c0cb09160d7a7d3c3780..e3c5a1294122e3452a96bf195e7d58cc30e9c580:/nt/cmdproxy.c diff --git a/nt/cmdproxy.c b/nt/cmdproxy.c index 312d6f6b3c..811a7380dc 100644 --- a/nt/cmdproxy.c +++ b/nt/cmdproxy.c @@ -1,7 +1,8 @@ /* Proxy shell designed for use with Emacs on Windows 95 and NT. - Copyright (C) 1997 Free Software Foundation, Inc. + Copyright (C) 1997, 2001, 2002, 2003, 2004, 2005, 2006, 2007, + 2008, 2009 Free Software Foundation, Inc. - Accepts subset of Unix sh(1) command-line options, for compatability + Accepts subset of Unix sh(1) command-line options, for compatibility with elisp code written for Unix. When possible, executes external programs directly (a common use of /bin/sh by Emacs), otherwise invokes the user-specified command processor to handle built-in shell @@ -14,10 +15,10 @@ This file is part of GNU Emacs. -GNU Emacs is free software; you can redistribute it and/or modify +GNU Emacs is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. GNU Emacs is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -25,9 +26,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with GNU Emacs; see the file COPYING. If not, write to -the Free Software Foundation, Inc., 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ +along with GNU Emacs. If not, see . */ #include @@ -158,6 +157,7 @@ get_next_token (char * buf, char ** pSrc) if (p[0] == escape_char && escape_char != '"') { escape_char_run++; + p++; continue; } else if (p[0] == '"') @@ -229,7 +229,7 @@ search_dir (char *dir, char *exec, int bufsize, char *buffer) int i, rc; /* Search the directory for the program. */ - for (i = 0; i < n_exts; i++) + for (i = 0; i < n_exts; i++) { rc = SearchPath (dir, exec, exts[i], bufsize, buffer, &dummy); if (rc > 0) @@ -239,7 +239,7 @@ search_dir (char *dir, char *exec, int bufsize, char *buffer) return 0; } -/* Return the absolute name of executable file PROG, including +/* Return the absolute name of executable file PROG, including any file extensions. If an absolute name for PROG cannot be found, return NULL. */ char * @@ -271,18 +271,18 @@ make_absolute (char *prog) return NULL; } - if (GetCurrentDirectory (MAX_PATH, curdir) <= 0) + if (GetCurrentDirectory (MAX_PATH, curdir) <= 0) return NULL; /* Relative path; search in current dir. */ - if (strpbrk (prog, "\\")) + if (strpbrk (prog, "\\")) { if (search_dir (curdir, prog, MAX_PATH, absname) > 0) return strdup (absname); - else + else return NULL; } - + /* Just filename; search current directory then PATH. */ path = alloca (strlen (getenv ("PATH")) + strlen (curdir) + 2); strcpy (path, curdir); @@ -303,7 +303,7 @@ make_absolute (char *prog) /* Move to the next directory. */ path = p + 1; - } + } return NULL; } @@ -321,7 +321,7 @@ setup_argv (void) char * cmdline = GetCommandLine (); int arg_bytes = 0; - + } #endif @@ -341,7 +341,7 @@ console_event_handler (DWORD event) case CTRL_BREAK_EVENT: if (!interactive) { - /* Both command.com and cmd.exe have the annoying behaviour of + /* Both command.com and cmd.exe have the annoying behavior of prompting "Terminate batch job (y/n)?" when interrupted while running a batch file, even if running in non-interactive (-c) mode. Try to make up for this @@ -369,7 +369,7 @@ console_event_handler (DWORD event) /* Change from normal usage; return value indicates whether spawn succeeded or failed - program return code is returned separately. */ int -spawn (char * progname, char * cmdline, int * retcode) +spawn (char * progname, char * cmdline, char * dir, int * retcode) { BOOL success = FALSE; SECURITY_ATTRIBUTES sec_attrs; @@ -383,12 +383,12 @@ spawn (char * progname, char * cmdline, int * retcode) sec_attrs.nLength = sizeof (sec_attrs); sec_attrs.lpSecurityDescriptor = NULL; sec_attrs.bInheritHandle = FALSE; - + memset (&start, 0, sizeof (start)); start.cb = sizeof (start); if (CreateProcess (progname, cmdline, &sec_attrs, NULL, TRUE, - 0, envblock, NULL, &start, &child)) + 0, envblock, dir, &start, &child)) { success = TRUE; /* wait for completion and pass on return code */ @@ -432,12 +432,16 @@ main (int argc, char ** argv) int num_pass_through_args; char modname[MAX_PATH]; char path[MAX_PATH]; + char dir[MAX_PATH]; interactive = TRUE; SetConsoleCtrlHandler ((PHANDLER_ROUTINE) console_event_handler, TRUE); + if (!GetCurrentDirectory (sizeof (dir), dir)) + fail ("error: GetCurrentDirectory failed\n"); + /* We serve double duty: we can be called either as a proxy for the real shell (that is, because we are defined to be the user shell), or in our role as a helper application for running DOS programs. @@ -453,16 +457,33 @@ main (int argc, char ** argv) if (!GetModuleFileName (NULL, modname, sizeof (modname))) fail ("error: GetModuleFileName failed\n"); + /* Change directory to location of .exe so startup directory can be + deleted. */ + progname = strrchr (modname, '\\'); + *progname = '\0'; + SetCurrentDirectory (modname); + *progname = '\\'; + + /* Due to problems with interaction between API functions that use "OEM" + codepage vs API functions that use the "ANSI" codepage, we need to + make things consistent by choosing one and sticking with it. */ + SetConsoleCP (GetACP()); + SetConsoleOutputCP (GetACP()); + /* Although Emacs always sets argv[0] to an absolute pathname, we might get run in other ways as well, so convert argv[0] to an - absolute name before comparing to the module name. */ + absolute name before comparing to the module name. Don't get + caught out by mixed short and long names. */ + GetShortPathName (modname, modname, sizeof (modname)); + path[0] = '\0'; if (!SearchPath (NULL, argv[0], ".exe", sizeof (path), path, &progname) + || !GetShortPathName (path, path, sizeof (path)) || stricmp (modname, path) != 0) { /* We are being used as a helper to run a DOS app; just pass command line to DOS app without change. */ /* TODO: fill in progname. */ - if (spawn (NULL, GetCommandLine (), &rc)) + if (spawn (NULL, GetCommandLine (), dir, &rc)) return rc; fail ("Could not run %s\n", GetCommandLine ()); } @@ -492,10 +513,10 @@ main (int argc, char ** argv) { ++argv; /* Act on switches we recognize (mostly single letter switches, - except for -e); all unrecognised switches and extra args are + except for -e); all unrecognized switches and extra args are passed on to real shell if used (only really of benefit for interactive use, but allow for batch use as well). Accept / as - switch char for compatability with cmd.exe. */ + switch char for compatibility with cmd.exe. */ if (((*argv)[0] == '-' || (*argv)[0] == '/') && (*argv)[1] != '\0') { if (((*argv)[1] == 'c' || (*argv)[1] == 'C') && ((*argv)[2] == '\0')) @@ -510,7 +531,7 @@ main (int argc, char ** argv) if (cmdline) warn ("warning: %s ignored because of -c\n", *argv); } - else if (((*argv)[1] == 'e' || (*argv[1] == 'E')) && ((*argv)[2] == ':')) + else if (((*argv)[1] == 'e' || (*argv)[1] == 'E') && ((*argv)[2] == ':')) { int requested_envsize = atoi (*argv + 3); /* Enforce a reasonable minimum size, as above. */ @@ -583,6 +604,7 @@ main (int argc, char ** argv) { char * p; int extra_arg_space = 0; + int run_command_dot_com; progname = getenv ("COMSPEC"); if (!progname) @@ -594,6 +616,10 @@ main (int argc, char ** argv) if (progname == NULL || strchr (progname, '\\') == NULL) fail ("error: the program %s could not be found.\n", getenv ("COMSPEC")); + /* Need to set environment size when running command.com. */ + run_command_dot_com = + (stricmp (strrchr (progname, '\\'), "command.com") == 0); + /* Work out how much extra space is required for pass_through_args. */ for (argv = pass_through_args; *argv != NULL; ++argv) @@ -620,8 +646,7 @@ main (int argc, char ** argv) for (argv = pass_through_args; *argv != NULL; ++argv) p += wsprintf (p, " %s", *argv); - if (GetVersion () & 0x80000000) - /* Set environment size to something reasonable on Windows 95. */ + if (run_command_dot_com) wsprintf(p, " /e:%d /c %s", envsize, cmdline); else wsprintf(p, " /c %s", cmdline); @@ -629,12 +654,10 @@ main (int argc, char ** argv) } else { - if (GetVersion () & 0x80000000) + if (run_command_dot_com) { /* Provide dir arg expected by command.com when first - started interactively (the "command search path"). - cmd.exe does not require it, but accepts it silently - - presumably other DOS compatible shells do the same. To + started interactively (the "command search path"). To avoid potential problems with spaces in command dir (which cannot be quoted - command.com doesn't like it), we always use the 8.3 form. */ @@ -644,7 +667,6 @@ main (int argc, char ** argv) *(++p) = '\0'; } else - /* Dir arg not needed on NT. */ path[0] = '\0'; cmdline = p = alloca (strlen (progname) + extra_arg_space + @@ -658,8 +680,7 @@ main (int argc, char ** argv) for (argv = pass_through_args; *argv != NULL; ++argv) p += wsprintf (p, " %s", *argv); - if (GetVersion () & 0x80000000) - /* Set environment size to something reasonable on Windows 95. */ + if (run_command_dot_com) wsprintf (p, " /e:%d", envsize); } } @@ -670,7 +691,7 @@ main (int argc, char ** argv) if (!cmdline) cmdline = progname; - if (spawn (progname, cmdline, &rc)) + if (spawn (progname, cmdline, dir, &rc)) return rc; if (!need_shell) @@ -683,3 +704,6 @@ main (int argc, char ** argv) return 0; } + +/* arch-tag: 88678d93-07ac-4e2f-ad63-d4a740ca69ac + (do not change this comment) */