(cvs-temp-buffer): Undo last ill-conceived change.
[bpt/emacs.git] / lib-src / emacsclient.c
CommitLineData
efb859b4 1/* Client process that communicates with GNU Emacs acting as server.
92b47a4a 2 Copyright (C) 1986, 1987, 1994, 1999, 2000, 2001, 2002, 2003, 2004,
4e6835db 3 2005, 2006, 2007 Free Software Foundation, Inc.
46cec291
RS
4
5This file is part of GNU Emacs.
6
7GNU Emacs is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
92af894f 9the Free Software Foundation; either version 2, or (at your option)
46cec291
RS
10any later version.
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU Emacs; see the file COPYING. If not, write to
364c38d3
LK
19the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20Boston, MA 02110-1301, USA. */
46cec291
RS
21
22
23#define NO_SHORTNAMES
e69233c2
PJ
24
25#ifdef HAVE_CONFIG_H
2f8fe2f4 26#include <config.h>
e69233c2
PJ
27#endif
28
aa0b6932 29#ifdef WINDOWSNT
aa0b6932 30
bc28de71
JB
31/* config.h defines these, which disables sockets altogether! */
32# undef _WINSOCKAPI_
33# undef _WINSOCK_H
34
411b80a5
JB
35# include <malloc.h>
36# include <stdlib.h>
42073bfb 37# include <windows.h>
411b80a5 38
411b80a5
JB
39# define NO_SOCKETS_IN_FILE_SYSTEM
40
aa0b6932
JB
41# define HSOCKET SOCKET
42# define CLOSE_SOCKET closesocket
aa0b6932 43# define INITIALIZE() (initialize_sockets ())
411b80a5
JB
44
45#else /* !WINDOWSNT */
46
ed4a3730
JB
47# include <sys/types.h>
48
1e7823d0
JB
49# ifdef HAVE_INET_SOCKETS
50# include <netinet/in.h>
51# endif
411b80a5 52
e35fc962 53# define INVALID_SOCKET -1
aa0b6932
JB
54# define HSOCKET int
55# define CLOSE_SOCKET close
aa0b6932 56# define INITIALIZE()
411b80a5
JB
57
58#endif /* !WINDOWSNT */
aa0b6932 59
4e23f2ba 60#undef signal
46cec291 61
42073bfb 62#include <stdarg.h>
e69233c2 63#include <ctype.h>
8f9aaa0a 64#include <stdio.h>
aa0b6932 65#include "getopt.h"
79f13bba
DL
66#ifdef HAVE_UNISTD_H
67#include <unistd.h>
68#endif
8f9aaa0a 69
9f637eea
GM
70#ifdef VMS
71# include "vms-pwd.h"
aa0b6932
JB
72#else /* not VMS */
73#ifdef WINDOWSNT
74# include <io.h>
75#else /* not WINDOWSNT */
9f637eea 76# include <pwd.h>
aa0b6932 77#endif /* not WINDOWSNT */
9f637eea
GM
78#endif /* not VMS */
79
8f9aaa0a 80char *getenv (), *getwd ();
5b9562c3 81char *(getcwd) ();
8f9aaa0a 82
8f9aaa0a
RS
83#ifndef VERSION
84#define VERSION "unspecified"
85#endif
86\f
aa0b6932
JB
87#define SEND_STRING(data) (send_to_emacs (s, (data)))
88#define SEND_QUOTED(data) (quote_file_name (s, (data)))
89
90#ifndef EXIT_SUCCESS
91#define EXIT_SUCCESS 0
92#endif
93
94#ifndef EXIT_FAILURE
95#define EXIT_FAILURE 1
96#endif
97
98#ifndef FALSE
99#define FALSE 0
100#endif
101
102#ifndef TRUE
103#define TRUE 1
104#endif
105
106#ifndef NO_RETURN
107#define NO_RETURN
108#endif
109\f
8f9aaa0a
RS
110/* Name used to invoke this program. */
111char *progname;
112
749ae770 113/* Nonzero means don't wait for a response from Emacs. --no-wait. */
8f9aaa0a
RS
114int nowait = 0;
115
30be2360
SM
116/* Nonzero means args are expressions to be evaluated. --eval. */
117int eval = 0;
118
119/* The display on which Emacs should work. --display. */
120char *display = NULL;
121
122/* If non-NULL, the name of an editor to fallback to if the server
123 is not running. --alternate-editor. */
b03d27bd 124const char *alternate_editor = NULL;
30be2360 125
3db926be 126/* If non-NULL, the filename of the UNIX socket. */
254107e4
RS
127char *socket_name = NULL;
128
aa0b6932
JB
129/* If non-NULL, the filename of the authentication file. */
130char *server_file = NULL;
131
c66648e0
JB
132/* PID of the Emacs server process. */
133int emacs_pid = 0;
134
2381d38d 135void print_help_and_exit () NO_RETURN;
7f3bff3e 136
8f9aaa0a
RS
137struct option longopts[] =
138{
749ae770 139 { "no-wait", no_argument, NULL, 'n' },
30be2360 140 { "eval", no_argument, NULL, 'e' },
8f9aaa0a
RS
141 { "help", no_argument, NULL, 'H' },
142 { "version", no_argument, NULL, 'V' },
3cf8c6aa 143 { "alternate-editor", required_argument, NULL, 'a' },
b03d27bd 144#ifndef NO_SOCKETS_IN_FILE_SYSTEM
254107e4 145 { "socket-name", required_argument, NULL, 's' },
b03d27bd 146#endif
aa0b6932 147 { "server-file", required_argument, NULL, 'f' },
30be2360
SM
148 { "display", required_argument, NULL, 'd' },
149 { 0, 0, 0, 0 }
8f9aaa0a
RS
150};
151
42073bfb
JB
152/* Message functions. */
153
154#ifdef WINDOWSNT
42073bfb 155int
f0384499 156w32_window_app ()
42073bfb
JB
157{
158 static int window_app = -1;
159 char szTitle[MAX_PATH];
160
161 if (window_app < 0)
0d3d6719
JB
162 /* Checking for STDOUT does not work; it's a valid handle also in
163 nonconsole apps. Testing for the console title seems to work. */
42073bfb
JB
164 window_app = (GetConsoleTitleA (szTitle, MAX_PATH) == 0);
165
166 return window_app;
167}
168#endif
169
170void
171message (int is_error, char *message, ...)
172{
c66648e0 173 char msg [2048];
42073bfb
JB
174 va_list args;
175
176 va_start (args, message);
42073bfb
JB
177 vsprintf (msg, message, args);
178 va_end (args);
179
180#ifdef WINDOWSNT
181 if (w32_window_app ())
182 {
183 if (is_error)
184 MessageBox (NULL, msg, "Emacsclient ERROR", MB_ICONERROR);
185 else
186 MessageBox (NULL, msg, "Emacsclient", MB_ICONINFORMATION);
187 }
188 else
189#endif
9219db75
JB
190 {
191 FILE *f = is_error ? stderr : stdout;
192
193 fputs (msg, f);
194 fflush (f);
195 }
42073bfb
JB
196}
197
8f9aaa0a 198/* Decode the options from argv and argc.
5212210c 199 The global variable `optind' will say how many arguments we used up. */
8f9aaa0a 200
5212210c 201void
8f9aaa0a
RS
202decode_options (argc, argv)
203 int argc;
204 char **argv;
205{
b6b6d6d2
SM
206 alternate_editor = getenv ("ALTERNATE_EDITOR");
207
8f9aaa0a
RS
208 while (1)
209 {
210 int opt = getopt_long (argc, argv,
b03d27bd
JB
211#ifndef NO_SOCKETS_IN_FILE_SYSTEM
212 "VHnea:s:f:d:",
213#else
214 "VHnea:f:d:",
215#endif
216 longopts, 0);
8f9aaa0a
RS
217
218 if (opt == EOF)
219 break;
220
221 switch (opt)
222 {
223 case 0:
224 /* If getopt returns 0, then it has already processed a
225 long-named option. We should do nothing. */
226 break;
e69233c2 227
97e3214d
GM
228 case 'a':
229 alternate_editor = optarg;
230 break;
e69233c2 231
b03d27bd 232#ifndef NO_SOCKETS_IN_FILE_SYSTEM
254107e4
RS
233 case 's':
234 socket_name = optarg;
235 break;
b03d27bd 236#endif
254107e4 237
aa0b6932
JB
238 case 'f':
239 server_file = optarg;
240 break;
241
30be2360
SM
242 case 'd':
243 display = optarg;
244 break;
245
8f9aaa0a
RS
246 case 'n':
247 nowait = 1;
248 break;
249
30be2360
SM
250 case 'e':
251 eval = 1;
252 break;
253
8f9aaa0a 254 case 'V':
42073bfb 255 message (FALSE, "emacsclient %s\n", VERSION);
65396510 256 exit (EXIT_SUCCESS);
8f9aaa0a 257 break;
46cec291 258
8f9aaa0a 259 case 'H':
8f9aaa0a 260 print_help_and_exit ();
20c396e8
JB
261 break;
262
263 default:
42073bfb 264 message (TRUE, "Try `%s --help' for more information\n", progname);
65396510 265 exit (EXIT_FAILURE);
20c396e8 266 break;
8f9aaa0a
RS
267 }
268 }
8f9aaa0a
RS
269}
270
7f3bff3e 271void
8f9aaa0a
RS
272print_help_and_exit ()
273{
42073bfb 274 message (FALSE,
20c396e8 275 "Usage: %s [OPTIONS] FILE...\n\
30be2360
SM
276Tell the Emacs server to visit the specified files.\n\
277Every FILE can be either just a FILENAME or [+LINE[:COLUMN]] FILENAME.\n\
20c396e8 278\n\
30be2360 279The following OPTIONS are accepted:\n\
30aa95ce
JB
280\n\
281-V, --version Just print version info and return\n\
282-H, --help Print this usage information message\n\
283-e, --eval Evaluate FILE arguments as Lisp expressions\n\
284-n, --no-wait Don't wait for the server to return\n\
285-d, --display=DISPLAY Visit the file in the given display\n"
aa0b6932
JB
286#ifndef NO_SOCKETS_IN_FILE_SYSTEM
287"-s, --socket-name=FILENAME\n\
30aa95ce 288 Set filename of the UNIX socket for communication\n"
aa0b6932
JB
289#endif
290"-f, --server-file=FILENAME\n\
30aa95ce 291 Set filename of the TCP authentication file\n\
30be2360 292-a, --alternate-editor=EDITOR\n\
30aa95ce 293 Editor to fallback to if server is not running\n\
20c396e8 294\n\
30be2360 295Report bugs to bug-gnu-emacs@gnu.org.\n", progname);
65396510 296 exit (EXIT_SUCCESS);
8f9aaa0a 297}
5212210c 298
aa0b6932 299\f
4472aef4
JB
300#ifdef WINDOWSNT
301
302/*
f0384499 303 execvp wrapper for Windows. Quotes arguments with embedded spaces.
4472aef4
JB
304
305 This is necessary due to the broken implementation of exec* routines in
306 the Microsoft libraries: they concatenate the arguments together without
307 quoting special characters, and pass the result to CreateProcess, with
308 predictably bad results. By contrast, Posix execvp passes the arguments
f0384499 309 directly into the argv array of the child process.
4472aef4
JB
310*/
311int
312w32_execvp (path, argv)
313 char *path;
314 char **argv;
315{
316 int i;
317
0d3d6719 318 /* Required to allow a .BAT script as alternate editor. */
4472aef4
JB
319 argv[0] = (char *) alternate_editor;
320
321 for (i = 0; argv[i]; i++)
322 if (strchr (argv[i], ' '))
323 {
324 char *quoted = alloca (strlen (argv[i]) + 3);
325 sprintf (quoted, "\"%s\"", argv[i]);
326 argv[i] = quoted;
327 }
328
329 return execvp (path, argv);
330}
331
332#undef execvp
333#define execvp w32_execvp
334
335#endif /* WINDOWSNT */
336
aa0b6932
JB
337/*
338 Try to run a different command, or --if no alternate editor is
339 defined-- exit with an errorcode.
340*/
341void
342fail (argc, argv)
343 int argc;
344 char **argv;
345{
346 if (alternate_editor)
347 {
348 int i = optind - 1;
4472aef4 349
aa0b6932 350 execvp (alternate_editor, argv + i);
42073bfb 351 message (TRUE, "%s: error executing alternate editor \"%s\"\n",
aa0b6932
JB
352 progname, alternate_editor);
353 }
aa0b6932
JB
354 exit (EXIT_FAILURE);
355}
356
357\f
1e7823d0 358#if !defined (HAVE_SOCKETS) || !defined (HAVE_INET_SOCKETS)
aa0b6932
JB
359
360int
361main (argc, argv)
362 int argc;
363 char **argv;
364{
42073bfb 365 message (TRUE, "%s: Sorry, the Emacs server is supported only\non systems with Berkely sockets.\n",
aa0b6932 366 argv[0]);
aa0b6932
JB
367
368 fail (argc, argv);
369}
370
1e7823d0 371#else /* HAVE_SOCKETS && HAVE_INET_SOCKETS */
aa0b6932
JB
372
373#ifdef WINDOWSNT
374# include <winsock2.h>
375#else
376# include <sys/types.h>
377# include <sys/socket.h>
378# include <sys/un.h>
379# include <sys/stat.h>
380# include <errno.h>
381#endif
382
383#define AUTH_KEY_LENGTH 64
384#define SEND_BUFFER_SIZE 4096
385
386extern char *strerror ();
387extern int errno;
388
389/* Buffer to accumulate data to send in TCP connections. */
390char send_buffer[SEND_BUFFER_SIZE + 1];
391int sblen = 0; /* Fill pointer for the send buffer. */
392
393/* Let's send the data to Emacs when either
394 - the data ends in "\n", or
395 - the buffer is full (but this shouldn't happen)
396 Otherwise, we just accumulate it. */
b03d27bd
JB
397void
398send_to_emacs (s, data)
aa0b6932
JB
399 HSOCKET s;
400 char *data;
401{
402 while (data)
403 {
404 int dlen = strlen (data);
405 if (dlen + sblen >= SEND_BUFFER_SIZE)
406 {
407 int part = SEND_BUFFER_SIZE - sblen;
408 strncpy (&send_buffer[sblen], data, part);
409 data += part;
410 sblen = SEND_BUFFER_SIZE;
411 }
412 else if (dlen)
413 {
414 strcpy (&send_buffer[sblen], data);
415 data = NULL;
416 sblen += dlen;
417 }
418 else
419 break;
420
421 if (sblen == SEND_BUFFER_SIZE
422 || (sblen > 0 && send_buffer[sblen-1] == '\n'))
423 {
424 int sent = send (s, send_buffer, sblen, 0);
425 if (sent != sblen)
426 strcpy (send_buffer, &send_buffer[sent]);
427 sblen -= sent;
428 }
429 }
430}
431
a4cf2096
RS
432/* In NAME, insert a & before each &, each space, each newline, and
433 any initial -. Change spaces to underscores, too, so that the
5212210c 434 return value never contains a space. */
87209357 435void
aa0b6932
JB
436quote_file_name (s, name)
437 HSOCKET s;
5212210c
RS
438 char *name;
439{
440 char *copy = (char *) malloc (strlen (name) * 2 + 1);
441 char *p, *q;
442
443 p = name;
444 q = copy;
445 while (*p)
446 {
447 if (*p == ' ')
448 {
f1db6a73 449 *q++ = '&';
5212210c
RS
450 *q++ = '_';
451 p++;
452 }
3cf8c6aa
SM
453 else if (*p == '\n')
454 {
455 *q++ = '&';
456 *q++ = 'n';
457 p++;
458 }
5212210c
RS
459 else
460 {
f1db6a73
RS
461 if (*p == '&' || (*p == '-' && p == name))
462 *q++ = '&';
5212210c
RS
463 *q++ = *p++;
464 }
465 }
f1db6a73 466 *q++ = 0;
5212210c 467
aa0b6932 468 SEND_STRING (copy);
87209357
EZ
469
470 free (copy);
5212210c 471}
0c76956f 472
b03d27bd
JB
473int
474file_name_absolute_p (filename)
475 const unsigned char *filename;
476{
477 /* Sanity check, it shouldn't happen. */
478 if (! filename) return FALSE;
479
480 /* /xxx is always an absolute path. */
481 if (filename[0] == '/') return TRUE;
482
483 /* Empty filenames (which shouldn't happen) are relative. */
484 if (filename[0] == '\0') return FALSE;
485
486#ifdef WINDOWSNT
71b8f735 487 /* X:\xxx is always absolute. */
5f7a4874 488 if (isalpha (filename[0])
cb0297bb 489 && filename[1] == ':' && (filename[2] == '\\' || filename[2] == '/'))
b03d27bd
JB
490 return TRUE;
491
492 /* Both \xxx and \\xxx\yyy are absolute. */
493 if (filename[0] == '\\') return TRUE;
71b8f735
JB
494
495 /*
496 FIXME: There's a corner case not dealt with, "x:y", where:
497
498 1) x is a valid drive designation (usually a letter in the A-Z range)
499 and y is a path, relative to the current directory on drive x. This
500 is absolute, *after* fixing the y part to include the current
501 directory in x.
502
503 2) x is a relative file name, and y is an NTFS stream name. This is a
504 correct relative path, but it is very unusual.
505
506 The trouble is that first case items are also valid examples of the
507 second case, i.e., "c:test" can be understood as drive:path or as
508 file:stream.
509
510 The "right" fix would involve checking whether
511 - the current drive/partition is NTFS,
512 - x is a valid (and accesible) drive designator,
513 - x:y already exists as a file:stream in the current directory,
514 - y already exists on the current directory of drive x,
515 - the auspices are favorable,
516 and then taking an "informed decision" based on the above.
517
518 Whatever the result, Emacs currently does a very bad job of dealing
519 with NTFS file:streams: it cannot visit them, and the only way to
520 create one is by setting `buffer-file-name' to point to it (either
521 manually or with emacsclient). So perhaps resorting to 1) and ignoring
522 2) for now is the right thing to do.
523
524 Anyway, something to decide After the Release.
525 */
b03d27bd
JB
526#endif
527
528 return FALSE;
529}
530
aa0b6932 531#ifdef WINDOWSNT
f0384499 532/* Wrapper to make WSACleanup a cdecl, as required by atexit. */
b03d27bd
JB
533void
534__cdecl close_winsock ()
aa0b6932
JB
535{
536 WSACleanup ();
537}
0c76956f 538
b03d27bd
JB
539/* Initialize the WinSock2 library. */
540void
541initialize_sockets ()
0c76956f 542{
aa0b6932
JB
543 WSADATA wsaData;
544
aa0b6932
JB
545 if (WSAStartup (MAKEWORD (2, 0), &wsaData))
546 {
42073bfb 547 message (TRUE, "%s: error initializing WinSock2", progname);
aa0b6932
JB
548 exit (EXIT_FAILURE);
549 }
550
551 atexit (close_winsock);
0c76956f 552}
e35fc962 553#endif /* WINDOWSNT */
8f9aaa0a 554\f
97e3214d 555/*
aa0b6932 556 * Read the information needed to set up a TCP comm channel with
434a6c5d 557 * the Emacs server: host, port, pid and authentication string.
0e0dced5 558 */
b03d27bd
JB
559int
560get_server_config (server, authentication)
aa0b6932
JB
561 struct sockaddr_in *server;
562 char *authentication;
97e3214d 563{
aa0b6932
JB
564 char dotted[32];
565 char *port;
434a6c5d 566 char *pid;
b03d27bd 567 FILE *config = NULL;
aa0b6932 568
b03d27bd
JB
569 if (file_name_absolute_p (server_file))
570 config = fopen (server_file, "rb");
571 else
97e3214d 572 {
aa0b6932 573 char *home = getenv ("HOME");
88b46d84 574
aa0b6932
JB
575 if (home)
576 {
577 char *path = alloca (32 + strlen (home) + strlen (server_file));
578 sprintf (path, "%s/.emacs.d/server/%s", home, server_file);
579 config = fopen (path, "rb");
580 }
88b46d84
JB
581#ifdef WINDOWSNT
582 if (!config && (home = getenv ("APPDATA")))
583 {
584 char *path = alloca (32 + strlen (home) + strlen (server_file));
585 sprintf (path, "%s/.emacs.d/server/%s", home, server_file);
586 config = fopen (path, "rb");
587 }
588#endif
aa0b6932
JB
589 }
590
591 if (! config)
592 return FALSE;
593
594 if (fgets (dotted, sizeof dotted, config)
434a6c5d
JB
595 && (port = strchr (dotted, ':'))
596 && (pid = strchr (port, ' ')))
aa0b6932
JB
597 {
598 *port++ = '\0';
434a6c5d 599 *pid++ = '\0';
97e3214d
GM
600 }
601 else
602 {
42073bfb 603 message (TRUE, "%s: invalid configuration info", progname);
65396510 604 exit (EXIT_FAILURE);
97e3214d 605 }
97e3214d 606
aa0b6932
JB
607 server->sin_family = AF_INET;
608 server->sin_addr.s_addr = inet_addr (dotted);
609 server->sin_port = htons (atoi (port));
97e3214d 610
aa0b6932
JB
611 if (! fread (authentication, AUTH_KEY_LENGTH, 1, config))
612 {
42073bfb 613 message (TRUE, "%s: cannot read authentication info", progname);
aa0b6932
JB
614 exit (EXIT_FAILURE);
615 }
46cec291 616
aa0b6932 617 fclose (config);
97e3214d 618
c66648e0 619 emacs_pid = atoi (pid);
434a6c5d 620
aa0b6932 621 return TRUE;
46cec291
RS
622}
623
aa0b6932
JB
624HSOCKET
625set_tcp_socket ()
626{
627 HSOCKET s;
628 struct sockaddr_in server;
aa0b6932
JB
629 struct linger l_arg = {1, 1};
630 char auth_string[AUTH_KEY_LENGTH + 1];
46cec291 631
aa0b6932
JB
632 if (! get_server_config (&server, auth_string))
633 return INVALID_SOCKET;
634
b03d27bd 635 if (server.sin_addr.s_addr != inet_addr ("127.0.0.1"))
9219db75 636 message (FALSE, "%s: connected to remote socket at %s\n",
b03d27bd
JB
637 progname, inet_ntoa (server.sin_addr));
638
aa0b6932
JB
639 /*
640 * Open up an AF_INET socket
641 */
642 if ((s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
643 {
42073bfb 644 message (TRUE, "%s: socket: %s\n", progname, strerror (errno));
aa0b6932
JB
645 return INVALID_SOCKET;
646 }
647
648 /*
649 * Set up the socket
650 */
651 if (connect (s, (struct sockaddr *) &server, sizeof server) < 0)
652 {
42073bfb 653 message (TRUE, "%s: connect: %s\n", progname, strerror (errno));
aa0b6932
JB
654 return INVALID_SOCKET;
655 }
656
aa0b6932
JB
657 setsockopt (s, SOL_SOCKET, SO_LINGER, (char *) &l_arg, sizeof l_arg);
658
659 /*
660 * Send the authentication
661 */
662 auth_string[AUTH_KEY_LENGTH] = '\0';
663
664 SEND_STRING ("-auth ");
665 SEND_STRING (auth_string);
666 SEND_STRING ("\n");
667
668 return s;
669}
670
671#if !defined (NO_SOCKETS_IN_FILE_SYSTEM)
46cec291 672
9f637eea
GM
673/* Three possibilities:
674 2 - can't be `stat'ed (sets errno)
675 1 - isn't owned by us
676 0 - success: none of the above */
677
678static int
679socket_status (socket_name)
680 char *socket_name;
681{
682 struct stat statbfr;
683
684 if (stat (socket_name, &statbfr) == -1)
685 return 2;
686
687 if (statbfr.st_uid != geteuid ())
688 return 1;
689
690 return 0;
691}
692
aa0b6932
JB
693HSOCKET
694set_local_socket ()
46cec291 695{
aa0b6932 696 HSOCKET s;
46cec291 697 struct sockaddr_un server;
46cec291 698
e69233c2 699 /*
46cec291
RS
700 * Open up an AF_UNIX socket in this person's home directory
701 */
702
703 if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
704 {
42073bfb 705 message (TRUE, "%s: socket: %s\n", progname, strerror (errno));
aa0b6932 706 return INVALID_SOCKET;
46cec291 707 }
e69233c2 708
46cec291 709 server.sun_family = AF_UNIX;
c5fee545 710
c5fee545 711 {
9f637eea 712 int sock_status = 0;
5c9659d3 713 int default_sock = !socket_name;
152b6e83 714 int saved_errno;
0734b0d0
SM
715 char *server_name = "server";
716
717 if (socket_name && !index (socket_name, '/') && !index (socket_name, '\\'))
718 { /* socket_name is a file name component. */
719 server_name = socket_name;
720 socket_name = NULL;
721 default_sock = 1; /* Try both UIDs. */
722 }
efb859b4 723
5c9659d3 724 if (default_sock)
254107e4 725 {
0734b0d0
SM
726 socket_name = alloca (100 + strlen (server_name));
727 sprintf (socket_name, "/tmp/emacs%d/%s",
728 (int) geteuid (), server_name);
254107e4
RS
729 }
730
731 if (strlen (socket_name) < sizeof (server.sun_path))
732 strcpy (server.sun_path, socket_name);
733 else
5c9659d3 734 {
42073bfb 735 message (TRUE, "%s: socket-name %s too long",
aa0b6932 736 progname, socket_name);
65396510 737 exit (EXIT_FAILURE);
5c9659d3 738 }
efb859b4 739
9f637eea
GM
740 /* See if the socket exists, and if it's owned by us. */
741 sock_status = socket_status (server.sun_path);
152b6e83 742 saved_errno = errno;
5c9659d3 743 if (sock_status && default_sock)
efb859b4 744 {
9f637eea
GM
745 /* Failing that, see if LOGNAME or USER exist and differ from
746 our euid. If so, look for a socket based on the UID
747 associated with the name. This is reminiscent of the logic
748 that init_editfns uses to set the global Vuser_full_name. */
e69233c2 749
9f637eea 750 char *user_name = (char *) getenv ("LOGNAME");
293f9f2a 751
9f637eea
GM
752 if (!user_name)
753 user_name = (char *) getenv ("USER");
e69233c2 754
9f637eea
GM
755 if (user_name)
756 {
757 struct passwd *pw = getpwnam (user_name);
293f9f2a 758
9f637eea
GM
759 if (pw && (pw->pw_uid != geteuid ()))
760 {
761 /* We're running under su, apparently. */
0734b0d0
SM
762 socket_name = alloca (100 + strlen (server_name));
763 sprintf (socket_name, "/tmp/emacs%d/%s",
764 (int) pw->pw_uid, server_name);
5c9659d3
SM
765
766 if (strlen (socket_name) < sizeof (server.sun_path))
767 strcpy (server.sun_path, socket_name);
768 else
769 {
42073bfb 770 message (TRUE, "%s: socket-name %s too long",
aa0b6932 771 progname, socket_name);
65396510 772 exit (EXIT_FAILURE);
5c9659d3
SM
773 }
774
9f637eea 775 sock_status = socket_status (server.sun_path);
152b6e83 776 saved_errno = errno;
9f637eea 777 }
293f9f2a
RS
778 else
779 errno = saved_errno;
9f637eea 780 }
efb859b4 781 }
e69233c2 782
aa0b6932
JB
783 switch (sock_status)
784 {
785 case 1:
786 /* There's a socket, but it isn't owned by us. This is OK if
787 we are root. */
788 if (0 != geteuid ())
789 {
42073bfb 790 message (TRUE, "%s: Invalid socket owner\n", progname);
aa0b6932
JB
791 return INVALID_SOCKET;
792 }
793 break;
794
795 case 2:
796 /* `stat' failed */
797 if (saved_errno == ENOENT)
42073bfb 798 message (TRUE,
aa0b6932 799 "%s: can't find socket; have you started the server?\n\
45adde32 800To start the server in Emacs, type \"M-x server-start\".\n",
aa0b6932
JB
801 progname);
802 else
42073bfb 803 message (TRUE, "%s: can't stat %s: %s\n",
aa0b6932 804 progname, server.sun_path, strerror (saved_errno));
b03d27bd 805 return INVALID_SOCKET;
aa0b6932 806 }
efb859b4 807 }
46cec291 808
4e23f2ba
JB
809 if (connect (s, (struct sockaddr *) &server, strlen (server.sun_path) + 2)
810 < 0)
46cec291 811 {
42073bfb 812 message (TRUE, "%s: connect: %s\n", progname, strerror (errno));
aa0b6932 813 return INVALID_SOCKET;
46cec291 814 }
23a7488d 815
aa0b6932
JB
816 return s;
817}
818#endif /* ! NO_SOCKETS_IN_FILE_SYSTEM */
819
820HSOCKET
821set_socket ()
822{
b03d27bd
JB
823 HSOCKET s;
824
825 INITIALIZE ();
826
aa0b6932 827#ifndef NO_SOCKETS_IN_FILE_SYSTEM
b03d27bd
JB
828 /* Explicit --socket-name argument. */
829 if (socket_name)
830 {
831 s = set_local_socket ();
832 if ((s != INVALID_SOCKET) || alternate_editor)
833 return s;
834
42073bfb 835 message (TRUE, "%s: error accessing socket \"%s\"",
b03d27bd
JB
836 progname, socket_name);
837 exit (EXIT_FAILURE);
838 }
839#endif
840
841 /* Explicit --server-file arg or EMACS_SERVER_FILE variable. */
842 if (!server_file)
843 server_file = getenv ("EMACS_SERVER_FILE");
844
845 if (server_file)
46cec291 846 {
b03d27bd
JB
847 s = set_tcp_socket ();
848 if ((s != INVALID_SOCKET) || alternate_editor)
849 return s;
850
42073bfb 851 message (TRUE, "%s: error accessing server file \"%s\"",
b03d27bd
JB
852 progname, server_file);
853 exit (EXIT_FAILURE);
46cec291 854 }
b03d27bd
JB
855
856#ifndef NO_SOCKETS_IN_FILE_SYSTEM
857 /* Implicit local socket. */
858 s = set_local_socket ();
859 if (s != INVALID_SOCKET)
860 return s;
861#endif
862
863 /* Implicit server file. */
864 server_file = "server";
865 s = set_tcp_socket ();
866 if ((s != INVALID_SOCKET) || alternate_editor)
867 return s;
868
869 /* No implicit or explicit socket, and no alternate editor. */
42073bfb 870 message (TRUE, "%s: No socket or alternate editor. Please use:\n\n"
b03d27bd
JB
871#ifndef NO_SOCKETS_IN_FILE_SYSTEM
872"\t--socket-name\n"
aa0b6932 873#endif
b03d27bd
JB
874"\t--server-file (or environment variable EMACS_SERVER_FILE)\n\
875\t--alternate-editor (or environment variable ALTERNATE_EDITOR)\n",
876 progname);
877 exit (EXIT_FAILURE);
aa0b6932 878}
46cec291 879
0e0dced5
JB
880#ifdef WINDOWSNT
881FARPROC set_fg; /* Pointer to AllowSetForegroundWindow. */
882FARPROC get_wc; /* Pointer to RealGetWindowClassA. */
883
884BOOL CALLBACK
885w32_find_emacs_process (hWnd, lParam)
886 HWND hWnd;
887 LPARAM lParam;
888{
889 DWORD pid;
890 char class[6];
891
892 /* Reject any window not of class "Emacs". */
893 if (! get_wc (hWnd, class, sizeof (class))
894 || strcmp (class, "Emacs"))
895 return TRUE;
896
897 /* We only need the process id, not the thread id. */
898 (void) GetWindowThreadProcessId (hWnd, &pid);
899
900 /* Not the one we're looking for. */
901 if (pid != (DWORD) emacs_pid) return TRUE;
902
903 /* OK, let's raise it. */
904 set_fg (emacs_pid);
905
906 /* Stop enumeration. */
907 return FALSE;
908}
909
910/*
911 * Search for a window of class "Emacs" and owned by a process with
912 * process id = emacs_pid. If found, allow it to grab the focus.
913 */
914void
915w32_give_focus ()
916{
917 HMODULE hUser32;
918
71b8f735 919 /* It shouldn't happen when dealing with TCP sockets. */
0e0dced5
JB
920 if (!emacs_pid) return;
921
922 if (!(hUser32 = LoadLibrary ("user32.dll"))) return;
923
924 /* Modern Windows restrict which processes can set the foreground window.
925 emacsclient can allow Emacs to grab the focus by calling the function
926 AllowSetForegroundWindow. Unfortunately, older Windows (W95, W98 and
927 NT) lack this function, so we have to check its availability. */
928 if ((set_fg = GetProcAddress (hUser32, "AllowSetForegroundWindow"))
929 && (get_wc = GetProcAddress (hUser32, "RealGetWindowClassA")))
930 EnumWindows (w32_find_emacs_process, (LPARAM) 0);
931
932 FreeLibrary (hUser32);
933}
934#endif
935
aa0b6932
JB
936int
937main (argc, argv)
938 int argc;
939 char **argv;
940{
941 HSOCKET s;
942 int i, rl, needlf = 0;
943 char *cwd;
944 char string[BUFSIZ+1];
945
946 progname = argv[0];
947
948 /* Process options. */
949 decode_options (argc, argv);
950
951 if ((argc - optind < 1) && !eval)
23a7488d 952 {
42073bfb
JB
953 message (TRUE, "%s: file name or argument required\nTry `%s --help' for more information\n",
954 progname, progname);
aa0b6932 955 exit (EXIT_FAILURE);
23a7488d
RS
956 }
957
aa0b6932
JB
958 if ((s = set_socket ()) == INVALID_SOCKET)
959 fail (argc, argv);
960
38732dba 961#ifdef HAVE_GETCWD
ee6a193c 962 cwd = getcwd (string, sizeof string);
38732dba
RS
963#else
964 cwd = getwd (string);
ee6a193c 965#endif
46cec291
RS
966 if (cwd == 0)
967 {
968 /* getwd puts message in STRING if it fails. */
42073bfb 969 message (TRUE, "%s: %s (%s)\n", progname,
c66648e0
JB
970#ifdef HAVE_GETCWD
971 "Cannot get current working directory",
38732dba 972#else
c66648e0 973 string,
bd252662 974#endif
c66648e0 975 strerror (errno));
97e3214d 976 fail (argc, argv);
46cec291
RS
977 }
978
c66648e0 979#ifdef WINDOWSNT
0e0dced5 980 w32_give_focus ();
c66648e0
JB
981#endif
982
5212210c 983 if (nowait)
aa0b6932 984 SEND_STRING ("-nowait ");
292d74a3 985
30be2360 986 if (eval)
aa0b6932 987 SEND_STRING ("-eval ");
30be2360
SM
988
989 if (display)
87209357 990 {
aa0b6932
JB
991 SEND_STRING ("-display ");
992 SEND_QUOTED (display);
993 SEND_STRING (" ");
87209357 994 }
30be2360 995
87209357 996 if ((argc - optind > 0))
5212210c 997 {
87209357 998 for (i = optind; i < argc; i++)
46cec291 999 {
87209357
EZ
1000 if (eval)
1001 ; /* Don't prepend any cwd or anything like that. */
1002 else if (*argv[i] == '+')
1003 {
1004 char *p = argv[i] + 1;
1005 while (isdigit ((unsigned char) *p) || *p == ':') p++;
1006 if (*p != 0)
1007 {
aa0b6932
JB
1008 SEND_QUOTED (cwd);
1009 SEND_STRING ("/");
87209357
EZ
1010 }
1011 }
b03d27bd 1012 else if (! file_name_absolute_p (argv[i]))
87209357 1013 {
aa0b6932
JB
1014 SEND_QUOTED (cwd);
1015 SEND_STRING ("/");
87209357
EZ
1016 }
1017
aa0b6932
JB
1018 SEND_QUOTED (argv[i]);
1019 SEND_STRING (" ");
46cec291 1020 }
46cec291 1021 }
87209357
EZ
1022 else
1023 {
aa0b6932 1024 while (fgets (string, BUFSIZ, stdin))
87209357 1025 {
aa0b6932 1026 SEND_QUOTED (string);
87209357 1027 }
aa0b6932 1028 SEND_STRING (" ");
87209357 1029 }
65396510 1030
aa0b6932 1031 SEND_STRING ("\n");
46cec291 1032
292d74a3 1033 /* Maybe wait for an answer. */
aa0b6932 1034 if (!nowait)
30be2360 1035 {
aa0b6932
JB
1036 if (!eval)
1037 {
1038 printf ("Waiting for Emacs...");
1039 needlf = 2;
1040 }
1041 fflush (stdout);
1042
1043 /* Now, wait for an answer and print any messages. */
1044 while ((rl = recv (s, string, BUFSIZ, 0)) > 0)
1045 {
1046 string[rl] = '\0';
1047 if (needlf == 2)
1048 printf ("\n");
1049 printf ("%s", string);
1050 needlf = string[0] == '\0' ? needlf : string[strlen (string) - 1] != '\n';
1051 }
1052
1053 if (needlf)
1054 printf ("\n");
1055 fflush (stdout);
30be2360 1056 }
23a7488d 1057
aa0b6932 1058 CLOSE_SOCKET (s);
65396510 1059 return EXIT_SUCCESS;
46cec291
RS
1060}
1061
1e7823d0 1062#endif /* HAVE_SOCKETS && HAVE_INET_SOCKETS */
aa0b6932 1063
27711600
RM
1064#ifndef HAVE_STRERROR
1065char *
1066strerror (errnum)
1067 int errnum;
1068{
1069 extern char *sys_errlist[];
1070 extern int sys_nerr;
1071
1072 if (errnum >= 0 && errnum < sys_nerr)
1073 return sys_errlist[errnum];
1074 return (char *) "Unknown error";
1075}
1076
1077#endif /* ! HAVE_STRERROR */
ab5796a9
MB
1078
1079/* arch-tag: f39bb9c4-73eb-477e-896d-50832e2ca9a7
1080 (do not change this comment) */
65396510
TTN
1081
1082/* emacsclient.c ends here */