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,
#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
/* PID of the Emacs server process. */
int emacs_pid = 0;
-/* Socket used to communicate with the Emacs server process. */
-HSOCKET s;
-
void print_help_and_exit () NO_RETURN;
struct option longopts[] =
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 */
void
message (int is_error, char *message, ...)
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, --current-frame Do not create a new frame;\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\
+-d, --display=DISPLAY Visit the file in the given display\n"
#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);
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;
/* 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);
}
#endif /* WINDOWSNT */
\f
-#ifdef WINDOWSNT
-
-/*
- 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 */
-
/*
* Read the information needed to set up a TCP comm channel with
* the Emacs server: host, port, pid and authentication string.
*/
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)
+{
+ 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;
+}
+
+
#if !defined (NO_SOCKETS_IN_FILE_SYSTEM)
/* Three possibilities:
if (tcgetpgrp (1) == getpgrp ())
{
/* We are in the foreground. */
- SEND_STRING ("-resume \n");
+ send_to_emacs (emacs_socket, "-resume \n");
}
else
{
{
int old_errno = errno;
sigset_t set;
-
- if (s)
- SEND_STRING ("-suspend \n");
+
+ 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 ()
{
set_socket ()
{
HSOCKET s;
-
+
INITIALIZE ();
-
+
#ifndef NO_SOCKETS_IN_FILE_SYSTEM
/* Explicit --socket-name argument. */
if (socket_name)
s = set_tcp_socket ();
if ((s != INVALID_SOCKET) || alternate_editor)
return s;
-
+
message (TRUE, "%s: error accessing server file \"%s\"",
progname, server_file);
exit (EXIT_FAILURE);
}
-
+
#ifndef NO_SOCKETS_IN_FILE_SYSTEM
/* Implicit local socket. */
s = set_local_socket ();
exit (EXIT_FAILURE);
}
- if ((s = set_socket ()) == INVALID_SOCKET)
+ if ((emacs_socket = set_socket ()) == INVALID_SOCKET)
fail ();
#endif
/* First of all, send our version number for verification. */
- SEND_STRING ("-version ");
- SEND_STRING (VERSION);
- SEND_STRING (" ");
+ send_to_emacs (emacs_socket, "-version ");
+ send_to_emacs (emacs_socket, VERSION);
+ send_to_emacs (emacs_socket, " ");
/* 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 *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 (str);
+ 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';
fprintf (stderr, "*ERROR*: %s", str);
needlf = str[0] == '\0' ? needlf : str[strlen (str) - 1] != '\n';
}
+#ifndef WINDOWSNT
else if (strprefix ("-suspend ", string))
{
/* -suspend: Suspend this terminal, i.e., stop the process. */
needlf = 0;
kill (0, SIGSTOP);
}
+#endif
else
{
/* Unknown command. */
fflush (stdout);
fsync (1);
- CLOSE_SOCKET (s);
+ CLOSE_SOCKET (emacs_socket);
return EXIT_SUCCESS;
}