1 /* Client process that communicates with GNU Emacs acting as server.
2 Copyright (C) 1986, 1987, 1994, 1999, 2000, 2001, 2002, 2003, 2004,
3 2005, 2006 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA. */
31 #define NO_SOCKETS_IN_FILE_SYSTEM
35 # define HSOCKET SOCKET
36 # define CLOSE_SOCKET closesocket
37 # define IOCTL ioctlsocket
38 # define INITIALIZE() (initialize_sockets ())
39 typedef unsigned long IOCTL_BOOL_ARG
;
42 # define CLOSE_SOCKET close
45 typedef int IOCTL_BOOL_ARG
;
62 #else /* not WINDOWSNT */
64 #endif /* not WINDOWSNT */
67 char *getenv (), *getwd ();
71 #define VERSION "unspecified"
74 #define SEND_STRING(data) (send_to_emacs (s, (data)))
75 #define SEND_QUOTED(data) (quote_file_name (s, (data)))
78 #define EXIT_SUCCESS 0
82 #define EXIT_FAILURE 1
97 /* Name used to invoke this program. */
100 /* Nonzero means don't wait for a response from Emacs. --no-wait. */
103 /* Nonzero means args are expressions to be evaluated. --eval. */
106 /* The display on which Emacs should work. --display. */
107 char *display
= NULL
;
109 /* If non-NULL, the name of an editor to fallback to if the server
110 is not running. --alternate-editor. */
111 const char * alternate_editor
= NULL
;
113 /* If non-NULL, the filename of the UNIX socket. */
114 char *socket_name
= NULL
;
116 /* If non-NULL, the filename of the authentication file. */
117 char *server_file
= NULL
;
119 void print_help_and_exit () NO_RETURN
;
121 struct option longopts
[] =
123 { "no-wait", no_argument
, NULL
, 'n' },
124 { "eval", no_argument
, NULL
, 'e' },
125 { "help", no_argument
, NULL
, 'H' },
126 { "version", no_argument
, NULL
, 'V' },
127 { "alternate-editor", required_argument
, NULL
, 'a' },
128 { "socket-name", required_argument
, NULL
, 's' },
129 { "server-file", required_argument
, NULL
, 'f' },
130 { "display", required_argument
, NULL
, 'd' },
134 /* Decode the options from argv and argc.
135 The global variable `optind' will say how many arguments we used up. */
138 decode_options (argc
, argv
)
142 alternate_editor
= getenv ("ALTERNATE_EDITOR");
143 server_file
= getenv ("EMACS_SERVER_FILE");
147 int opt
= getopt_long (argc
, argv
,
148 "VHnea:s:f:d:", longopts
, 0);
156 /* If getopt returns 0, then it has already processed a
157 long-named option. We should do nothing. */
161 alternate_editor
= optarg
;
165 socket_name
= optarg
;
169 server_file
= optarg
;
185 printf ("emacsclient %s\n", VERSION
);
190 print_help_and_exit ();
194 fprintf (stderr
, "Try `%s --help' for more information\n", progname
);
202 print_help_and_exit ()
205 "Usage: %s [OPTIONS] FILE...\n\
206 Tell the Emacs server to visit the specified files.\n\
207 Every FILE can be either just a FILENAME or [+LINE[:COLUMN]] FILENAME.\n\
209 The following OPTIONS are accepted:\n\
210 -V, --version Just print a version info and return\n\
211 -H, --help Print this usage information message\n\
212 -n, --no-wait Don't wait for the server to return\n\
213 -e, --eval Evaluate the FILE arguments as ELisp expressions\n\
214 -d, --display=DISPLAY Visit the file in the given display\n"
215 #ifndef NO_SOCKETS_IN_FILE_SYSTEM
216 "-s, --socket-name=FILENAME\n\
217 Set the filename of the UNIX socket for communication\n"
219 "-f, --server-file=FILENAME\n\
220 Set the filename of the TCP configuration file\n\
221 -a, --alternate-editor=EDITOR\n\
222 Editor to fallback to if the server is not running\n\
224 Report bugs to bug-gnu-emacs@gnu.org.\n", progname
);
230 Try to run a different command, or --if no alternate editor is
231 defined-- exit with an errorcode.
238 if (alternate_editor
)
241 execvp (alternate_editor
, argv
+ i
);
242 fprintf (stderr
, "%s: error executing alternate editor \"%s\"\n",
243 progname
, alternate_editor
);
247 fprintf (stderr
, "%s: No socket or alternate editor. Please use:\n\n"
248 #if !defined (NO_SOCKETS_IN_FILE_SYSTEM)
251 "\t--server-file (or environment variable EMACS_SERVER_FILE)\n\
252 \t--alternate-editor (or environment variable ALTERNATE_EDITOR)\n",
259 #if !defined (HAVE_SOCKETS)
266 fprintf (stderr
, "%s: Sorry, the Emacs server is supported only\n",
268 fprintf (stderr
, "on systems with Berkeley sockets.\n");
273 #else /* HAVE_SOCKETS */
276 # include <winsock2.h>
278 # include <sys/types.h>
279 # include <sys/socket.h>
281 # include <sys/stat.h>
285 #define AUTH_KEY_LENGTH 64
286 #define SEND_BUFFER_SIZE 4096
288 extern char *strerror ();
291 /* Buffer to accumulate data to send in TCP connections. */
292 char send_buffer
[SEND_BUFFER_SIZE
+ 1];
293 int sblen
= 0; /* Fill pointer for the send buffer. */
295 /* Let's send the data to Emacs when either
296 - the data ends in "\n", or
297 - the buffer is full (but this shouldn't happen)
298 Otherwise, we just accumulate it. */
299 void send_to_emacs (s
, data
)
305 int dlen
= strlen (data
);
306 if (dlen
+ sblen
>= SEND_BUFFER_SIZE
)
308 int part
= SEND_BUFFER_SIZE
- sblen
;
309 strncpy (&send_buffer
[sblen
], data
, part
);
311 sblen
= SEND_BUFFER_SIZE
;
315 strcpy (&send_buffer
[sblen
], data
);
322 if (sblen
== SEND_BUFFER_SIZE
323 || (sblen
> 0 && send_buffer
[sblen
-1] == '\n'))
325 int sent
= send (s
, send_buffer
, sblen
, 0);
327 strcpy (send_buffer
, &send_buffer
[sent
]);
333 /* In NAME, insert a & before each &, each space, each newline, and
334 any initial -. Change spaces to underscores, too, so that the
335 return value never contains a space. */
337 quote_file_name (s
, name
)
341 char *copy
= (char *) malloc (strlen (name
) * 2 + 1);
362 if (*p
== '&' || (*p
== '-' && p
== name
))
375 /* Wrapper to make WSACleanup a cdecl, as required by atexit(). */
376 void close_winsock ()
381 void initialize_sockets ()
385 /* Initialize the WinSock2 library. */
386 if (WSAStartup (MAKEWORD (2, 0), &wsaData
))
388 fprintf (stderr
, "%s: error initializing WinSock2", progname
);
392 atexit (close_winsock
);
393 #endif /* WINDOWSNT */
397 * Read the information needed to set up a TCP comm channel with
398 * the Emacs server: host, port and authentication string.
400 int get_server_config (server
, authentication
)
401 struct sockaddr_in
*server
;
402 char *authentication
;
408 if (! (config
= fopen (server_file
, "rb")))
410 char *home
= getenv ("HOME");
413 home
= getenv ("APPDATA");
417 char *path
= alloca (32 + strlen (home
) + strlen (server_file
));
418 sprintf (path
, "%s/.emacs.d/server/%s", home
, server_file
);
419 config
= fopen (path
, "rb");
426 if (fgets (dotted
, sizeof dotted
, config
)
427 && (port
= strchr (dotted
, ':')))
433 fprintf (stderr
, "%s: invalid configuration info", progname
);
437 server
->sin_family
= AF_INET
;
438 server
->sin_addr
.s_addr
= inet_addr (dotted
);
439 server
->sin_port
= htons (atoi (port
));
441 if (! fread (authentication
, AUTH_KEY_LENGTH
, 1, config
))
443 fprintf (stderr
, "%s: cannot read authentication info", progname
);
456 struct sockaddr_in server
;
457 IOCTL_BOOL_ARG c_arg
= 0;
458 struct linger l_arg
= {1, 1};
459 char auth_string
[AUTH_KEY_LENGTH
+ 1];
463 if (! get_server_config (&server
, auth_string
))
464 return INVALID_SOCKET
;
467 * Open up an AF_INET socket
469 if ((s
= socket (AF_INET
, SOCK_STREAM
, IPPROTO_TCP
)) < 0)
471 fprintf (stderr
, "%s: ", progname
);
473 return INVALID_SOCKET
;
479 if (connect (s
, (struct sockaddr
*) &server
, sizeof server
) < 0)
481 fprintf (stderr
, "%s: ", progname
);
483 return INVALID_SOCKET
;
486 IOCTL (s
, FIONBIO
, &c_arg
);
487 setsockopt (s
, SOL_SOCKET
, SO_LINGER
, (char *) &l_arg
, sizeof l_arg
);
490 * Send the authentication
492 auth_string
[AUTH_KEY_LENGTH
] = '\0';
494 SEND_STRING ("-auth ");
495 SEND_STRING (auth_string
);
501 #if !defined (NO_SOCKETS_IN_FILE_SYSTEM)
503 /* Three possibilities:
504 2 - can't be `stat'ed (sets errno)
505 1 - isn't owned by us
506 0 - success: none of the above */
509 socket_status (socket_name
)
514 if (stat (socket_name
, &statbfr
) == -1)
517 if (statbfr
.st_uid
!= geteuid ())
527 struct sockaddr_un server
;
530 * Open up an AF_UNIX socket in this person's home directory
533 if ((s
= socket (AF_UNIX
, SOCK_STREAM
, 0)) < 0)
535 fprintf (stderr
, "%s: ", progname
);
537 return INVALID_SOCKET
;
540 server
.sun_family
= AF_UNIX
;
544 int default_sock
= !socket_name
;
546 char *server_name
= "server";
548 if (socket_name
&& !index (socket_name
, '/') && !index (socket_name
, '\\'))
549 { /* socket_name is a file name component. */
550 server_name
= socket_name
;
552 default_sock
= 1; /* Try both UIDs. */
557 socket_name
= alloca (100 + strlen (server_name
));
558 sprintf (socket_name
, "/tmp/emacs%d/%s",
559 (int) geteuid (), server_name
);
562 if (strlen (socket_name
) < sizeof (server
.sun_path
))
563 strcpy (server
.sun_path
, socket_name
);
566 fprintf (stderr
, "%s: socket-name %s too long",
567 progname
, socket_name
);
571 /* See if the socket exists, and if it's owned by us. */
572 sock_status
= socket_status (server
.sun_path
);
574 if (sock_status
&& default_sock
)
576 /* Failing that, see if LOGNAME or USER exist and differ from
577 our euid. If so, look for a socket based on the UID
578 associated with the name. This is reminiscent of the logic
579 that init_editfns uses to set the global Vuser_full_name. */
581 char *user_name
= (char *) getenv ("LOGNAME");
584 user_name
= (char *) getenv ("USER");
588 struct passwd
*pw
= getpwnam (user_name
);
590 if (pw
&& (pw
->pw_uid
!= geteuid ()))
592 /* We're running under su, apparently. */
593 socket_name
= alloca (100 + strlen (server_name
));
594 sprintf (socket_name
, "/tmp/emacs%d/%s",
595 (int) pw
->pw_uid
, server_name
);
597 if (strlen (socket_name
) < sizeof (server
.sun_path
))
598 strcpy (server
.sun_path
, socket_name
);
601 fprintf (stderr
, "%s: socket-name %s too long",
602 progname
, socket_name
);
606 sock_status
= socket_status (server
.sun_path
);
617 /* There's a socket, but it isn't owned by us. This is OK if
621 fprintf (stderr
, "%s: Invalid socket owner\n", argv
[0]);
622 return INVALID_SOCKET
;
628 if (saved_errno
== ENOENT
)
630 "%s: can't find socket; have you started the server?\n\
631 To start the server in Emacs, type \"M-x server-start\".\n",
634 fprintf (stderr
, "%s: can't stat %s: %s\n",
635 progname
, server
.sun_path
, strerror (saved_errno
));
636 return INVALID_SOCKET
;
640 if (connect (s
, (struct sockaddr
*) &server
, strlen (server
.sun_path
) + 2)
643 fprintf (stderr
, "%s: ", progname
);
645 return INVALID_SOCKET
;
650 #endif /* ! NO_SOCKETS_IN_FILE_SYSTEM */
656 return set_tcp_socket ();
658 #ifndef NO_SOCKETS_IN_FILE_SYSTEM
659 return set_local_socket ();
662 server_file
= "server";
663 return set_tcp_socket ();
674 int i
, rl
, needlf
= 0;
676 char string
[BUFSIZ
+1];
680 /* Process options. */
681 decode_options (argc
, argv
);
683 if ((argc
- optind
< 1) && !eval
)
685 fprintf (stderr
, "%s: file name or argument required\n", progname
);
686 fprintf (stderr
, "Try `%s --help' for more information\n", progname
);
690 if ((s
= set_socket ()) == INVALID_SOCKET
)
694 cwd
= getcwd (string
, sizeof string
);
696 cwd
= getwd (string
);
700 /* getwd puts message in STRING if it fails. */
702 fprintf (stderr
, "%s: %s (%s)\n", progname
,
703 "Cannot get current working directory", strerror (errno
));
705 fprintf (stderr
, "%s: %s (%s)\n", progname
, string
, strerror (errno
));
711 SEND_STRING ("-nowait ");
714 SEND_STRING ("-eval ");
718 SEND_STRING ("-display ");
719 SEND_QUOTED (display
);
723 if ((argc
- optind
> 0))
725 for (i
= optind
; i
< argc
; i
++)
728 ; /* Don't prepend any cwd or anything like that. */
729 else if (*argv
[i
] == '+')
731 char *p
= argv
[i
] + 1;
732 while (isdigit ((unsigned char) *p
) || *p
== ':') p
++;
740 else if (*argv
[i
] != '/')
742 else if ((*argv
[i
] != '/')
743 /* Absolute paths can also start with backslash
745 && (*argv
[i
] != '\\')
746 && (!islower (tolower (*argv
[i
]))
747 || (argv
[i
][1] != ':')))
754 SEND_QUOTED (argv
[i
]);
760 while (fgets (string
, BUFSIZ
, stdin
))
762 SEND_QUOTED (string
);
769 /* Maybe wait for an answer. */
774 printf ("Waiting for Emacs...");
779 /* Now, wait for an answer and print any messages. */
780 while ((rl
= recv (s
, string
, BUFSIZ
, 0)) > 0)
785 printf ("%s", string
);
786 needlf
= string
[0] == '\0' ? needlf
: string
[strlen (string
) - 1] != '\n';
798 #endif /* HAVE_SOCKETS */
800 #ifndef HAVE_STRERROR
805 extern char *sys_errlist
[];
808 if (errnum
>= 0 && errnum
< sys_nerr
)
809 return sys_errlist
[errnum
];
810 return (char *) "Unknown error";
813 #endif /* ! HAVE_STRERROR */
815 /* arch-tag: f39bb9c4-73eb-477e-896d-50832e2ca9a7
816 (do not change this comment) */
818 /* emacsclient.c ends here */