/* Client process that communicates with GNU Emacs acting as server.
Copyright (C) 1986, 1987, 1994, 1999, 2000, 2001, 2002, 2003, 2004,
- 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+ 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
This file is part of GNU Emacs.
#else /* !WINDOWSNT */
-# include <sys/types.h>
+# include "syswait.h"
# ifdef HAVE_INET_SOCKETS
# include <netinet/in.h>
# endif
+# include <arpa/inet.h>
+
# define INVALID_SOCKET -1
# define HSOCKET int
# define CLOSE_SOCKET close
# define INITIALIZE()
+# ifndef WCONTINUED
+# define WCONTINUED 8
+# endif
+
#endif /* !WINDOWSNT */
#undef signal
inconvenient. So we force users to use "--display $DISPLAY" if
they want Emacs to connect to their current display. */
if (!current_frame && !tty && !display)
- display = egetenv ("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";
+#endif
+ }
/* A null-string display is invalid. */
if (display && strlen (display) == 0)
arguments or expressions given. */
if (nowait && tty && argc - optind > 0)
current_frame = 1;
+
+#ifdef WINDOWSNT
+ if (alternate_editor && alternate_editor[0] == '\0')
+ {
+ message (TRUE, "--alternate-editor argument or ALTERNATE_EDITOR variable cannot be\n\
+an empty string");
+ exit (EXIT_FAILURE);
+ }
+#endif /* WINDOWSNT */
}
\f
"-f, --server-file=FILENAME\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\
-\n\
+ Editor to fallback to if the server is not running\n"
+#ifdef WINDOWSNT
+" If EDITOR is the empty string, start Emacs in daemon\n\
+ mode and try connecting again\n"
+#endif /* WINDOWSNT */
+"\n\
Report bugs to bug-gnu-emacs@gnu.org.\n", progname);
exit (EXIT_SUCCESS);
}
#endif /* ! NO_SOCKETS_IN_FILE_SYSTEM */
HSOCKET
-set_socket ()
+set_socket (int no_exit_if_error)
{
HSOCKET s;
if (socket_name)
{
s = set_local_socket ();
- if ((s != INVALID_SOCKET) || alternate_editor)
+ if ((s != INVALID_SOCKET) || no_exit_if_error)
return s;
message (TRUE, "%s: error accessing socket \"%s\"\n",
progname, socket_name);
if (server_file)
{
s = set_tcp_socket ();
- if ((s != INVALID_SOCKET) || alternate_editor)
+ if ((s != INVALID_SOCKET) || no_exit_if_error)
return s;
message (TRUE, "%s: error accessing server file \"%s\"\n",
/* Implicit server file. */
server_file = "server";
s = set_tcp_socket ();
- if ((s != INVALID_SOCKET) || alternate_editor)
+ if ((s != INVALID_SOCKET) || no_exit_if_error)
return s;
/* No implicit or explicit socket, and no alternate editor. */
}
#endif
+/* Start the emacs daemon and try to connect to it. */
+
+void
+start_daemon_and_retry_set_socket (void)
+{
+#ifndef WINDOWSNT
+ pid_t dpid;
+ int status;
+
+ dpid = fork ();
+
+ if (dpid > 0)
+ {
+ pid_t w;
+ w = waitpid (dpid, &status, WUNTRACED | WCONTINUED);
+
+ if ((w == -1) || !WIFEXITED (status) || WEXITSTATUS(status))
+ {
+ message (TRUE, "Error: Could not start the Emacs daemon\n");
+ exit (EXIT_FAILURE);
+ }
+
+ /* Try connecting, the daemon should have started by now. */
+ message (TRUE, "Emacs daemon should have started, trying to connect again\n");
+ if ((emacs_socket = set_socket (1)) == INVALID_SOCKET)
+ {
+ message (TRUE, "Error: Cannot connect even after starting the Emacs daemon\n");
+ exit (EXIT_FAILURE);
+ }
+ }
+ else if (dpid < 0)
+ {
+ fprintf (stderr, "Error: Cannot fork!\n");
+ exit (1);
+ }
+ else
+ {
+ char *d_argv[] = {"emacs", "--daemon", 0 };
+ if (socket_name != NULL)
+ {
+ /* Pass --daemon=socket_name as argument. */
+ char *deq = "--daemon=";
+ char *daemon_arg = alloca (strlen (deq)
+ + strlen (socket_name) + 1);
+ strcpy (daemon_arg, deq);
+ strcat (daemon_arg, socket_name);
+ d_argv[1] = daemon_arg;
+ }
+ execvp ("emacs", d_argv);
+ message (TRUE, "%s: error starting emacs daemon\n", progname);
+ }
+#endif /* WINDOWSNT */
+}
+
int
main (argc, argv)
int argc;
int i, rl, needlf = 0;
char *cwd, *str;
char string[BUFSIZ+1];
+ int null_socket_name, null_server_file, start_daemon_if_needed;
main_argv = argv;
progname = argv[0];
exit (EXIT_FAILURE);
}
- if ((emacs_socket = set_socket ()) == INVALID_SOCKET)
- fail ();
+ /* 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);
+ }
+ if ((emacs_socket = set_socket (alternate_editor
+ || start_daemon_if_needed)) == INVALID_SOCKET)
+ if (start_daemon_if_needed)
+ {
+ /* 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 ();
+ }
+ else
+ fail ();
cwd = get_current_dir_name ();
if (cwd == 0)
quote_argument (emacs_socket, environ[i]);
send_to_emacs (emacs_socket, " ");
}
- send_to_emacs (emacs_socket, "-dir ");
- quote_argument (emacs_socket, cwd);
- send_to_emacs (emacs_socket, "/");
- send_to_emacs (emacs_socket, " ");
}
+ send_to_emacs (emacs_socket, "-dir ");
+ quote_argument (emacs_socket, cwd);
+ send_to_emacs (emacs_socket, "/");
+ send_to_emacs (emacs_socket, " ");
retry:
if (nowait)
{
for (i = optind; i < argc; i++)
{
- int relative = 0;
if (eval)
{
send_to_emacs (emacs_socket, " ");
continue;
}
- else
- relative = 1;
}
- else if (! file_name_absolute_p (argv[i]))
-#ifndef WINDOWSNT
- relative = 1;
-#else
- /* Call GetFullPathName so filenames of the form X:Y, where X is
- a valid drive designator, are interpreted as drive:path, not
- file:stream, and treated as absolute.
- The user can still pass a file:stream if desired (for example,
- .\X:Y), but it is not very useful, as Emacs currently does a
- very bad job of dealing with NTFS streams. */
- {
- char *filename = (char *) xmalloc (MAX_PATH);
- DWORD size;
-
- size = GetFullPathName (argv[i], MAX_PATH, filename, NULL);
- if (size > 0 && size < MAX_PATH)
- argv[i] = filename;
- else
- {
- relative = 1;
- free (filename);
- }
- }
-#endif
send_to_emacs (emacs_socket, "-file ");
- if (relative)
- {
- quote_argument (emacs_socket, cwd);
- send_to_emacs (emacs_socket, "/");
- }
quote_argument (emacs_socket, argv[i]);
send_to_emacs (emacs_socket, " ");
}