* calendar/todo-mode.el: Fix two bugs.
[bpt/emacs.git] / lib-src / emacsclient.c
index 76aa218..a1177f5 100644 (file)
@@ -1,5 +1,6 @@
 /* Client process that communicates with GNU Emacs acting as server.
 /* Client process that communicates with GNU Emacs acting as server.
-   Copyright (C) 1986-1987, 1994, 1999-2011 Free Software Foundation, Inc.
+
+Copyright (C) 1986-1987, 1994, 1999-2014 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
 
 This file is part of GNU Emacs.
 
@@ -21,7 +22,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #ifdef WINDOWSNT
 
 
 #ifdef WINDOWSNT
 
-/* config.h defines these, which disables sockets altogether! */
+/* ms-w32.h defines these, which disables sockets altogether!  */
 # undef _WINSOCKAPI_
 # undef _WINSOCK_H
 
 # undef _WINSOCKAPI_
 # undef _WINSOCK_H
 
@@ -43,6 +44,10 @@ char *w32_getenv (char *);
 
 #else /* !WINDOWSNT */
 
 
 #else /* !WINDOWSNT */
 
+# ifdef HAVE_NTGUI
+# include <windows.h>
+# endif /* HAVE_NTGUI */
+
 # include "syswait.h"
 
 # ifdef HAVE_INET_SOCKETS
 # include "syswait.h"
 
 # ifdef HAVE_INET_SOCKETS
@@ -60,10 +65,6 @@ char *w32_getenv (char *);
 # define CLOSE_SOCKET close
 # define INITIALIZE()
 
 # define CLOSE_SOCKET close
 # define INITIALIZE()
 
-# ifndef WCONTINUED
-#  define WCONTINUED 8
-# endif
-
 #define egetenv(VAR) getenv(VAR)
 
 #endif /* !WINDOWSNT */
 #define egetenv(VAR) getenv(VAR)
 
 #endif /* !WINDOWSNT */
@@ -83,10 +84,7 @@ char *w32_getenv (char *);
 
 
 \f
 
 
 \f
-char *getenv (const char *), *getwd (char *);
-#ifdef HAVE_GETCWD
-char *(getcwd) (char *, size_t);
-#endif
+char *getenv (const char *);
 
 #ifndef VERSION
 #define VERSION "unspecified"
 
 #ifndef VERSION
 #define VERSION "unspecified"
@@ -101,23 +99,13 @@ char *(getcwd) (char *, size_t);
 #define EXIT_FAILURE 1
 #endif
 
 #define EXIT_FAILURE 1
 #endif
 
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-#ifndef TRUE
-#define TRUE 1
-#endif
-
 /* Additional space when allocating buffers for filenames, etc.  */
 #define EXTRA_SPACE 100
 
 /* Additional space when allocating buffers for filenames, etc.  */
 #define EXTRA_SPACE 100
 
-/* Use this to suppress gcc's `...may be used before initialized' warnings. */
-#ifdef lint
-# define IF_LINT(Code) Code
-#else
-# define IF_LINT(Code) /* empty */
+#ifdef min
+#undef min
 #endif
 #endif
+#define min(x, y) (((x) < (y)) ? (x) : (y))
 
 \f
 /* Name used to invoke this program.  */
 
 \f
 /* Name used to invoke this program.  */
@@ -141,6 +129,9 @@ int current_frame = 1;
 /* The display on which Emacs should work.  --display.  */
 const char *display = NULL;
 
 /* The display on which Emacs should work.  --display.  */
 const char *display = NULL;
 
+/* The alternate display we should try if Emacs does not support display.  */
+const char *alt_display = NULL;
+
 /* The parent window ID, if we are opening a frame via XEmbed.  */
 char *parent_id = NULL;
 
 /* The parent window ID, if we are opening a frame via XEmbed.  */
 char *parent_id = NULL;
 
@@ -152,7 +143,7 @@ int tty = 0;
 const char *alternate_editor = NULL;
 
 /* If non-NULL, the filename of the UNIX socket.  */
 const char *alternate_editor = NULL;
 
 /* If non-NULL, the filename of the UNIX socket.  */
-char *socket_name = NULL;
+const char *socket_name = NULL;
 
 /* If non-NULL, the filename of the authentication file.  */
 const char *server_file = NULL;
 
 /* If non-NULL, the filename of the authentication file.  */
 const char *server_file = NULL;
@@ -164,8 +155,7 @@ int emacs_pid = 0;
    be used for the new frame */
 const char *frame_parameters = NULL;
 
    be used for the new frame */
 const char *frame_parameters = NULL;
 
-static void print_help_and_exit (void) NO_RETURN;
-static void fail (void) NO_RETURN;
+static _Noreturn void print_help_and_exit (void);
 
 
 struct option longopts[] =
 
 
 struct option longopts[] =
@@ -184,9 +174,7 @@ struct option longopts[] =
   { "socket-name",     required_argument, NULL, 's' },
 #endif
   { "server-file",     required_argument, NULL, 'f' },
   { "socket-name",     required_argument, NULL, 's' },
 #endif
   { "server-file",     required_argument, NULL, 'f' },
-#ifndef WINDOWSNT
   { "display", required_argument, NULL, 'd' },
   { "display", required_argument, NULL, 'd' },
-#endif
   { "parent-id", required_argument, NULL, 'p' },
   { 0, 0, 0, 0 }
 };
   { "parent-id", required_argument, NULL, 'p' },
   { 0, 0, 0, 0 }
 };
@@ -209,21 +197,6 @@ xmalloc (size_t size)
 /* From sysdep.c */
 #if !defined (HAVE_GET_CURRENT_DIR_NAME) || defined (BROKEN_GET_CURRENT_DIR_NAME)
 
 /* 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
-
 char *get_current_dir_name (void);
 
 /* Return the current working directory.  Returns NULL on errors.
 char *get_current_dir_name (void);
 
 /* Return the current working directory.  Returns NULL on errors.
@@ -235,7 +208,7 @@ get_current_dir_name (void)
   char *buf;
   const char *pwd;
   struct stat dotstat, pwdstat;
   char *buf;
   const char *pwd;
   struct stat dotstat, pwdstat;
-  /* If PWD is accurate, use it instead of calling getwd.  PWD is
+  /* If PWD is accurate, use it instead of calling getcwd.  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 = egetenv ("PWD")) != 0
      sometimes a nicer name, and using it may avoid a fatal error if a
      parent directory is searchable but not readable.  */
     if ((pwd = egetenv ("PWD")) != 0
@@ -252,7 +225,6 @@ get_current_dir_name (void)
       buf = (char *) xmalloc (strlen (pwd) + 1);
       strcpy (buf, pwd);
     }
       buf = (char *) xmalloc (strlen (pwd) + 1);
       strcpy (buf, pwd);
     }
-#ifdef HAVE_GETCWD
   else
     {
       size_t buf_size = 1024;
   else
     {
       size_t buf_size = 1024;
@@ -279,20 +251,6 @@ get_current_dir_name (void)
            }
         }
     }
            }
         }
     }
-#else
-  else
-    {
-      /* We need MAXPATHLEN here.  */
-      buf = (char *) xmalloc (MAXPATHLEN + 1);
-      if (getwd (buf) == NULL)
-        {
-          int tmp_errno = errno;
-          free (buf);
-          errno = tmp_errno;
-          return NULL;
-        }
-    }
-#endif
   return buf;
 }
 #endif
   return buf;
 }
 #endif
@@ -402,32 +360,6 @@ w32_getenv (char *envvar)
   return NULL;
 }
 
   return NULL;
 }
 
-void
-w32_set_user_model_id (void)
-{
-  HMODULE shell;
-  HRESULT (WINAPI * set_user_model) (wchar_t * id);
-
-  /* On Windows 7 and later, we need to set the user model ID
-     to associate emacsclient launched files with Emacs frames
-     in the UI.  */
-  shell = LoadLibrary ("shell32.dll");
-  if (shell)
-    {
-      set_user_model
-       = (void *) GetProcAddress (shell,
-                                  "SetCurrentProcessExplicitAppUserModelID");
-      /* If the function is defined, then we are running on Windows 7
-        or newer, and the UI uses this to group related windows
-        together.  Since emacs, runemacs, emacsclient are related, we
-        want them grouped even though the executables are different,
-        so we need to set a consistent ID between them.  */
-      if (set_user_model)
-       set_user_model (L"GNU.Emacs");
-
-      FreeLibrary (shell);
-    }
-}
 
 int
 w32_window_app (void)
 
 int
 w32_window_app (void)
@@ -447,19 +379,19 @@ w32_window_app (void)
   return window_app;
 }
 
   return window_app;
 }
 
-/*
-  execvp wrapper for Windows.  Quotes arguments with embedded spaces.
+/* 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
 
   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.
-*/
+  directly into the argv array of the child process.  */
+
 int
 w32_execvp (const char *path, char **argv)
 {
   int i;
 int
 w32_execvp (const char *path, char **argv)
 {
   int i;
+  extern int execvp (const char*, char **);
 
   /* Required to allow a .BAT script as alternate editor.  */
   argv[0] = (char *) alternate_editor;
 
   /* Required to allow a .BAT script as alternate editor.  */
   argv[0] = (char *) alternate_editor;
@@ -489,9 +421,9 @@ ttyname (int fd)
 
 /* Display a normal or error message.
    On Windows, use a message box if compiled as a Windows app.  */
 
 /* Display a normal or error message.
    On Windows, use a message box if compiled as a Windows app.  */
-static void message (int, const char *, ...) ATTRIBUTE_FORMAT_PRINTF (2, 3);
+static void message (bool, const char *, ...) ATTRIBUTE_FORMAT_PRINTF (2, 3);
 static void
 static void
-message (int is_error, const char *format, ...)
+message (bool is_error, const char *format, ...)
 {
   va_list args;
 
 {
   va_list args;
 
@@ -584,7 +516,7 @@ decode_options (int argc, char **argv)
          break;
 
        case 'V':
          break;
 
        case 'V':
-         message (FALSE, "emacsclient %s\n", VERSION);
+         message (false, "emacsclient %s\n", VERSION);
          exit (EXIT_SUCCESS);
          break;
 
          exit (EXIT_SUCCESS);
          break;
 
@@ -611,7 +543,7 @@ decode_options (int argc, char **argv)
           break;
 
        default:
           break;
 
        default:
-         message (TRUE, "Try `%s --help' for more information\n", progname);
+         message (true, "Try `%s --help' for more information\n", progname);
          exit (EXIT_FAILURE);
          break;
        }
          exit (EXIT_FAILURE);
          break;
        }
@@ -622,16 +554,29 @@ decode_options (int argc, char **argv)
      Without the -c option, we used to set `display' to $DISPLAY by
      default, but this changed the default behavior and is sometimes
      inconvenient.  So we force users to use "--display $DISPLAY" if
      Without the -c option, we used to set `display' to $DISPLAY by
      default, but this changed the default behavior and is sometimes
      inconvenient.  So we force users to use "--display $DISPLAY" if
-     they want Emacs to connect to their current display.  */
+     they want Emacs to connect to their current display.
+
+     Some window systems have a notion of default display not
+     reflected in the DISPLAY variable.  If the user didn't give us an
+     explicit display, try this platform-specific after trying the
+     display in DISPLAY (if any).  */
   if (!current_frame && !tty && !display)
     {
   if (!current_frame && !tty && !display)
     {
-      display = egetenv ("DISPLAY");
-#ifdef NS_IMPL_COCOA
-      /* Under Cocoa, we don't really use displays the same way as in X,
-         so provide a dummy. */
-      if (!display || strlen (display) == 0)
-        display = "ns";
+      /* Set these here so we use a default_display only when the user
+         didn't give us an explicit display.  */
+#if defined (NS_IMPL_COCOA)
+      alt_display = "ns";
+#elif defined (HAVE_NTGUI)
+      alt_display = "w32";
 #endif
 #endif
+
+      display = egetenv ("DISPLAY");
+    }
+
+  if (!display)
+    {
+      display = alt_display;
+      alt_display = NULL;
     }
 
   /* A null-string display is invalid.  */
     }
 
   /* A null-string display is invalid.  */
@@ -642,39 +587,38 @@ decode_options (int argc, char **argv)
   if (!current_frame && !display)
     tty = 1;
 
   if (!current_frame && !display)
     tty = 1;
 
-  /* --no-wait implies --current-frame on ttys when there are file
-     arguments or expressions given.  */
-  if (nowait && tty && argc - optind > 0)
-    current_frame = 1;
-
 #ifdef WINDOWSNT
 #ifdef WINDOWSNT
+  /* Emacs on Windows does not support graphical and text terminal
+     frames in the same instance.  So, treat the -t and -c options as
+     equivalent, and open a new frame on the server's terminal.
+     Ideally, we would only set tty = 1 when the serve is running in a
+     console, but alas we don't know that.  As a workaround, always
+     ask for a tty frame, and let server.el figure it out.  */
+  if (!current_frame)
+    {
+      display = NULL;
+      tty = 1;
+    }
+
   if (alternate_editor && alternate_editor[0] == '\0')
     {
   if (alternate_editor && alternate_editor[0] == '\0')
     {
-      message (TRUE, "--alternate-editor argument or ALTERNATE_EDITOR variable cannot be\n\
+      message (true, "--alternate-editor argument or ALTERNATE_EDITOR variable cannot be\n\
 an empty string");
       exit (EXIT_FAILURE);
     }
 an empty string");
       exit (EXIT_FAILURE);
     }
-
-  /* TTY frames not supported on Windows.  Continue using GUI rather than
-     forcing the user to change their command-line.  This is required since
-     tty is set above if certain options are given and $DISPLAY is not set,
-     which is not obvious to users.  */
-  if (tty)
-      tty = 0;
-
 #endif /* WINDOWSNT */
 }
 
 \f
 #endif /* WINDOWSNT */
 }
 
 \f
-static void
+static _Noreturn void
 print_help_and_exit (void)
 {
   /* 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.  */
 print_help_and_exit (void)
 {
   /* 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\
+  message (false,
+          "Usage: %s [OPTIONS] FILE...\n%s%s%s", progname, "\
 Tell the Emacs server to visit the specified files.\n\
 Every FILE can be either just a FILENAME or [+LINE[:COLUMN]] FILENAME.\n\
 \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\
@@ -684,6 +628,7 @@ The following OPTIONS are accepted:\n\
 -nw, -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\
 -nw, -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\
+", "\
 -F ALIST, --frame-parameters=ALIST\n\
                        Set the parameters of a new frame\n\
 -e, --eval             Evaluate the FILE arguments as ELisp expressions\n\
 -F ALIST, --frame-parameters=ALIST\n\
                        Set the parameters of a new frame\n\
 -e, --eval             Evaluate the FILE arguments as ELisp expressions\n\
@@ -691,6 +636,7 @@ The following OPTIONS are accepted:\n\
 -q, --quiet            Don't display messages on success\n\
 -d DISPLAY, --display=DISPLAY\n\
                        Visit the file in the given display\n\
 -q, --quiet            Don't display messages on success\n\
 -d DISPLAY, --display=DISPLAY\n\
                        Visit the file in the given display\n\
+", "\
 --parent-id=ID          Open in parent window ID, via XEmbed\n"
 #ifndef NO_SOCKETS_IN_FILE_SYSTEM
 "-s SOCKET, --socket-name=SOCKET\n\
 --parent-id=ID          Open in parent window ID, via XEmbed\n"
 #ifndef NO_SOCKETS_IN_FILE_SYSTEM
 "-s SOCKET, --socket-name=SOCKET\n\
@@ -705,16 +651,15 @@ The following OPTIONS are accepted:\n\
                        mode and try connecting again\n"
 #endif /* not WINDOWSNT */
 "\n\
                        mode and try connecting again\n"
 #endif /* not WINDOWSNT */
 "\n\
-Report bugs with M-x report-emacs-bug.\n", progname);
+Report bugs with M-x report-emacs-bug.\n");
   exit (EXIT_SUCCESS);
 }
 
   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.
-*/
-static void
+/* 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.  */
+
+static _Noreturn void
 fail (void)
 {
   if (alternate_editor)
 fail (void)
 {
   if (alternate_editor)
@@ -722,7 +667,7 @@ fail (void)
       int i = optind - 1;
 
       execvp (alternate_editor, main_argv + i);
       int i = optind - 1;
 
       execvp (alternate_editor, main_argv + i);
-      message (TRUE, "%s: error executing alternate editor \"%s\"\n",
+      message (true, "%s: error executing alternate editor \"%s\"\n",
               progname, alternate_editor);
     }
   exit (EXIT_FAILURE);
               progname, alternate_editor);
     }
   exit (EXIT_FAILURE);
@@ -736,7 +681,7 @@ main (int argc, char **argv)
 {
   main_argv = argv;
   progname = argv[0];
 {
   main_argv = argv;
   progname = argv[0];
-  message (TRUE, "%s: Sorry, the Emacs server is supported only\n"
+  message (true, "%s: Sorry, the Emacs server is supported only\n"
           "on systems with Berkeley sockets.\n",
           argv[0]);
   fail ();
           "on systems with Berkeley sockets.\n",
           argv[0]);
   fail ();
@@ -747,16 +692,15 @@ main (int argc, char **argv)
 #define AUTH_KEY_LENGTH      64
 #define SEND_BUFFER_SIZE   4096
 
 #define AUTH_KEY_LENGTH      64
 #define SEND_BUFFER_SIZE   4096
 
-extern char *strerror (int);
-
 /* 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;
 
 /* 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.  */
+/* On Windows, the socket library was historically separate from the
+   standard C library, so errors are handled differently.  */
+
 static void
 sock_err_message (const char *function_name)
 {
 static void
 sock_err_message (const char *function_name)
 {
@@ -768,11 +712,11 @@ sock_err_message (const char *function_name)
                  | FORMAT_MESSAGE_ARGUMENT_ARRAY,
                  NULL, WSAGetLastError (), 0, (LPTSTR)&msg, 0, NULL);
 
                  | FORMAT_MESSAGE_ARGUMENT_ARRAY,
                  NULL, WSAGetLastError (), 0, (LPTSTR)&msg, 0, NULL);
 
-  message (TRUE, "%s: %s: %s\n", progname, function_name, msg);
+  message (true, "%s: %s: %s\n", progname, function_name, msg);
 
   LocalFree (msg);
 #else
 
   LocalFree (msg);
 #else
-  message (TRUE, "%s: %s: %s\n", progname, function_name, strerror (errno));
+  message (true, "%s: %s: %s\n", progname, function_name, strerror (errno));
 #endif
 }
 
 #endif
 }
 
@@ -784,33 +728,35 @@ sock_err_message (const char *function_name)
 static void
 send_to_emacs (HSOCKET s, const char *data)
 {
 static void
 send_to_emacs (HSOCKET s, const char *data)
 {
-  while (data)
+  size_t dlen;
+
+  if (!data)
+    return;
+
+  dlen = strlen (data);
+  while (*data)
     {
     {
-      size_t dlen = strlen (data);
-      if (dlen + sblen >= SEND_BUFFER_SIZE)
-       {
-         int part = SEND_BUFFER_SIZE - sblen;
-         strncpy (&send_buffer[sblen], data, part);
-         data += part;
-         sblen = SEND_BUFFER_SIZE;
-       }
-      else if (dlen)
-       {
-         strcpy (&send_buffer[sblen], data);
-         data = NULL;
-         sblen += dlen;
-       }
-      else
-       break;
+      size_t part = min (dlen, SEND_BUFFER_SIZE - sblen);
+      memcpy (&send_buffer[sblen], data, part);
+      data += part;
+      sblen += part;
 
       if (sblen == SEND_BUFFER_SIZE
          || (sblen > 0 && send_buffer[sblen-1] == '\n'))
        {
          int sent = send (s, send_buffer, sblen, 0);
 
       if (sblen == SEND_BUFFER_SIZE
          || (sblen > 0 && send_buffer[sblen-1] == '\n'))
        {
          int sent = send (s, send_buffer, sblen, 0);
+         if (sent < 0)
+           {
+             message (true, "%s: failed to send %d bytes to socket: %s\n",
+                      progname, sblen, strerror (errno));
+             fail ();
+           }
          if (sent != sblen)
          if (sent != sblen)
-           strcpy (send_buffer, &send_buffer[sent]);
+           memmove (send_buffer, &send_buffer[sent], sblen - sent);
          sblen -= sent;
        }
          sblen -= sent;
        }
+
+      dlen -= part;
     }
 }
 
     }
 }
 
@@ -859,7 +805,7 @@ quote_argument (HSOCKET s, const char *str)
 
 
 /* The inverse of quote_argument.  Removes quoting in string STR by
 
 
 /* The inverse of quote_argument.  Removes quoting in string STR by
-   modifying the string in place.   Returns STR. */
+   modifying the string in place.   Returns STR.  */
 
 static char *
 unquote_argument (char *str)
 
 static char *
 unquote_argument (char *str)
@@ -896,25 +842,25 @@ static int
 file_name_absolute_p (const char *filename)
 {
   /* Sanity check, it shouldn't happen.  */
 file_name_absolute_p (const char *filename)
 {
   /* Sanity check, it shouldn't happen.  */
-  if (! filename) return FALSE;
+  if (! filename) return false;
 
   /* /xxx is always an absolute path.  */
 
   /* /xxx is always an absolute path.  */
-  if (filename[0] == '/') return TRUE;
+  if (filename[0] == '/') return true;
 
   /* Empty filenames (which shouldn't happen) are relative.  */
 
   /* Empty filenames (which shouldn't happen) are relative.  */
-  if (filename[0] == '\0') return FALSE;
+  if (filename[0] == '\0') return false;
 
 #ifdef WINDOWSNT
   /* X:\xxx is always absolute.  */
   if (isalpha ((unsigned char) filename[0])
       && filename[1] == ':' && (filename[2] == '\\' || filename[2] == '/'))
 
 #ifdef WINDOWSNT
   /* X:\xxx is always absolute.  */
   if (isalpha ((unsigned char) filename[0])
       && filename[1] == ':' && (filename[2] == '\\' || filename[2] == '/'))
-    return TRUE;
+    return true;
 
   /* Both \xxx and \\xxx\yyy are absolute.  */
 
   /* Both \xxx and \\xxx\yyy are absolute.  */
-  if (filename[0] == '\\') return TRUE;
+  if (filename[0] == '\\') return true;
 #endif
 
 #endif
 
-  return FALSE;
+  return false;
 }
 
 #ifdef WINDOWSNT
 }
 
 #ifdef WINDOWSNT
@@ -933,7 +879,7 @@ initialize_sockets (void)
 
   if (WSAStartup (MAKEWORD (2, 0), &wsaData))
     {
 
   if (WSAStartup (MAKEWORD (2, 0), &wsaData))
     {
-      message (TRUE, "%s: error initializing WinSock2\n", progname);
+      message (true, "%s: error initializing WinSock2\n", progname);
       exit (EXIT_FAILURE);
     }
 
       exit (EXIT_FAILURE);
     }
 
@@ -942,41 +888,41 @@ initialize_sockets (void)
 #endif /* WINDOWSNT */
 
 \f
 #endif /* WINDOWSNT */
 
 \f
-/*
- * Read the information needed to set up a TCP comm channel with
- * the Emacs server: host, port, and authentication string.
- */
+/* Read the information needed to set up a TCP comm channel with
+   the Emacs server: host, port, and authentication string.  */
+
 static int
 static int
-get_server_config (struct sockaddr_in *server, char *authentication)
+get_server_config (const char *config_file, struct sockaddr_in *server,
+                  char *authentication)
 {
   char dotted[32];
   char *port;
   FILE *config = NULL;
 
 {
   char dotted[32];
   char *port;
   FILE *config = NULL;
 
-  if (file_name_absolute_p (server_file))
-    config = fopen (server_file, "rb");
+  if (file_name_absolute_p (config_file))
+    config = fopen (config_file, "rb");
   else
     {
       const char *home = egetenv ("HOME");
 
       if (home)
         {
   else
     {
       const char *home = egetenv ("HOME");
 
       if (home)
         {
-         char *path = xmalloc (strlen (home) + strlen (server_file)
+         char *path = xmalloc (strlen (home) + strlen (config_file)
                                + EXTRA_SPACE);
          strcpy (path, home);
          strcat (path, "/.emacs.d/server/");
                                + EXTRA_SPACE);
          strcpy (path, home);
          strcat (path, "/.emacs.d/server/");
-         strcat (path, server_file);
+         strcat (path, config_file);
           config = fopen (path, "rb");
          free (path);
         }
 #ifdef WINDOWSNT
       if (!config && (home = egetenv ("APPDATA")))
         {
           config = fopen (path, "rb");
          free (path);
         }
 #ifdef WINDOWSNT
       if (!config && (home = egetenv ("APPDATA")))
         {
-         char *path = xmalloc (strlen (home) + strlen (server_file)
+         char *path = xmalloc (strlen (home) + strlen (config_file)
                                + EXTRA_SPACE);
          strcpy (path, home);
          strcat (path, "/.emacs.d/server/");
                                + EXTRA_SPACE);
          strcpy (path, home);
          strcat (path, "/.emacs.d/server/");
-         strcat (path, server_file);
+         strcat (path, config_file);
           config = fopen (path, "rb");
          free (path);
         }
           config = fopen (path, "rb");
          free (path);
         }
@@ -984,14 +930,14 @@ get_server_config (struct sockaddr_in *server, char *authentication)
     }
 
   if (! config)
     }
 
   if (! config)
-    return FALSE;
+    return false;
 
   if (fgets (dotted, sizeof dotted, config)
       && (port = strchr (dotted, ':')))
     *port++ = '\0';
   else
     {
 
   if (fgets (dotted, sizeof dotted, config)
       && (port = strchr (dotted, ':')))
     *port++ = '\0';
   else
     {
-      message (TRUE, "%s: invalid configuration info\n", progname);
+      message (true, "%s: invalid configuration info\n", progname);
       exit (EXIT_FAILURE);
     }
 
       exit (EXIT_FAILURE);
     }
 
@@ -1001,42 +947,38 @@ get_server_config (struct sockaddr_in *server, char *authentication)
 
   if (! fread (authentication, AUTH_KEY_LENGTH, 1, config))
     {
 
   if (! fread (authentication, AUTH_KEY_LENGTH, 1, config))
     {
-      message (TRUE, "%s: cannot read authentication info\n", progname);
+      message (true, "%s: cannot read authentication info\n", progname);
       exit (EXIT_FAILURE);
     }
 
   fclose (config);
 
       exit (EXIT_FAILURE);
     }
 
   fclose (config);
 
-  return TRUE;
+  return true;
 }
 
 static HSOCKET
 }
 
 static HSOCKET
-set_tcp_socket (void)
+set_tcp_socket (const char *local_server_file)
 {
   HSOCKET s;
   struct sockaddr_in server;
   struct linger l_arg = {1, 1};
   char auth_string[AUTH_KEY_LENGTH + 1];
 
 {
   HSOCKET s;
   struct sockaddr_in server;
   struct linger l_arg = {1, 1};
   char auth_string[AUTH_KEY_LENGTH + 1];
 
-  if (! get_server_config (&server, auth_string))
+  if (! get_server_config (local_server_file, &server, auth_string))
     return INVALID_SOCKET;
 
   if (server.sin_addr.s_addr != inet_addr ("127.0.0.1") && !quiet)
     return INVALID_SOCKET;
 
   if (server.sin_addr.s_addr != inet_addr ("127.0.0.1") && !quiet)
-    message (FALSE, "%s: connected to remote socket at %s\n",
+    message (false, "%s: connected to remote socket at %s\n",
              progname, inet_ntoa (server.sin_addr));
 
              progname, inet_ntoa (server.sin_addr));
 
-  /*
-   * Open up an AF_INET socket
-   */
+  /* Open up an AF_INET socket.  */
   if ((s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
     {
       sock_err_message ("socket");
       return INVALID_SOCKET;
     }
 
   if ((s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
     {
       sock_err_message ("socket");
       return INVALID_SOCKET;
     }
 
-  /*
-   * Set up the socket
-   */
+  /* Set up the socket.  */
   if (connect (s, (struct sockaddr *) &server, sizeof server) < 0)
     {
       sock_err_message ("connect");
   if (connect (s, (struct sockaddr *) &server, sizeof server) < 0)
     {
       sock_err_message ("connect");
@@ -1045,9 +987,7 @@ set_tcp_socket (void)
 
   setsockopt (s, SOL_SOCKET, SO_LINGER, (char *) &l_arg, sizeof l_arg);
 
 
   setsockopt (s, SOL_SOCKET, SO_LINGER, (char *) &l_arg, sizeof l_arg);
 
-  /*
-   * Send the authentication
-   */
+  /* Send the authentication.  */
   auth_string[AUTH_KEY_LENGTH] = '\0';
 
   send_to_emacs (s, "-auth ");
   auth_string[AUTH_KEY_LENGTH] = '\0';
 
   send_to_emacs (s, "-auth ");
@@ -1081,7 +1021,7 @@ find_tty (const char **tty_type, const char **tty_name, int noabort)
        return 0;
       else
        {
        return 0;
       else
        {
-         message (TRUE, "%s: could not get terminal name\n", progname);
+         message (true, "%s: could not get terminal name\n", progname);
          fail ();
        }
     }
          fail ();
        }
     }
@@ -1092,7 +1032,7 @@ find_tty (const char **tty_type, const char **tty_name, int noabort)
        return 0;
       else
        {
        return 0;
       else
        {
-         message (TRUE, "%s: please set the TERM variable to your terminal type\n",
+         message (true, "%s: please set the TERM variable to your terminal type\n",
                   progname);
          fail ();
        }
                   progname);
          fail ();
        }
@@ -1105,7 +1045,7 @@ find_tty (const char **tty_type, const char **tty_name, int noabort)
       else
        {
          /* This causes nasty, MULTI_KBOARD-related input lockouts. */
       else
        {
          /* This causes nasty, MULTI_KBOARD-related input lockouts. */
-         message (TRUE, "%s: opening a frame in an Emacs term buffer"
+         message (true, "%s: opening a frame in an Emacs term buffer"
                   " is not supported\n", progname);
          fail ();
        }
                   " is not supported\n", progname);
          fail ();
        }
@@ -1161,16 +1101,18 @@ static void
 handle_sigcont (int signalnum)
 {
   int old_errno = errno;
 handle_sigcont (int signalnum)
 {
   int old_errno = errno;
+  pid_t pgrp = getpgrp ();
+  pid_t tcpgrp = tcgetpgrp (1);
 
 
-  if (tcgetpgrp (1) == getpgrp ())
+  if (tcpgrp == pgrp)
     {
     {
-      /* We are in the foreground. */
+      /* We are in the foreground.  */
       send_to_emacs (emacs_socket, "-resume \n");
     }
       send_to_emacs (emacs_socket, "-resume \n");
     }
-  else
+  else if (0 <= tcpgrp && tty)
     {
     {
-      /* We are in the background; cancel the continue. */
-      kill (getpid (), SIGSTOP);
+      /* We are in the background; cancel the continue.  */
+      kill (-pgrp, SIGTTIN);
     }
 
   signal (signalnum, handle_sigcont);
     }
 
   signal (signalnum, handle_sigcont);
@@ -1181,7 +1123,7 @@ handle_sigcont (int signalnum)
    going to sleep.  Normally the suspend is initiated by Emacs via
    server-handle-suspend-tty, but if the server gets out of sync with
    reality, we may get a SIGTSTP on C-z.  Handling this signal and
    going to sleep.  Normally the suspend is initiated by Emacs via
    server-handle-suspend-tty, but if the server gets out of sync with
    reality, we may get a SIGTSTP on C-z.  Handling this signal and
-   notifying Emacs about it should get things under control again. */
+   notifying Emacs about it should get things under control again.  */
 
 static void
 handle_sigtstp (int signalnum)
 
 static void
 handle_sigtstp (int signalnum)
@@ -1193,11 +1135,11 @@ handle_sigtstp (int signalnum)
     send_to_emacs (emacs_socket, "-suspend \n");
 
   /* Unblock this signal and call the default handler by temporarily
     send_to_emacs (emacs_socket, "-suspend \n");
 
   /* Unblock this signal and call the default handler by temporarily
-     changing the handler and resignalling. */
+     changing the handler and resignaling.  */
   sigprocmask (SIG_BLOCK, NULL, &set);
   sigdelset (&set, signalnum);
   signal (signalnum, SIG_DFL);
   sigprocmask (SIG_BLOCK, NULL, &set);
   sigdelset (&set, signalnum);
   signal (signalnum, SIG_DFL);
-  kill (getpid (), signalnum);
+  raise (signalnum);
   sigprocmask (SIG_SETMASK, &set, NULL); /* Let's the above signal through. */
   signal (signalnum, handle_sigtstp);
 
   sigprocmask (SIG_SETMASK, &set, NULL); /* Let's the above signal through. */
   signal (signalnum, handle_sigtstp);
 
@@ -1228,45 +1170,35 @@ init_signals (void)
 
 
 static HSOCKET
 
 
 static HSOCKET
-set_local_socket (void)
+set_local_socket (const char *local_socket_name)
 {
   HSOCKET s;
   struct sockaddr_un server;
 
 {
   HSOCKET s;
   struct sockaddr_un server;
 
-  /*
-   * Open up an AF_UNIX socket in this person's home directory
-   */
-
+  /* Open up an AF_UNIX socket in this person's home directory.  */
   if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
     {
   if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
     {
-      message (TRUE, "%s: socket: %s\n", progname, strerror (errno));
+      message (true, "%s: socket: %s\n", progname, strerror (errno));
       return INVALID_SOCKET;
     }
 
   server.sun_family = AF_UNIX;
 
   {
       return INVALID_SOCKET;
     }
 
   server.sun_family = AF_UNIX;
 
   {
-    int sock_status = 0;
-    int default_sock = !socket_name;
-    int saved_errno = 0;
-    const char *server_name = "server";
+    int sock_status;
+    int use_tmpdir = 0;
+    int saved_errno;
+    const char *server_name = local_socket_name;
     const char *tmpdir IF_LINT ( = NULL);
     char *tmpdir_storage = NULL;
     char *socket_name_storage = NULL;
 
     const char *tmpdir IF_LINT ( = NULL);
     char *tmpdir_storage = NULL;
     char *socket_name_storage = NULL;
 
-    if (socket_name && !strchr (socket_name, '/')
-       && !strchr (socket_name, '\\'))
+    if (!strchr (local_socket_name, '/') && !strchr (local_socket_name, '\\'))
       {
        /* socket_name is a file name component.  */
       {
        /* socket_name is a file name component.  */
-       server_name = socket_name;
-       socket_name = NULL;
-       default_sock = 1;       /* Try both UIDs.  */
-      }
-
-    if (default_sock)
-      {
        long uid = geteuid ();
        ptrdiff_t tmpdirlen;
        long uid = geteuid ();
        ptrdiff_t tmpdirlen;
+       use_tmpdir = 1;
        tmpdir = egetenv ("TMPDIR");
        if (!tmpdir)
           {
        tmpdir = egetenv ("TMPDIR");
        if (!tmpdir)
           {
@@ -1278,33 +1210,34 @@ set_local_socket (void)
             if (n > 0)
               {
                tmpdir = tmpdir_storage = xmalloc (n);
             if (n > 0)
               {
                tmpdir = tmpdir_storage = xmalloc (n);
-                confstr (_CS_DARWIN_USER_TEMP_DIR, tmpdir, n);
+               confstr (_CS_DARWIN_USER_TEMP_DIR, tmpdir_storage, n);
               }
             else
 #endif
               tmpdir = "/tmp";
           }
        tmpdirlen = strlen (tmpdir);
               }
             else
 #endif
               tmpdir = "/tmp";
           }
        tmpdirlen = strlen (tmpdir);
-       socket_name = socket_name_storage =
+       socket_name_storage =
          xmalloc (tmpdirlen + strlen (server_name) + EXTRA_SPACE);
          xmalloc (tmpdirlen + strlen (server_name) + EXTRA_SPACE);
-       strcpy (socket_name, tmpdir);
-       sprintf (socket_name + tmpdirlen, "/emacs%ld/", uid);
-       strcat (socket_name + tmpdirlen, server_name);
+       strcpy (socket_name_storage, tmpdir);
+       sprintf (socket_name_storage + tmpdirlen, "/emacs%ld/", uid);
+       strcat (socket_name_storage + tmpdirlen, server_name);
+       local_socket_name = socket_name_storage;
       }
 
       }
 
-    if (strlen (socket_name) < sizeof (server.sun_path))
-      strcpy (server.sun_path, socket_name);
+    if (strlen (local_socket_name) < sizeof (server.sun_path))
+      strcpy (server.sun_path, local_socket_name);
     else
       {
     else
       {
-        message (TRUE, "%s: socket-name %s too long\n",
-                 progname, socket_name);
+        message (true, "%s: socket-name %s too long\n",
+                 progname, local_socket_name);
         fail ();
       }
 
     /* See if the socket exists, and if it's owned by us. */
     sock_status = socket_status (server.sun_path);
     saved_errno = errno;
         fail ();
       }
 
     /* See if the socket exists, and if it's owned by us. */
     sock_status = socket_status (server.sun_path);
     saved_errno = errno;
-    if (sock_status && default_sock)
+    if (sock_status && use_tmpdir)
       {
        /* Failing that, see if LOGNAME or USER exist and differ from
           our euid.  If so, look for a socket based on the UID
       {
        /* Failing that, see if LOGNAME or USER exist and differ from
           our euid.  If so, look for a socket based on the UID
@@ -1325,21 +1258,21 @@ set_local_socket (void)
                /* We're running under su, apparently. */
                long uid = pw->pw_uid;
                ptrdiff_t tmpdirlen = strlen (tmpdir);
                /* We're running under su, apparently. */
                long uid = pw->pw_uid;
                ptrdiff_t tmpdirlen = strlen (tmpdir);
-               socket_name = xmalloc (tmpdirlen + strlen (server_name)
-                                      + EXTRA_SPACE);
-               strcpy (socket_name, tmpdir);
-               sprintf (socket_name + tmpdirlen, "/emacs%ld/", uid);
-               strcat (socket_name + tmpdirlen, server_name);
-
-               if (strlen (socket_name) < sizeof (server.sun_path))
-                 strcpy (server.sun_path, socket_name);
+               char *user_socket_name
+                 = xmalloc (tmpdirlen + strlen (server_name) + EXTRA_SPACE);
+               strcpy (user_socket_name, tmpdir);
+               sprintf (user_socket_name + tmpdirlen, "/emacs%ld/", uid);
+               strcat (user_socket_name + tmpdirlen, server_name);
+
+               if (strlen (user_socket_name) < sizeof (server.sun_path))
+                 strcpy (server.sun_path, user_socket_name);
                else
                  {
                else
                  {
-                   message (TRUE, "%s: socket-name %s too long\n",
-                            progname, socket_name);
+                   message (true, "%s: socket-name %s too long\n",
+                            progname, user_socket_name);
                    exit (EXIT_FAILURE);
                  }
                    exit (EXIT_FAILURE);
                  }
-               free (socket_name);
+               free (user_socket_name);
 
                sock_status = socket_status (server.sun_path);
                 saved_errno = errno;
 
                sock_status = socket_status (server.sun_path);
                 saved_errno = errno;
@@ -1359,7 +1292,7 @@ set_local_socket (void)
           we are root. */
        if (0 != geteuid ())
          {
           we are root. */
        if (0 != geteuid ())
          {
-           message (TRUE, "%s: Invalid socket owner\n", progname);
+           message (true, "%s: Invalid socket owner\n", progname);
            return INVALID_SOCKET;
          }
        break;
            return INVALID_SOCKET;
          }
        break;
@@ -1367,12 +1300,12 @@ set_local_socket (void)
       case 2:
        /* `stat' failed */
        if (saved_errno == ENOENT)
       case 2:
        /* `stat' failed */
        if (saved_errno == ENOENT)
-         message (TRUE,
+         message (true,
                   "%s: can't find socket; have you started the server?\n\
 To start the server in Emacs, type \"M-x server-start\".\n",
                   progname);
        else
                   "%s: can't find socket; have you started the server?\n\
 To start the server in Emacs, type \"M-x server-start\".\n",
                   progname);
        else
-         message (TRUE, "%s: can't stat %s: %s\n",
+         message (true, "%s: can't stat %s: %s\n",
                   progname, server.sun_path, strerror (saved_errno));
        return INVALID_SOCKET;
       }
                   progname, server.sun_path, strerror (saved_errno));
        return INVALID_SOCKET;
       }
@@ -1381,7 +1314,7 @@ To start the server in Emacs, type \"M-x server-start\".\n",
   if (connect (s, (struct sockaddr *) &server, strlen (server.sun_path) + 2)
       < 0)
     {
   if (connect (s, (struct sockaddr *) &server, strlen (server.sun_path) + 2)
       < 0)
     {
-      message (TRUE, "%s: connect: %s\n", progname, strerror (errno));
+      message (true, "%s: connect: %s\n", progname, strerror (errno));
       return INVALID_SOCKET;
     }
 
       return INVALID_SOCKET;
     }
 
@@ -1393,6 +1326,7 @@ static HSOCKET
 set_socket (int no_exit_if_error)
 {
   HSOCKET s;
 set_socket (int no_exit_if_error)
 {
   HSOCKET s;
+  const char *local_server_file = server_file;
 
   INITIALIZE ();
 
 
   INITIALIZE ();
 
@@ -1400,45 +1334,44 @@ set_socket (int no_exit_if_error)
   /* Explicit --socket-name argument.  */
   if (socket_name)
     {
   /* Explicit --socket-name argument.  */
   if (socket_name)
     {
-      s = set_local_socket ();
+      s = set_local_socket (socket_name);
       if ((s != INVALID_SOCKET) || no_exit_if_error)
        return s;
       if ((s != INVALID_SOCKET) || no_exit_if_error)
        return s;
-      message (TRUE, "%s: error accessing socket \"%s\"\n",
+      message (true, "%s: error accessing socket \"%s\"\n",
               progname, socket_name);
       exit (EXIT_FAILURE);
     }
 #endif
 
   /* Explicit --server-file arg or EMACS_SERVER_FILE variable.  */
               progname, socket_name);
       exit (EXIT_FAILURE);
     }
 #endif
 
   /* Explicit --server-file arg or EMACS_SERVER_FILE variable.  */
-  if (!server_file)
-    server_file = egetenv ("EMACS_SERVER_FILE");
+  if (!local_server_file)
+    local_server_file = egetenv ("EMACS_SERVER_FILE");
 
 
-  if (server_file)
+  if (local_server_file)
     {
     {
-      s = set_tcp_socket ();
+      s = set_tcp_socket (local_server_file);
       if ((s != INVALID_SOCKET) || no_exit_if_error)
        return s;
 
       if ((s != INVALID_SOCKET) || no_exit_if_error)
        return s;
 
-      message (TRUE, "%s: error accessing server file \"%s\"\n",
-              progname, server_file);
+      message (true, "%s: error accessing server file \"%s\"\n",
+              progname, local_server_file);
       exit (EXIT_FAILURE);
     }
 
 #ifndef NO_SOCKETS_IN_FILE_SYSTEM
   /* Implicit local socket.  */
       exit (EXIT_FAILURE);
     }
 
 #ifndef NO_SOCKETS_IN_FILE_SYSTEM
   /* Implicit local socket.  */
-  s = set_local_socket ();
+  s = set_local_socket ("server");
   if (s != INVALID_SOCKET)
     return s;
 #endif
 
   /* Implicit server file.  */
   if (s != INVALID_SOCKET)
     return s;
 #endif
 
   /* Implicit server file.  */
-  server_file = "server";
-  s = set_tcp_socket ();
+  s = set_tcp_socket ("server");
   if ((s != INVALID_SOCKET) || no_exit_if_error)
     return s;
 
   /* No implicit or explicit socket, and no alternate editor.  */
   if ((s != INVALID_SOCKET) || no_exit_if_error)
     return s;
 
   /* No implicit or explicit socket, and no alternate editor.  */
-  message (TRUE, "%s: No socket or alternate editor.  Please use:\n\n"
+  message (true, "%s: No socket or alternate editor.  Please use:\n\n"
 #ifndef NO_SOCKETS_IN_FILE_SYSTEM
 "\t--socket-name\n"
 #endif
 #ifndef NO_SOCKETS_IN_FILE_SYSTEM
 "\t--socket-name\n"
 #endif
@@ -1448,10 +1381,37 @@ set_socket (int no_exit_if_error)
   exit (EXIT_FAILURE);
 }
 
   exit (EXIT_FAILURE);
 }
 
-#ifdef WINDOWSNT
+#ifdef HAVE_NTGUI
 FARPROC set_fg;  /* Pointer to AllowSetForegroundWindow.  */
 FARPROC get_wc;  /* Pointer to RealGetWindowClassA.  */
 
 FARPROC set_fg;  /* Pointer to AllowSetForegroundWindow.  */
 FARPROC get_wc;  /* Pointer to RealGetWindowClassA.  */
 
+void
+w32_set_user_model_id (void)
+{
+  HMODULE shell;
+  HRESULT (WINAPI * set_user_model) (wchar_t * id);
+
+  /* On Windows 7 and later, we need to set the user model ID
+     to associate emacsclient launched files with Emacs frames
+     in the UI.  */
+  shell = LoadLibrary ("shell32.dll");
+  if (shell)
+    {
+      set_user_model
+       = (void *) GetProcAddress (shell,
+                                  "SetCurrentProcessExplicitAppUserModelID");
+      /* If the function is defined, then we are running on Windows 7
+        or newer, and the UI uses this to group related windows
+        together.  Since emacs, runemacs, emacsclient are related, we
+        want them grouped even though the executables are different,
+        so we need to set a consistent ID between them.  */
+      if (set_user_model)
+       set_user_model (L"GNU.Emacs");
+
+      FreeLibrary (shell);
+    }
+}
+
 BOOL CALLBACK
 w32_find_emacs_process (HWND hWnd, LPARAM lParam)
 {
 BOOL CALLBACK
 w32_find_emacs_process (HWND hWnd, LPARAM lParam)
 {
@@ -1476,10 +1436,9 @@ w32_find_emacs_process (HWND hWnd, LPARAM lParam)
   return FALSE;
 }
 
   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.
- */
+/* 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 (void)
 {
 void
 w32_give_focus (void)
 {
@@ -1501,7 +1460,7 @@ w32_give_focus (void)
       && (get_wc = GetProcAddress (user32, "RealGetWindowClassA")))
     EnumWindows (w32_find_emacs_process, (LPARAM) 0);
 }
       && (get_wc = GetProcAddress (user32, "RealGetWindowClassA")))
     EnumWindows (w32_find_emacs_process, (LPARAM) 0);
 }
-#endif
+#endif /* HAVE_NTGUI */
 
 /* Start the emacs daemon and try to connect to it.  */
 
 
 /* Start the emacs daemon and try to connect to it.  */
 
@@ -1521,15 +1480,15 @@ start_daemon_and_retry_set_socket (void)
 
       if ((w == -1) || !WIFEXITED (status) || WEXITSTATUS (status))
        {
 
       if ((w == -1) || !WIFEXITED (status) || WEXITSTATUS (status))
        {
-         message (TRUE, "Error: Could not start the Emacs daemon\n");
+         message (true, "Error: Could not start the Emacs daemon\n");
          exit (EXIT_FAILURE);
        }
 
       /* Try connecting, the daemon should have started by now.  */
          exit (EXIT_FAILURE);
        }
 
       /* Try connecting, the daemon should have started by now.  */
-      message (TRUE, "Emacs daemon should have started, trying to connect again\n");
+      message (true, "Emacs daemon should have started, trying to connect again\n");
       if ((emacs_socket = set_socket (1)) == INVALID_SOCKET)
        {
       if ((emacs_socket = set_socket (1)) == INVALID_SOCKET)
        {
-         message (TRUE, "Error: Cannot connect even after starting the Emacs daemon\n");
+         message (true, "Error: Cannot connect even after starting the Emacs daemon\n");
          exit (EXIT_FAILURE);
        }
     }
          exit (EXIT_FAILURE);
        }
     }
@@ -1542,7 +1501,10 @@ start_daemon_and_retry_set_socket (void)
     {
       char emacs[] = "emacs";
       char daemon_option[] = "--daemon";
     {
       char emacs[] = "emacs";
       char daemon_option[] = "--daemon";
-      char *d_argv[] = {emacs, daemon_option, 0 };
+      char *d_argv[3];
+      d_argv[0] = emacs;
+      d_argv[1] = daemon_option;
+      d_argv[2] = 0;
       if (socket_name != NULL)
        {
          /* Pass  --daemon=socket_name as argument.  */
       if (socket_name != NULL)
        {
          /* Pass  --daemon=socket_name as argument.  */
@@ -1554,7 +1516,7 @@ start_daemon_and_retry_set_socket (void)
          d_argv[1] = daemon_arg;
        }
       execvp ("emacs", d_argv);
          d_argv[1] = daemon_arg;
        }
       execvp ("emacs", d_argv);
-      message (TRUE, "%s: error starting emacs daemon\n", progname);
+      message (true, "%s: error starting emacs daemon\n", progname);
     }
 #endif /* WINDOWSNT */
 }
     }
 #endif /* WINDOWSNT */
 }
@@ -1565,43 +1527,45 @@ main (int argc, char **argv)
   int rl = 0, needlf = 0;
   char *cwd, *str;
   char string[BUFSIZ+1];
   int rl = 0, needlf = 0;
   char *cwd, *str;
   char string[BUFSIZ+1];
-  int null_socket_name IF_LINT ( = 0);
-  int null_server_file IF_LINT ( = 0);
   int start_daemon_if_needed;
   int exit_status = EXIT_SUCCESS;
 
   main_argv = argv;
   progname = argv[0];
 
   int start_daemon_if_needed;
   int exit_status = EXIT_SUCCESS;
 
   main_argv = argv;
   progname = argv[0];
 
-#ifdef WINDOWSNT
-  /* On Windows 7 and later, we need to explicitly associate emacsclient
-     with emacs so the UI behaves sensibly.  */
+#ifdef HAVE_NTGUI
+  /* On Windows 7 and later, we need to explicitly associate
+     emacsclient with emacs so the UI behaves sensibly.  This
+     association does no harm if we're not actually connecting to an
+     Emacs using a window display.  */
   w32_set_user_model_id ();
   w32_set_user_model_id ();
-#endif
+#endif /* HAVE_NTGUI */
 
   /* Process options.  */
   decode_options (argc, argv);
 
   if ((argc - optind < 1) && !eval && current_frame)
     {
 
   /* Process options.  */
   decode_options (argc, argv);
 
   if ((argc - optind < 1) && !eval && current_frame)
     {
-      message (TRUE, "%s: file name or argument required\n"
+      message (true, "%s: file name or argument required\n"
               "Try `%s --help' for more information\n",
               progname, progname);
       exit (EXIT_FAILURE);
     }
 
               "Try `%s --help' for more information\n",
               progname, progname);
       exit (EXIT_FAILURE);
     }
 
+#ifndef WINDOWSNT
+  if (tty)
+    {
+      pid_t pgrp = getpgrp ();
+      pid_t tcpgrp = tcgetpgrp (1);
+      if (0 <= tcpgrp && tcpgrp != pgrp)
+       kill (-pgrp, SIGTTIN);
+    }
+#endif /* !WINDOWSNT */
+
   /* If alternate_editor is the empty string, start the emacs daemon
      in case of failure to connect.  */
   start_daemon_if_needed = (alternate_editor
                            && (alternate_editor[0] == '\0'));
   /* If alternate_editor is the empty string, start the emacs daemon
      in case of failure to connect.  */
   start_daemon_if_needed = (alternate_editor
                            && (alternate_editor[0] == '\0'));
-  if (start_daemon_if_needed)
-    {
-      /* set_socket changes the values for socket_name and
-        server_file, we need to reset them, if they were NULL before
-        for the second call to set_socket.  */
-      null_socket_name = (socket_name == NULL);
-      null_server_file = (server_file == NULL);
-    }
 
   emacs_socket = set_socket (alternate_editor || start_daemon_if_needed);
   if (emacs_socket == INVALID_SOCKET)
 
   emacs_socket = set_socket (alternate_editor || start_daemon_if_needed);
   if (emacs_socket == INVALID_SOCKET)
@@ -1609,33 +1573,25 @@ main (int argc, char **argv)
       if (! start_daemon_if_needed)
        fail ();
 
       if (! start_daemon_if_needed)
        fail ();
 
-      /* Reset socket_name and server_file if they were NULL
-        before the set_socket call.  */
-      if (null_socket_name)
-       socket_name = NULL;
-      if (null_server_file)
-       server_file = NULL;
-
       start_daemon_and_retry_set_socket ();
     }
 
   cwd = get_current_dir_name ();
   if (cwd == 0)
     {
       start_daemon_and_retry_set_socket ();
     }
 
   cwd = get_current_dir_name ();
   if (cwd == 0)
     {
-      /* getwd puts message in STRING if it fails.  */
-      message (TRUE, "%s: %s\n", progname,
+      message (true, "%s: %s\n", progname,
               "Cannot get current working directory");
       fail ();
     }
 
               "Cannot get current working directory");
       fail ();
     }
 
-#ifdef WINDOWSNT
+#ifdef HAVE_NTGUI
+  if (display && !strcmp (display, "w32"))
   w32_give_focus ();
   w32_give_focus ();
-#endif
+#endif /* HAVE_NTGUI */
 
   /* Send over our environment and current directory. */
   if (!current_frame)
     {
 
   /* Send over our environment and current directory. */
   if (!current_frame)
     {
-      extern char **environ;
       int i;
       for (i = 0; environ[i]; i++)
         {
       int i;
       for (i = 0; environ[i]; i++)
         {
@@ -1677,10 +1633,10 @@ main (int argc, char **argv)
       send_to_emacs (emacs_socket, " ");
     }
 
       send_to_emacs (emacs_socket, " ");
     }
 
-  /* If using the current frame, send tty information to Emacs anyway.
-     In daemon mode, Emacs may need to occupy this tty if no other
-     frame is available.  */
-  if (tty || (current_frame && !eval))
+  /* Unless we are certain we don't want to occupy the tty, send our
+     tty information to Emacs.  For example, in daemon mode Emacs may
+     need to occupy this tty if no other frame is available.  */
+  if (!current_frame || !eval)
     {
       const char *tty_type, *tty_name;
 
     {
       const char *tty_type, *tty_name;
 
@@ -1773,12 +1729,13 @@ main (int argc, char **argv)
       needlf = 2;
     }
   fflush (stdout);
       needlf = 2;
     }
   fflush (stdout);
-  fsync (1);
+  while (fdatasync (1) != 0 && errno == EINTR)
+    continue;
 
   /* Now, wait for an answer and print any messages.  */
   while (exit_status == EXIT_SUCCESS)
     {
 
   /* Now, wait for an answer and print any messages.  */
   while (exit_status == EXIT_SUCCESS)
     {
-      char *p;
+      char *p, *end_p;
       do
         {
           errno = 0;
       do
         {
           errno = 0;
@@ -1793,67 +1750,89 @@ main (int argc, char **argv)
 
       string[rl] = '\0';
 
 
       string[rl] = '\0';
 
-      p = string + strlen (string) - 1;
-      while (p > string && *p == '\n')
-        *p-- = 0;
+      /* Loop over all NL-terminated messages.  */
+      for (end_p = p = string; end_p != NULL && *end_p != '\0'; p = end_p)
+       {
+         end_p = strchr (p, '\n');
+         if (end_p != NULL)
+           *end_p++ = '\0';
 
 
-      if (strprefix ("-emacs-pid ", string))
-        {
-          /* -emacs-pid PID: The process id of the Emacs process. */
-          emacs_pid = strtol (string + strlen ("-emacs-pid"), NULL, 10);
-        }
-      else if (strprefix ("-window-system-unsupported ", string))
-        {
-          /* -window-system-unsupported: Emacs was compiled without X
-              support.  Try again on the terminal. */
-          nowait = 0;
-          tty = 1;
-          goto retry;
-        }
-      else if (strprefix ("-print ", string))
-        {
-          /* -print STRING: Print STRING on the terminal. */
-          str = unquote_argument (string + strlen ("-print "));
-          if (needlf)
-            printf ("\n");
-          printf ("%s", str);
-          needlf = str[0] == '\0' ? needlf : str[strlen (str) - 1] != '\n';
-        }
-      else if (strprefix ("-error ", string))
-        {
-          /* -error DESCRIPTION: Signal an error on the terminal. */
-          str = unquote_argument (string + strlen ("-error "));
-          if (needlf)
-            printf ("\n");
-          fprintf (stderr, "*ERROR*: %s", str);
-          needlf = str[0] == '\0' ? needlf : str[strlen (str) - 1] != '\n';
-         exit_status = EXIT_FAILURE;
-        }
+          if (strprefix ("-emacs-pid ", p))
+            {
+              /* -emacs-pid PID: The process id of the Emacs process. */
+              emacs_pid = strtol (p + strlen ("-emacs-pid"), NULL, 10);
+            }
+          else if (strprefix ("-window-system-unsupported ", p))
+            {
+              /* -window-system-unsupported: Emacs was compiled without support
+                 for whatever window system we tried.  Try the alternate
+                 display, or, failing that, try the terminal.  */
+              if (alt_display)
+                {
+                  display = alt_display;
+                  alt_display = NULL;
+                }
+              else
+                {
+                  nowait = 0;
+                  tty = 1;
+                }
+
+              goto retry;
+            }
+          else if (strprefix ("-print ", p))
+            {
+              /* -print STRING: Print STRING on the terminal. */
+              str = unquote_argument (p + strlen ("-print "));
+              if (needlf)
+                printf ("\n");
+              printf ("%s", str);
+              needlf = str[0] == '\0' ? needlf : str[strlen (str) - 1] != '\n';
+            }
+          else if (strprefix ("-print-nonl ", p))
+            {
+              /* -print-nonl STRING: Print STRING on the terminal.
+                 Used to continue a preceding -print command.  */
+              str = unquote_argument (p + strlen ("-print-nonl "));
+              printf ("%s", str);
+              needlf = str[0] == '\0' ? needlf : str[strlen (str) - 1] != '\n';
+            }
+          else if (strprefix ("-error ", p))
+            {
+              /* -error DESCRIPTION: Signal an error on the terminal. */
+              str = unquote_argument (p + strlen ("-error "));
+              if (needlf)
+                printf ("\n");
+              fprintf (stderr, "*ERROR*: %s", str);
+              needlf = str[0] == '\0' ? needlf : str[strlen (str) - 1] != '\n';
+              exit_status = EXIT_FAILURE;
+            }
 #ifdef SIGSTOP
 #ifdef SIGSTOP
-      else if (strprefix ("-suspend ", string))
-        {
-          /* -suspend: Suspend this terminal, i.e., stop the process. */
-          if (needlf)
-            printf ("\n");
-          needlf = 0;
-          kill (0, SIGSTOP);
-        }
+         else if (strprefix ("-suspend ", p))
+           {
+             /* -suspend: Suspend this terminal, i.e., stop the process. */
+             if (needlf)
+               printf ("\n");
+             needlf = 0;
+             kill (0, SIGSTOP);
+           }
 #endif
 #endif
-      else
-        {
-          /* Unknown command. */
-          if (needlf)
-            printf ("\n");
-          printf ("*ERROR*: Unknown message: %s", string);
-          needlf = string[0]
-           == '\0' ? needlf : string[strlen (string) - 1] != '\n';
-        }
+         else
+           {
+             /* Unknown command. */
+             if (needlf)
+               printf ("\n");
+             needlf = 0;
+             printf ("*ERROR*: Unknown message: %s\n", p);
+           }
+       }
     }
 
   if (needlf)
     printf ("\n");
   fflush (stdout);
     }
 
   if (needlf)
     printf ("\n");
   fflush (stdout);
-  fsync (1);
+  while (fdatasync (1) != 0 && errno == EINTR)
+    continue;
 
   if (rl < 0)
     exit_status = EXIT_FAILURE;
 
   if (rl < 0)
     exit_status = EXIT_FAILURE;
@@ -1863,22 +1842,3 @@ main (int argc, char **argv)
 }
 
 #endif /* HAVE_SOCKETS && HAVE_INET_SOCKETS */
 }
 
 #endif /* HAVE_SOCKETS && HAVE_INET_SOCKETS */
-
-\f
-#ifndef HAVE_STRERROR
-char *
-strerror (errnum)
-     int errnum;
-{
-  extern char *sys_errlist[];
-  extern int sys_nerr;
-
-  if (errnum >= 0 && errnum < sys_nerr)
-    return sys_errlist[errnum];
-  return (char *) "Unknown error";
-}
-
-#endif /* ! HAVE_STRERROR */
-
-
-/* emacsclient.c ends here */