/* Client process that communicates with GNU Emacs acting as server.
Copyright (C) 1986, 1987, 1994, 1999, 2000, 2001, 2002, 2003, 2004,
- 2005, 2006 Free Software Foundation, Inc.
+ 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
This file is part of GNU Emacs.
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)
+the Free Software Foundation; either version 3, or (at your option)
any later version.
GNU Emacs is distributed in the hope that it will be useful,
# include <malloc.h>
# include <stdlib.h>
# include <windows.h>
+# include <commctrl.h>
# define NO_SOCKETS_IN_FILE_SYSTEM
#include <signal.h>
#include <errno.h>
-/* From lisp.h */
-#ifndef DIRECTORY_SEP
-#define DIRECTORY_SEP '/'
-#endif
-#ifndef IS_DIRECTORY_SEP
-#define IS_DIRECTORY_SEP(_c_) ((_c_) == DIRECTORY_SEP)
-#endif
-#ifndef IS_DEVICE_SEP
-#ifndef DEVICE_SEP
-#define IS_DEVICE_SEP(_c_) 0
-#else
-#define IS_DEVICE_SEP(_c_) ((_c_) == DEVICE_SEP)
-#endif
-#endif
-#ifndef IS_ANY_SEP
-#define IS_ANY_SEP(_c_) (IS_DIRECTORY_SEP (_c_))
-#endif
-
-
\f
char *getenv (), *getwd ();
char *(getcwd) ();
+#ifdef WINDOWSNT
+char *w32_getenv ();
+#define egetenv(VAR) w32_getenv(VAR)
+#else
+#define egetenv(VAR) getenv(VAR)
+#endif
+
#ifndef VERSION
#define VERSION "unspecified"
#endif
\f
-#define SEND_STRING(data) (send_to_emacs (s, (data)))
-#define SEND_QUOTED(data) (quote_argument (s, (data)))
#ifndef EXIT_SUCCESS
#define EXIT_SUCCESS 0
/* Name used to invoke this program. */
char *progname;
-/* The first argument to main. */
-int main_argc;
-
/* The second argument to main. */
char **main_argv;
/* Nonzero means args are expressions to be evaluated. --eval. */
int eval = 0;
-/* Nonzero means don't open a new frame. --current-frame. */
-int current_frame = 0;
+/* Nonzero means don't open a new frame. Inverse of --create-frame. */
+int current_frame = 1;
/* Nonzero means open a new graphical frame. */
int window_system = 0;
/* PID of the Emacs server process. */
int emacs_pid = 0;
-/* File handles for communicating with Emacs. */
-FILE *out, *in;
-
void print_help_and_exit () NO_RETURN;
struct option longopts[] =
{ "help", no_argument, NULL, 'H' },
{ "version", no_argument, NULL, 'V' },
{ "tty", no_argument, NULL, 't' },
- { "current-frame", no_argument, NULL, 'c' },
+ { "create-frame", no_argument, NULL, 'c' },
{ "alternate-editor", required_argument, NULL, 'a' },
#ifndef NO_SOCKETS_IN_FILE_SYSTEM
{ "socket-name", required_argument, NULL, 's' },
#endif
{ "server-file", required_argument, NULL, 'f' },
+#ifndef WINDOWSNT
{ "display", required_argument, NULL, 'd' },
+#endif
{ 0, 0, 0, 0 }
};
/* From sysdep.c */
#if !defined (HAVE_GET_CURRENT_DIR_NAME) || defined (BROKEN_GET_CURRENT_DIR_NAME)
+/* From lisp.h */
+#ifndef DIRECTORY_SEP
+#define DIRECTORY_SEP '/'
+#endif
+#ifndef IS_DIRECTORY_SEP
+#define IS_DIRECTORY_SEP(_c_) ((_c_) == DIRECTORY_SEP)
+#endif
+#ifndef IS_DEVICE_SEP
+#ifndef DEVICE_SEP
+#define IS_DEVICE_SEP(_c_) 0
+#else
+#define IS_DEVICE_SEP(_c_) ((_c_) == DEVICE_SEP)
+#endif
+#endif
+#ifndef IS_ANY_SEP
+#define IS_ANY_SEP(_c_) (IS_DIRECTORY_SEP (_c_))
+#endif
+
+
/* Return the current working directory. Returns NULL on errors.
Any other returned value must be freed with free. This is used
only when get_current_dir_name is not defined on the system. */
/* If PWD is accurate, use it instead of calling getwd. PWD is
sometimes a nicer name, and using it may avoid a fatal error if a
parent directory is searchable but not readable. */
- if ((pwd = getenv ("PWD")) != 0
+ if ((pwd = egetenv ("PWD")) != 0
&& (IS_DIRECTORY_SEP (*pwd) || (*pwd && IS_DEVICE_SEP (pwd[1])))
&& stat (pwd, &pwdstat) == 0
&& stat (".", &dotstat) == 0
}
#endif
-/* Message functions. */
-
#ifdef WINDOWSNT
-/* I first tried to check for STDOUT. The check did not work,
- I get a valid handle also in nonconsole apps.
- Instead I test for console title, which seems to work. */
+
+#define REG_ROOT "SOFTWARE\\GNU\\Emacs"
+
+/* Retrieve an environment variable from the Emacs subkeys of the registry.
+ Return NULL if the variable was not found, or it was empty.
+ This code is based on w32_get_resource (w32.c). */
+char *
+w32_get_resource (predefined, key, type)
+ HKEY predefined;
+ char *key;
+ LPDWORD type;
+{
+ HKEY hrootkey = NULL;
+ char *result = NULL;
+ DWORD cbData;
+
+ if (RegOpenKeyEx (predefined, REG_ROOT, 0, KEY_READ, &hrootkey) == ERROR_SUCCESS)
+ {
+ if (RegQueryValueEx (hrootkey, key, NULL, NULL, NULL, &cbData) == ERROR_SUCCESS)
+ {
+ result = (char *) xmalloc (cbData);
+
+ if ((RegQueryValueEx (hrootkey, key, NULL, type, result, &cbData) != ERROR_SUCCESS) ||
+ (*result == 0))
+ {
+ free (result);
+ result = NULL;
+ }
+ }
+
+ RegCloseKey (hrootkey);
+ }
+
+ return result;
+}
+
+/*
+ getenv wrapper for Windows
+
+ This is needed to duplicate Emacs's behavior, which is to look for enviroment
+ variables in the registry if they don't appear in the environment.
+*/
+char *
+w32_getenv (envvar)
+ char *envvar;
+{
+ char *value;
+ DWORD dwType;
+
+ if (value = getenv (envvar))
+ /* Found in the environment. */
+ return value;
+
+ if (! (value = w32_get_resource (HKEY_CURRENT_USER, envvar, &dwType)) &&
+ ! (value = w32_get_resource (HKEY_LOCAL_MACHINE, envvar, &dwType)))
+ /* Not found in the registry. */
+ return NULL;
+
+ if (dwType == REG_SZ)
+ /* Registry; no need to expand. */
+ return value;
+
+ if (dwType == REG_EXPAND_SZ)
+ {
+ DWORD size;
+
+ if (size = ExpandEnvironmentStrings (value, NULL, 0))
+ {
+ char *buffer = (char *) xmalloc (size);
+ if (ExpandEnvironmentStrings (value, buffer, size))
+ {
+ /* Found and expanded. */
+ free (value);
+ return buffer;
+ }
+
+ /* Error expanding. */
+ free (buffer);
+ }
+ }
+
+ /* Not the right type, or not correctly expanded. */
+ free (value);
+ return NULL;
+}
+
int
-w32_window_app()
+w32_window_app ()
{
static int window_app = -1;
char szTitle[MAX_PATH];
if (window_app < 0)
- window_app = (GetConsoleTitleA (szTitle, MAX_PATH) == 0);
+ {
+ /* Checking for STDOUT does not work; it's a valid handle also in
+ nonconsole apps. Testing for the console title seems to work. */
+ window_app = (GetConsoleTitleA (szTitle, MAX_PATH) == 0);
+ if (window_app)
+ InitCommonControls();
+ }
return window_app;
}
-#endif
+/*
+ execvp wrapper for Windows. Quotes arguments with embedded spaces.
+
+ This is necessary due to the broken implementation of exec* routines in
+ the Microsoft libraries: they concatenate the arguments together without
+ quoting special characters, and pass the result to CreateProcess, with
+ predictably bad results. By contrast, Posix execvp passes the arguments
+ directly into the argv array of the child process.
+*/
+int
+w32_execvp (path, argv)
+ char *path;
+ char **argv;
+{
+ int i;
+
+ /* Required to allow a .BAT script as alternate editor. */
+ argv[0] = (char *) alternate_editor;
+
+ for (i = 0; argv[i]; i++)
+ if (strchr (argv[i], ' '))
+ {
+ char *quoted = alloca (strlen (argv[i]) + 3);
+ sprintf (quoted, "\"%s\"", argv[i]);
+ argv[i] = quoted;
+ }
+
+ return execvp (path, argv);
+}
+
+#undef execvp
+#define execvp w32_execvp
+
+#endif /* WINDOWSNT */
+
+/* Display a normal or error message.
+ On Windows, use a message box if compiled as a Windows app. */
void
message (int is_error, char *message, ...)
{
int argc;
char **argv;
{
- alternate_editor = getenv ("ALTERNATE_EDITOR");
- display = getenv ("DISPLAY");
+ alternate_editor = egetenv ("ALTERNATE_EDITOR");
+#ifndef WINDOWSNT
+ display = egetenv ("DISPLAY");
if (display && strlen (display) == 0)
display = NULL;
+#endif
while (1)
{
server_file = optarg;
break;
+#ifndef WINDOWSNT
case 'd':
display = optarg;
break;
+#endif
case 'n':
nowait = 1;
case 't':
tty = 1;
+ current_frame = 0;
break;
case 'c':
- current_frame = 1;
+ current_frame = 0;
break;
case 'H':
if (!tty && display)
window_system = 1;
+#if !defined (WINDOWSNT) && !defined (HAVE_CARBON)
else
tty = 1;
+#endif
/* --no-wait implies --current-frame on ttys when there are file
arguments or expressions given. */
void
print_help_and_exit ()
{
+ /* Spaces and tabs are significant in this message; they're chosen so the
+ message aligns properly both in a tty and in a Windows message box.
+ Please try to preserve them; otherwise the output is very hard to read
+ when using emacsclientw. */
message (FALSE,
"Usage: %s [OPTIONS] FILE...\n\
Tell the Emacs server to visit the specified files.\n\
Every FILE can be either just a FILENAME or [+LINE[:COLUMN]] FILENAME.\n\
\n\
The following OPTIONS are accepted:\n\
--V, --version Just print version info and return\n\
--H, --help Print this usage information message\n\
--t, --tty Open a new Emacs frame on the current terminal\n\
--c, --current-frame Do not create a new frame; use the current Emacs frame\n\
--e, --eval Evaluate the FILE arguments as ELisp expressions\n\
--n, --no-wait Don't wait for the server to return\n\
--d, --display=DISPLAY Visit the file in the given display\n"
+-V, --version Just print version info and return\n\
+-H, --help Print this usage information message\n\
+-t, --tty Open a new Emacs frame on the current terminal\n\
+-c, --create-frame Create a new frame instead of trying to\n\
+ use the current Emacs frame\n\
+-e, --eval Evaluate the FILE arguments as ELisp expressions\n\
+-n, --no-wait Don't wait for the server to return\n"
+#ifndef WINDOWSNT
+"-d, --display=DISPLAY Visit the file in the given display\n"
+#endif
#ifndef NO_SOCKETS_IN_FILE_SYSTEM
"-s, --socket-name=FILENAME\n\
- Set filename of the UNIX socket for communication\n"
+ Set filename of the UNIX socket for communication\n"
#endif
"-f, --server-file=FILENAME\n\
- Set filename of the TCP authentication file\n\
+ Set filename of the TCP authentication file\n\
-a, --alternate-editor=EDITOR\n\
- Editor to fallback to if the server is not running\n\
+ Editor to fallback to if the server is not running\n\
\n\
Report bugs to bug-gnu-emacs@gnu.org.\n", progname);
exit (EXIT_SUCCESS);
/*
Try to run a different command, or --if no alternate editor is
defined-- exit with an errorcode.
+ Uses argv, but gets it from the global variable main_argv.
*/
void
fail (void)
if (alternate_editor)
{
int i = optind - 1;
-#ifdef WINDOWSNT
- main_argv[i] = (char *)alternate_editor;
-#endif
+
execvp (alternate_editor, main_argv + i);
message (TRUE, "%s: error executing alternate editor \"%s\"\n",
progname, alternate_editor);
int argc;
char **argv;
{
- main_argc = argc;
main_argv = argv;
progname = argv[0];
message (TRUE, "%s: Sorry, the Emacs server is supported only\n"
- "on systems with Berkeley sockets.\n",
+ "on systems with Berkeley sockets.\n",
argv[0]);
fail ();
}
# include <sys/types.h>
# include <sys/socket.h>
# include <sys/un.h>
-# include <sys/stat.h>
-# include <errno.h>
#endif
#define AUTH_KEY_LENGTH 64
/* Buffer to accumulate data to send in TCP connections. */
char send_buffer[SEND_BUFFER_SIZE + 1];
int sblen = 0; /* Fill pointer for the send buffer. */
+/* Socket used to communicate with the Emacs server process. */
+HSOCKET emacs_socket = 0;
+
+/* On Windows, the socket library was historically separate from the standard
+ C library, so errors are handled differently. */
+void
+sock_err_message (function_name)
+ char *function_name;
+{
+#ifdef WINDOWSNT
+ char* msg = NULL;
+
+ FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM
+ | FORMAT_MESSAGE_ALLOCATE_BUFFER
+ | FORMAT_MESSAGE_ARGUMENT_ARRAY,
+ NULL, WSAGetLastError (), 0, (LPTSTR)&msg, 0, NULL);
+
+ message (TRUE, "%s: %s: %s\n", progname, function_name, msg);
+
+ LocalFree (msg);
+#else
+ message (TRUE, "%s: %s: %s\n", progname, function_name, strerror (errno));
+#endif
+}
+
/* Let's send the data to Emacs when either
- the data ends in "\n", or
}
*q++ = 0;
- SEND_STRING (copy);
+ send_to_emacs (s, copy);
free (copy);
}
if (filename[0] == '\0') return FALSE;
#ifdef WINDOWSNT
- /* X:\xxx is always absolute; X:xxx is an error and will fail. */
+ /* X:\xxx is always absolute. */
if (isalpha (filename[0])
&& filename[1] == ':' && (filename[2] == '\\' || filename[2] == '/'))
return TRUE;
/* Both \xxx and \\xxx\yyy are absolute. */
if (filename[0] == '\\') return TRUE;
+
+ /*
+ FIXME: There's a corner case not dealt with, "x:y", where:
+
+ 1) x is a valid drive designation (usually a letter in the A-Z range)
+ and y is a path, relative to the current directory on drive x. This
+ is absolute, *after* fixing the y part to include the current
+ directory in x.
+
+ 2) x is a relative file name, and y is an NTFS stream name. This is a
+ correct relative path, but it is very unusual.
+
+ The trouble is that first case items are also valid examples of the
+ second case, i.e., "c:test" can be understood as drive:path or as
+ file:stream.
+
+ The "right" fix would involve checking whether
+ - the current drive/partition is NTFS,
+ - x is a valid (and accesible) drive designator,
+ - x:y already exists as a file:stream in the current directory,
+ - y already exists on the current directory of drive x,
+ - the auspices are favorable,
+ and then taking an "informed decision" based on the above.
+
+ Whatever the result, Emacs currently does a very bad job of dealing
+ with NTFS file:streams: it cannot visit them, and the only way to
+ create one is by setting `buffer-file-name' to point to it (either
+ manually or with emacsclient). So perhaps resorting to 1) and ignoring
+ 2) for now is the right thing to do.
+
+ Anyway, something to decide After the Release.
+ */
#endif
return FALSE;
}
#ifdef WINDOWSNT
-/* Wrapper to make WSACleanup a cdecl, as required by atexit(). */
+/* Wrapper to make WSACleanup a cdecl, as required by atexit. */
void
__cdecl close_winsock ()
{
if (WSAStartup (MAKEWORD (2, 0), &wsaData))
{
- message (TRUE, "%s: error initializing WinSock2", progname);
+ message (TRUE, "%s: error initializing WinSock2\n", progname);
exit (EXIT_FAILURE);
}
/*
* Read the information needed to set up a TCP comm channel with
* the Emacs server: host, port, pid and authentication string.
-*/
+ */
int
get_server_config (server, authentication)
struct sockaddr_in *server;
config = fopen (server_file, "rb");
else
{
- char *home = getenv ("HOME");
+ char *home = egetenv ("HOME");
if (home)
{
config = fopen (path, "rb");
}
#ifdef WINDOWSNT
- if (!config && (home = getenv ("APPDATA")))
+ if (!config && (home = egetenv ("APPDATA")))
{
char *path = alloca (32 + strlen (home) + strlen (server_file));
sprintf (path, "%s/.emacs.d/server/%s", home, server_file);
}
else
{
- message (TRUE, "%s: invalid configuration info", progname);
+ message (TRUE, "%s: invalid configuration info\n", progname);
exit (EXIT_FAILURE);
}
if (! fread (authentication, AUTH_KEY_LENGTH, 1, config))
{
- message (TRUE, "%s: cannot read authentication info", progname);
+ message (TRUE, "%s: cannot read authentication info\n", progname);
exit (EXIT_FAILURE);
}
*/
if ((s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
{
- message (TRUE, "%s: socket: %s\n", progname, strerror (errno));
+ sock_err_message ("socket");
return INVALID_SOCKET;
}
*/
if (connect (s, (struct sockaddr *) &server, sizeof server) < 0)
{
- message (TRUE, "%s: connect: %s\n", progname, strerror (errno));
+ sock_err_message ("connect");
return INVALID_SOCKET;
}
*/
auth_string[AUTH_KEY_LENGTH] = '\0';
- SEND_STRING ("-auth ");
- SEND_STRING (auth_string);
- SEND_STRING ("\n");
+ send_to_emacs (s, "-auth ");
+ send_to_emacs (s, auth_string);
+ send_to_emacs (s, "\n");
return s;
}
+
+/* Returns 1 if PREFIX is a prefix of STRING. */
+static int
+strprefix (char *prefix, char *string)
+{
+ return !strncmp (prefix, string, strlen (prefix));
+}
+
+
#if !defined (NO_SOCKETS_IN_FILE_SYSTEM)
/* Three possibilities:
if (tcgetpgrp (1) == getpgrp ())
{
/* We are in the foreground. */
- fprintf (out, "-resume \n");
- fflush (out);
- fsync (fileno (out));
+ send_to_emacs (emacs_socket, "-resume \n");
}
else
{
{
int old_errno = errno;
sigset_t set;
-
- if (out)
- {
- fprintf (out, "-suspend \n");
- fflush (out);
- fsync (fileno (out));
- }
+
+ if (emacs_socket)
+ send_to_emacs (emacs_socket, "-suspend \n");
/* Unblock this signal and call the default handler by temprarily
changing the handler and resignalling. */
errno = old_errno;
}
-
/* Set up signal handlers before opening a frame on the current tty. */
void
}
-
-/* Returns 1 if PREFIX is a prefix of STRING. */
-static int
-strprefix (char *prefix, char *string)
-{
- int i;
- if (! prefix)
- return 1;
-
- if (!string)
- return 0;
-
- for (i = 0; prefix[i]; i++)
- if (!string[i] || string[i] != prefix[i])
- return 0;
- return 1;
-}
-
-
HSOCKET
set_local_socket ()
{
int sock_status = 0;
int default_sock = !socket_name;
int saved_errno = 0;
-
char *server_name = "server";
if (socket_name && !index (socket_name, '/') && !index (socket_name, '\\'))
strcpy (server.sun_path, socket_name);
else
{
- message (TRUE, "%s: socket-name %s too long",
+ message (TRUE, "%s: socket-name %s too long\n",
progname, socket_name);
fail ();
}
associated with the name. This is reminiscent of the logic
that init_editfns uses to set the global Vuser_full_name. */
- char *user_name = (char *) getenv ("LOGNAME");
+ char *user_name = (char *) egetenv ("LOGNAME");
if (!user_name)
- user_name = (char *) getenv ("USER");
+ user_name = (char *) egetenv ("USER");
if (user_name)
{
strcpy (server.sun_path, socket_name);
else
{
- message (TRUE, "%s: socket-name %s too long",
+ message (TRUE, "%s: socket-name %s too long\n",
progname, socket_name);
exit (EXIT_FAILURE);
}
set_socket ()
{
HSOCKET s;
-
+
INITIALIZE ();
-
+
#ifndef NO_SOCKETS_IN_FILE_SYSTEM
/* Explicit --socket-name argument. */
if (socket_name)
s = set_local_socket ();
if ((s != INVALID_SOCKET) || alternate_editor)
return s;
- message (TRUE, "%s: error accessing socket \"%s\"",
+ message (TRUE, "%s: error accessing socket \"%s\"\n",
progname, socket_name);
exit (EXIT_FAILURE);
}
/* Explicit --server-file arg or EMACS_SERVER_FILE variable. */
if (!server_file)
- server_file = getenv ("EMACS_SERVER_FILE");
+ server_file = egetenv ("EMACS_SERVER_FILE");
if (server_file)
{
s = set_tcp_socket ();
if ((s != INVALID_SOCKET) || alternate_editor)
return s;
-
- message (TRUE, "%s: error accessing server file \"%s\"",
+
+ message (TRUE, "%s: error accessing server file \"%s\"\n",
progname, server_file);
exit (EXIT_FAILURE);
}
-
+
#ifndef NO_SOCKETS_IN_FILE_SYSTEM
/* Implicit local socket. */
s = set_local_socket ();
exit (EXIT_FAILURE);
}
+#ifdef WINDOWSNT
+FARPROC set_fg; /* Pointer to AllowSetForegroundWindow. */
+FARPROC get_wc; /* Pointer to RealGetWindowClassA. */
+
+BOOL CALLBACK
+w32_find_emacs_process (hWnd, lParam)
+ HWND hWnd;
+ LPARAM lParam;
+{
+ DWORD pid;
+ char class[6];
+
+ /* Reject any window not of class "Emacs". */
+ if (! get_wc (hWnd, class, sizeof (class))
+ || strcmp (class, "Emacs"))
+ return TRUE;
+
+ /* We only need the process id, not the thread id. */
+ (void) GetWindowThreadProcessId (hWnd, &pid);
+
+ /* Not the one we're looking for. */
+ if (pid != (DWORD) emacs_pid) return TRUE;
+
+ /* OK, let's raise it. */
+ set_fg (emacs_pid);
+
+ /* Stop enumeration. */
+ return FALSE;
+}
+
+/*
+ * Search for a window of class "Emacs" and owned by a process with
+ * process id = emacs_pid. If found, allow it to grab the focus.
+ */
+void
+w32_give_focus ()
+{
+ HMODULE hUser32;
+
+ /* It shouldn't happen when dealing with TCP sockets. */
+ if (!emacs_pid) return;
+
+ if (!(hUser32 = LoadLibrary ("user32.dll"))) return;
+
+ /* Modern Windows restrict which processes can set the foreground window.
+ emacsclient can allow Emacs to grab the focus by calling the function
+ AllowSetForegroundWindow. Unfortunately, older Windows (W95, W98 and
+ NT) lack this function, so we have to check its availability. */
+ if ((set_fg = GetProcAddress (hUser32, "AllowSetForegroundWindow"))
+ && (get_wc = GetProcAddress (hUser32, "RealGetWindowClassA")))
+ EnumWindows (w32_find_emacs_process, (LPARAM) 0);
+
+ FreeLibrary (hUser32);
+}
+#endif
+
int
main (argc, argv)
int argc;
char **argv;
{
- HSOCKET s;
int i, rl, needlf = 0;
char *cwd, *str;
char string[BUFSIZ+1];
- main_argc = argc;
main_argv = argv;
progname = argv[0];
exit (EXIT_FAILURE);
}
- if ((s = set_socket ()) == INVALID_SOCKET)
+ if ((emacs_socket = set_socket ()) == INVALID_SOCKET)
fail ();
}
#ifdef WINDOWSNT
- /*
- Modern Windows restrict which processes can set the foreground window.
- emacsclient can allow Emacs to grab the focus by calling the function
- AllowSetForegroundWindow(). Unfortunately, older Windows (W95, W98
- and NT) lack this function, so we have to check its availability.
- */
- if (emacs_pid)
- {
- HMODULE hUser32;
-
- if (hUser32 = LoadLibrary ("user32.dll"))
- {
- FARPROC set_fg;
- if (set_fg = GetProcAddress (hUser32, "AllowSetForegroundWindow"))
- set_fg (emacs_pid);
- FreeLibrary (hUser32);
- }
- }
+ w32_give_focus ();
#endif
- /* First of all, send our version number for verification. */
- SEND_STRING ("-version ");
- SEND_STRING (VERSION);
- SEND_STRING (" ");
-
/* Send over our environment. */
if (!current_frame)
{
{
char *name = xstrdup (environ[i]);
char *value = strchr (name, '=');
- SEND_STRING ("-env ");
- SEND_QUOTED (environ[i]);
- SEND_STRING (" ");
+ send_to_emacs (emacs_socket, "-env ");
+ quote_argument (emacs_socket, environ[i]);
+ send_to_emacs (emacs_socket, " ");
}
}
/* Send over our current directory. */
if (!current_frame)
{
- SEND_STRING ("-dir ");
- SEND_QUOTED (cwd);
- SEND_STRING ("/");
- SEND_STRING (" ");
+ send_to_emacs (emacs_socket, "-dir ");
+ quote_argument (emacs_socket, cwd);
+ send_to_emacs (emacs_socket, "/");
+ send_to_emacs (emacs_socket, " ");
}
retry:
if (nowait)
- SEND_STRING ("-nowait ");
+ send_to_emacs (emacs_socket, "-nowait ");
if (current_frame)
- SEND_STRING ("-current-frame ");
-
+ send_to_emacs (emacs_socket, "-current-frame ");
+
if (display)
{
- SEND_STRING ("-display ");
- SEND_QUOTED (display);
- SEND_STRING (" ");
+ send_to_emacs (emacs_socket, "-display ");
+ quote_argument (emacs_socket, display);
+ send_to_emacs (emacs_socket, " ");
}
if (tty)
{
- char *tty_name = ttyname (fileno (stdin));
- char *type = getenv ("TERM");
+ char *type = egetenv ("TERM");
+ char *tty_name = NULL;
+#ifndef WINDOWSNT
+ tty_name = ttyname (fileno (stdin));
+#endif
if (! tty_name)
{
" is not supported\n", progname);
fail ();
}
-
+#if !defined (NO_SOCKETS_IN_FILE_SYSTEM)
init_signals ();
+#endif
- SEND_STRING ("-tty ");
- SEND_QUOTED (tty_name);
- SEND_STRING (" ");
- SEND_QUOTED (type);
- SEND_STRING (" ");
+ send_to_emacs (emacs_socket, "-tty ");
+ quote_argument (emacs_socket, tty_name);
+ send_to_emacs (emacs_socket, " ");
+ quote_argument (emacs_socket, type);
+ send_to_emacs (emacs_socket, " ");
}
if (window_system)
- SEND_STRING ("-window-system ");
+ send_to_emacs (emacs_socket, "-window-system ");
if ((argc - optind > 0))
{
if (eval)
{
/* Don't prepend cwd or anything like that. */
- SEND_STRING ("-eval ");
- SEND_QUOTED (argv[i]);
- SEND_STRING (" ");
+ send_to_emacs (emacs_socket, "-eval ");
+ quote_argument (emacs_socket, argv[i]);
+ send_to_emacs (emacs_socket, " ");
continue;
}
while (isdigit ((unsigned char) *p) || *p == ':') p++;
if (*p == 0)
{
- SEND_STRING ("-position ");
- SEND_QUOTED (argv[i]);
- SEND_STRING (" ");
+ send_to_emacs (emacs_socket, "-position ");
+ quote_argument (emacs_socket, argv[i]);
+ send_to_emacs (emacs_socket, " ");
continue;
}
else
else if (! file_name_absolute_p (argv[i]))
relative = 1;
- SEND_STRING ("-file ");
+ send_to_emacs (emacs_socket, "-file ");
if (relative)
{
- SEND_QUOTED (cwd);
- SEND_STRING ("/");
+ quote_argument (emacs_socket, cwd);
+ send_to_emacs (emacs_socket, "/");
}
- SEND_QUOTED (argv[i]);
- SEND_STRING (" ");
+ quote_argument (emacs_socket, argv[i]);
+ send_to_emacs (emacs_socket, " ");
}
}
else
while ((str = fgets (string, BUFSIZ, stdin)))
{
if (eval)
- SEND_STRING ("-eval ");
+ send_to_emacs (emacs_socket, "-eval ");
else
- SEND_STRING ("-file ");
- SEND_QUOTED (out);
+ send_to_emacs (emacs_socket, "-file ");
+ quote_argument (emacs_socket, str);
}
- SEND_STRING (" ");
+ send_to_emacs (emacs_socket, " ");
}
}
- SEND_STRING ("\n");
+ send_to_emacs (emacs_socket, "\n");
/* Wait for an answer. */
if (!eval && !tty && !nowait)
fsync (1);
/* Now, wait for an answer and print any messages. */
- while ((rl = recv (s, string, BUFSIZ, 0)) > 0)
+ while ((rl = recv (emacs_socket, string, BUFSIZ, 0)) > 0)
{
char *p;
string[rl] = '\0';
while (p > string && *p == '\n')
*p-- = 0;
- if (strprefix ("-good-version ", string))
- {
- /* -good-version: The versions match. */
- }
- else if (strprefix ("-emacs-pid ", string))
+ if (strprefix ("-emacs-pid ", string))
{
/* -emacs-pid PID: The process id of the Emacs process. */
emacs_pid = strtol (string + strlen ("-emacs-pid"), NULL, 10);
fprintf (stderr, "*ERROR*: %s", str);
needlf = str[0] == '\0' ? needlf : str[strlen (str) - 1] != '\n';
}
- else if (strprefix ("-suspend ", str))
+#ifdef SIGSTOP
+ else if (strprefix ("-suspend ", string))
{
/* -suspend: Suspend this terminal, i.e., stop the process. */
if (needlf)
needlf = 0;
kill (0, SIGSTOP);
}
+#endif
else
{
/* Unknown command. */
fflush (stdout);
fsync (1);
- CLOSE_SOCKET (s);
+ CLOSE_SOCKET (emacs_socket);
return EXIT_SUCCESS;
}