** kzeitler@lucent.com, Nov 29: Cursor placement with mouse in long
[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,
273dc16a 3 2005, 2006 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
2381d38d 132void print_help_and_exit () NO_RETURN;
7f3bff3e 133
8f9aaa0a
RS
134struct option longopts[] =
135{
749ae770 136 { "no-wait", no_argument, NULL, 'n' },
30be2360 137 { "eval", no_argument, NULL, 'e' },
8f9aaa0a
RS
138 { "help", no_argument, NULL, 'H' },
139 { "version", no_argument, NULL, 'V' },
3cf8c6aa 140 { "alternate-editor", required_argument, NULL, 'a' },
b03d27bd 141#ifndef NO_SOCKETS_IN_FILE_SYSTEM
254107e4 142 { "socket-name", required_argument, NULL, 's' },
b03d27bd 143#endif
aa0b6932 144 { "server-file", required_argument, NULL, 'f' },
30be2360
SM
145 { "display", required_argument, NULL, 'd' },
146 { 0, 0, 0, 0 }
8f9aaa0a
RS
147};
148
42073bfb
JB
149/* Message functions. */
150
151#ifdef WINDOWSNT
152/* I first tried to check for STDOUT. The check did not work,
153 I get a valid handle also in nonconsole apps.
154 Instead I test for console title, which seems to work. */
155int
156w32_window_app()
157{
158 static int window_app = -1;
159 char szTitle[MAX_PATH];
160
161 if (window_app < 0)
162 window_app = (GetConsoleTitleA (szTitle, MAX_PATH) == 0);
163
164 return window_app;
165}
166#endif
167
168void
169message (int is_error, char *message, ...)
170{
171 char buf [2048];
172 char *msg = buf;
173 va_list args;
174
175 va_start (args, message);
176
177 if (is_error)
178 {
179 sprintf (buf, "%s: ", progname);
180 msg = strchr (buf, '\0');
181 }
182
183 vsprintf (msg, message, args);
184 va_end (args);
185
186#ifdef WINDOWSNT
187 if (w32_window_app ())
188 {
189 if (is_error)
190 MessageBox (NULL, msg, "Emacsclient ERROR", MB_ICONERROR);
191 else
192 MessageBox (NULL, msg, "Emacsclient", MB_ICONINFORMATION);
193 }
194 else
195#endif
196 fprintf (is_error ? stderr : stdout, msg);
197}
198
8f9aaa0a 199/* Decode the options from argv and argc.
5212210c 200 The global variable `optind' will say how many arguments we used up. */
8f9aaa0a 201
5212210c 202void
8f9aaa0a
RS
203decode_options (argc, argv)
204 int argc;
205 char **argv;
206{
b6b6d6d2
SM
207 alternate_editor = getenv ("ALTERNATE_EDITOR");
208
8f9aaa0a
RS
209 while (1)
210 {
211 int opt = getopt_long (argc, argv,
b03d27bd
JB
212#ifndef NO_SOCKETS_IN_FILE_SYSTEM
213 "VHnea:s:f:d:",
214#else
215 "VHnea:f:d:",
216#endif
217 longopts, 0);
8f9aaa0a
RS
218
219 if (opt == EOF)
220 break;
221
222 switch (opt)
223 {
224 case 0:
225 /* If getopt returns 0, then it has already processed a
226 long-named option. We should do nothing. */
227 break;
e69233c2 228
97e3214d
GM
229 case 'a':
230 alternate_editor = optarg;
231 break;
e69233c2 232
b03d27bd 233#ifndef NO_SOCKETS_IN_FILE_SYSTEM
254107e4
RS
234 case 's':
235 socket_name = optarg;
236 break;
b03d27bd 237#endif
254107e4 238
aa0b6932
JB
239 case 'f':
240 server_file = optarg;
241 break;
242
30be2360
SM
243 case 'd':
244 display = optarg;
245 break;
246
8f9aaa0a
RS
247 case 'n':
248 nowait = 1;
249 break;
250
30be2360
SM
251 case 'e':
252 eval = 1;
253 break;
254
8f9aaa0a 255 case 'V':
42073bfb 256 message (FALSE, "emacsclient %s\n", VERSION);
65396510 257 exit (EXIT_SUCCESS);
8f9aaa0a 258 break;
46cec291 259
8f9aaa0a 260 case 'H':
8f9aaa0a 261 print_help_and_exit ();
20c396e8
JB
262 break;
263
264 default:
42073bfb 265 message (TRUE, "Try `%s --help' for more information\n", progname);
65396510 266 exit (EXIT_FAILURE);
20c396e8 267 break;
8f9aaa0a
RS
268 }
269 }
8f9aaa0a
RS
270}
271
7f3bff3e 272void
8f9aaa0a
RS
273print_help_and_exit ()
274{
42073bfb 275 message (FALSE,
20c396e8 276 "Usage: %s [OPTIONS] FILE...\n\
30be2360
SM
277Tell the Emacs server to visit the specified files.\n\
278Every FILE can be either just a FILENAME or [+LINE[:COLUMN]] FILENAME.\n\
20c396e8 279\n\
30be2360 280The following OPTIONS are accepted:\n\
30aa95ce
JB
281\n\
282-V, --version Just print version info and return\n\
283-H, --help Print this usage information message\n\
284-e, --eval Evaluate FILE arguments as Lisp expressions\n\
285-n, --no-wait Don't wait for the server to return\n\
286-d, --display=DISPLAY Visit the file in the given display\n"
aa0b6932
JB
287#ifndef NO_SOCKETS_IN_FILE_SYSTEM
288"-s, --socket-name=FILENAME\n\
30aa95ce 289 Set filename of the UNIX socket for communication\n"
aa0b6932
JB
290#endif
291"-f, --server-file=FILENAME\n\
30aa95ce 292 Set filename of the TCP authentication file\n\
30be2360 293-a, --alternate-editor=EDITOR\n\
30aa95ce 294 Editor to fallback to if server is not running\n\
20c396e8 295\n\
30be2360 296Report bugs to bug-gnu-emacs@gnu.org.\n", progname);
65396510 297 exit (EXIT_SUCCESS);
8f9aaa0a 298}
5212210c 299
aa0b6932
JB
300\f
301/*
302 Try to run a different command, or --if no alternate editor is
303 defined-- exit with an errorcode.
304*/
305void
306fail (argc, argv)
307 int argc;
308 char **argv;
309{
310 if (alternate_editor)
311 {
312 int i = optind - 1;
b73ea44b
JB
313#ifdef WINDOWSNT
314 argv[i] = (char *)alternate_editor;
315#endif
aa0b6932 316 execvp (alternate_editor, argv + i);
42073bfb 317 message (TRUE, "%s: error executing alternate editor \"%s\"\n",
aa0b6932
JB
318 progname, alternate_editor);
319 }
aa0b6932
JB
320 exit (EXIT_FAILURE);
321}
322
323\f
1e7823d0 324#if !defined (HAVE_SOCKETS) || !defined (HAVE_INET_SOCKETS)
aa0b6932
JB
325
326int
327main (argc, argv)
328 int argc;
329 char **argv;
330{
42073bfb 331 message (TRUE, "%s: Sorry, the Emacs server is supported only\non systems with Berkely sockets.\n",
aa0b6932 332 argv[0]);
aa0b6932
JB
333
334 fail (argc, argv);
335}
336
1e7823d0 337#else /* HAVE_SOCKETS && HAVE_INET_SOCKETS */
aa0b6932
JB
338
339#ifdef WINDOWSNT
340# include <winsock2.h>
341#else
342# include <sys/types.h>
343# include <sys/socket.h>
344# include <sys/un.h>
345# include <sys/stat.h>
346# include <errno.h>
347#endif
348
349#define AUTH_KEY_LENGTH 64
350#define SEND_BUFFER_SIZE 4096
351
352extern char *strerror ();
353extern int errno;
354
355/* Buffer to accumulate data to send in TCP connections. */
356char send_buffer[SEND_BUFFER_SIZE + 1];
357int sblen = 0; /* Fill pointer for the send buffer. */
358
359/* Let's send the data to Emacs when either
360 - the data ends in "\n", or
361 - the buffer is full (but this shouldn't happen)
362 Otherwise, we just accumulate it. */
b03d27bd
JB
363void
364send_to_emacs (s, data)
aa0b6932
JB
365 HSOCKET s;
366 char *data;
367{
368 while (data)
369 {
370 int dlen = strlen (data);
371 if (dlen + sblen >= SEND_BUFFER_SIZE)
372 {
373 int part = SEND_BUFFER_SIZE - sblen;
374 strncpy (&send_buffer[sblen], data, part);
375 data += part;
376 sblen = SEND_BUFFER_SIZE;
377 }
378 else if (dlen)
379 {
380 strcpy (&send_buffer[sblen], data);
381 data = NULL;
382 sblen += dlen;
383 }
384 else
385 break;
386
387 if (sblen == SEND_BUFFER_SIZE
388 || (sblen > 0 && send_buffer[sblen-1] == '\n'))
389 {
390 int sent = send (s, send_buffer, sblen, 0);
391 if (sent != sblen)
392 strcpy (send_buffer, &send_buffer[sent]);
393 sblen -= sent;
394 }
395 }
396}
397
a4cf2096
RS
398/* In NAME, insert a & before each &, each space, each newline, and
399 any initial -. Change spaces to underscores, too, so that the
5212210c 400 return value never contains a space. */
87209357 401void
aa0b6932
JB
402quote_file_name (s, name)
403 HSOCKET s;
5212210c
RS
404 char *name;
405{
406 char *copy = (char *) malloc (strlen (name) * 2 + 1);
407 char *p, *q;
408
409 p = name;
410 q = copy;
411 while (*p)
412 {
413 if (*p == ' ')
414 {
f1db6a73 415 *q++ = '&';
5212210c
RS
416 *q++ = '_';
417 p++;
418 }
3cf8c6aa
SM
419 else if (*p == '\n')
420 {
421 *q++ = '&';
422 *q++ = 'n';
423 p++;
424 }
5212210c
RS
425 else
426 {
f1db6a73
RS
427 if (*p == '&' || (*p == '-' && p == name))
428 *q++ = '&';
5212210c
RS
429 *q++ = *p++;
430 }
431 }
f1db6a73 432 *q++ = 0;
5212210c 433
aa0b6932 434 SEND_STRING (copy);
87209357
EZ
435
436 free (copy);
5212210c 437}
0c76956f 438
b03d27bd
JB
439int
440file_name_absolute_p (filename)
441 const unsigned char *filename;
442{
443 /* Sanity check, it shouldn't happen. */
444 if (! filename) return FALSE;
445
446 /* /xxx is always an absolute path. */
447 if (filename[0] == '/') return TRUE;
448
449 /* Empty filenames (which shouldn't happen) are relative. */
450 if (filename[0] == '\0') return FALSE;
451
452#ifdef WINDOWSNT
453 /* X:\xxx is always absolute; X:xxx is an error and will fail. */
5f7a4874 454 if (isalpha (filename[0])
cb0297bb 455 && filename[1] == ':' && (filename[2] == '\\' || filename[2] == '/'))
b03d27bd
JB
456 return TRUE;
457
458 /* Both \xxx and \\xxx\yyy are absolute. */
459 if (filename[0] == '\\') return TRUE;
460#endif
461
462 return FALSE;
463}
464
aa0b6932 465#ifdef WINDOWSNT
db9cd97a 466/* Wrapper to make WSACleanup a cdecl, as required by atexit(). */
b03d27bd
JB
467void
468__cdecl close_winsock ()
aa0b6932
JB
469{
470 WSACleanup ();
471}
0c76956f 472
b03d27bd
JB
473/* Initialize the WinSock2 library. */
474void
475initialize_sockets ()
0c76956f 476{
aa0b6932
JB
477 WSADATA wsaData;
478
aa0b6932
JB
479 if (WSAStartup (MAKEWORD (2, 0), &wsaData))
480 {
42073bfb 481 message (TRUE, "%s: error initializing WinSock2", progname);
aa0b6932
JB
482 exit (EXIT_FAILURE);
483 }
484
485 atexit (close_winsock);
0c76956f 486}
e35fc962 487#endif /* WINDOWSNT */
8f9aaa0a 488\f
97e3214d 489/*
aa0b6932 490 * Read the information needed to set up a TCP comm channel with
434a6c5d 491 * the Emacs server: host, port, pid and authentication string.
97e3214d 492*/
b03d27bd
JB
493int
494get_server_config (server, authentication)
aa0b6932
JB
495 struct sockaddr_in *server;
496 char *authentication;
97e3214d 497{
aa0b6932
JB
498 char dotted[32];
499 char *port;
434a6c5d 500 char *pid;
b03d27bd 501 FILE *config = NULL;
aa0b6932 502
b03d27bd
JB
503 if (file_name_absolute_p (server_file))
504 config = fopen (server_file, "rb");
505 else
97e3214d 506 {
aa0b6932 507 char *home = getenv ("HOME");
88b46d84 508
aa0b6932
JB
509 if (home)
510 {
511 char *path = alloca (32 + strlen (home) + strlen (server_file));
512 sprintf (path, "%s/.emacs.d/server/%s", home, server_file);
513 config = fopen (path, "rb");
514 }
88b46d84
JB
515#ifdef WINDOWSNT
516 if (!config && (home = getenv ("APPDATA")))
517 {
518 char *path = alloca (32 + strlen (home) + strlen (server_file));
519 sprintf (path, "%s/.emacs.d/server/%s", home, server_file);
520 config = fopen (path, "rb");
521 }
522#endif
aa0b6932
JB
523 }
524
525 if (! config)
526 return FALSE;
527
528 if (fgets (dotted, sizeof dotted, config)
434a6c5d
JB
529 && (port = strchr (dotted, ':'))
530 && (pid = strchr (port, ' ')))
aa0b6932
JB
531 {
532 *port++ = '\0';
434a6c5d 533 *pid++ = '\0';
97e3214d
GM
534 }
535 else
536 {
42073bfb 537 message (TRUE, "%s: invalid configuration info", progname);
65396510 538 exit (EXIT_FAILURE);
97e3214d 539 }
97e3214d 540
aa0b6932
JB
541 server->sin_family = AF_INET;
542 server->sin_addr.s_addr = inet_addr (dotted);
543 server->sin_port = htons (atoi (port));
97e3214d 544
aa0b6932
JB
545 if (! fread (authentication, AUTH_KEY_LENGTH, 1, config))
546 {
42073bfb 547 message (TRUE, "%s: cannot read authentication info", progname);
aa0b6932
JB
548 exit (EXIT_FAILURE);
549 }
46cec291 550
aa0b6932 551 fclose (config);
97e3214d 552
434a6c5d
JB
553#ifdef WINDOWSNT
554 /*
555 Modern Windows restrict which processes can set the foreground window.
556 So, for emacsclient to be able to force Emacs into the foreground, we
557 have to call AllowSetForegroundWindow(). Unfortunately, older Windows
558 (W95, W98 and NT) don't have this function, so we have to check first.
559
560 We're doing this here because it has to be done before sending info
561 to Emacs, and otherwise we'll need a global variable just to pass around
562 the pid, which is also inelegant.
563 */
564 {
565 HMODULE hUser32;
566
567 if (hUser32 = LoadLibrary ("user32.dll"))
568 {
2dc07a12 569 FARPROC set_fg;
434a6c5d
JB
570 if (set_fg = GetProcAddress (hUser32, "AllowSetForegroundWindow"))
571 set_fg (atoi (pid));
572 FreeLibrary (hUser32);
573 }
574 }
575#endif
576
aa0b6932 577 return TRUE;
46cec291
RS
578}
579
aa0b6932
JB
580HSOCKET
581set_tcp_socket ()
582{
583 HSOCKET s;
584 struct sockaddr_in server;
aa0b6932
JB
585 struct linger l_arg = {1, 1};
586 char auth_string[AUTH_KEY_LENGTH + 1];
46cec291 587
aa0b6932
JB
588 if (! get_server_config (&server, auth_string))
589 return INVALID_SOCKET;
590
b03d27bd 591 if (server.sin_addr.s_addr != inet_addr ("127.0.0.1"))
42073bfb 592 message (TRUE, "%s: connected to remote socket at %s\n",
b03d27bd
JB
593 progname, inet_ntoa (server.sin_addr));
594
aa0b6932
JB
595 /*
596 * Open up an AF_INET socket
597 */
598 if ((s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
599 {
42073bfb 600 message (TRUE, "%s: socket: %s\n", progname, strerror (errno));
aa0b6932
JB
601 return INVALID_SOCKET;
602 }
603
604 /*
605 * Set up the socket
606 */
607 if (connect (s, (struct sockaddr *) &server, sizeof server) < 0)
608 {
42073bfb 609 message (TRUE, "%s: connect: %s\n", progname, strerror (errno));
aa0b6932
JB
610 return INVALID_SOCKET;
611 }
612
aa0b6932
JB
613 setsockopt (s, SOL_SOCKET, SO_LINGER, (char *) &l_arg, sizeof l_arg);
614
615 /*
616 * Send the authentication
617 */
618 auth_string[AUTH_KEY_LENGTH] = '\0';
619
620 SEND_STRING ("-auth ");
621 SEND_STRING (auth_string);
622 SEND_STRING ("\n");
623
624 return s;
625}
626
627#if !defined (NO_SOCKETS_IN_FILE_SYSTEM)
46cec291 628
9f637eea
GM
629/* Three possibilities:
630 2 - can't be `stat'ed (sets errno)
631 1 - isn't owned by us
632 0 - success: none of the above */
633
634static int
635socket_status (socket_name)
636 char *socket_name;
637{
638 struct stat statbfr;
639
640 if (stat (socket_name, &statbfr) == -1)
641 return 2;
642
643 if (statbfr.st_uid != geteuid ())
644 return 1;
645
646 return 0;
647}
648
aa0b6932
JB
649HSOCKET
650set_local_socket ()
46cec291 651{
aa0b6932 652 HSOCKET s;
46cec291 653 struct sockaddr_un server;
46cec291 654
e69233c2 655 /*
46cec291
RS
656 * Open up an AF_UNIX socket in this person's home directory
657 */
658
659 if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
660 {
42073bfb 661 message (TRUE, "%s: socket: %s\n", progname, strerror (errno));
aa0b6932 662 return INVALID_SOCKET;
46cec291 663 }
e69233c2 664
46cec291 665 server.sun_family = AF_UNIX;
c5fee545 666
c5fee545 667 {
9f637eea 668 int sock_status = 0;
5c9659d3 669 int default_sock = !socket_name;
152b6e83 670 int saved_errno;
0734b0d0
SM
671 char *server_name = "server";
672
673 if (socket_name && !index (socket_name, '/') && !index (socket_name, '\\'))
674 { /* socket_name is a file name component. */
675 server_name = socket_name;
676 socket_name = NULL;
677 default_sock = 1; /* Try both UIDs. */
678 }
efb859b4 679
5c9659d3 680 if (default_sock)
254107e4 681 {
0734b0d0
SM
682 socket_name = alloca (100 + strlen (server_name));
683 sprintf (socket_name, "/tmp/emacs%d/%s",
684 (int) geteuid (), server_name);
254107e4
RS
685 }
686
687 if (strlen (socket_name) < sizeof (server.sun_path))
688 strcpy (server.sun_path, socket_name);
689 else
5c9659d3 690 {
42073bfb 691 message (TRUE, "%s: socket-name %s too long",
aa0b6932 692 progname, socket_name);
65396510 693 exit (EXIT_FAILURE);
5c9659d3 694 }
efb859b4 695
9f637eea
GM
696 /* See if the socket exists, and if it's owned by us. */
697 sock_status = socket_status (server.sun_path);
152b6e83 698 saved_errno = errno;
5c9659d3 699 if (sock_status && default_sock)
efb859b4 700 {
9f637eea
GM
701 /* Failing that, see if LOGNAME or USER exist and differ from
702 our euid. If so, look for a socket based on the UID
703 associated with the name. This is reminiscent of the logic
704 that init_editfns uses to set the global Vuser_full_name. */
e69233c2 705
9f637eea 706 char *user_name = (char *) getenv ("LOGNAME");
293f9f2a 707
9f637eea
GM
708 if (!user_name)
709 user_name = (char *) getenv ("USER");
e69233c2 710
9f637eea
GM
711 if (user_name)
712 {
713 struct passwd *pw = getpwnam (user_name);
293f9f2a 714
9f637eea
GM
715 if (pw && (pw->pw_uid != geteuid ()))
716 {
717 /* We're running under su, apparently. */
0734b0d0
SM
718 socket_name = alloca (100 + strlen (server_name));
719 sprintf (socket_name, "/tmp/emacs%d/%s",
720 (int) pw->pw_uid, server_name);
5c9659d3
SM
721
722 if (strlen (socket_name) < sizeof (server.sun_path))
723 strcpy (server.sun_path, socket_name);
724 else
725 {
42073bfb 726 message (TRUE, "%s: socket-name %s too long",
aa0b6932 727 progname, socket_name);
65396510 728 exit (EXIT_FAILURE);
5c9659d3
SM
729 }
730
9f637eea 731 sock_status = socket_status (server.sun_path);
152b6e83 732 saved_errno = errno;
9f637eea 733 }
293f9f2a
RS
734 else
735 errno = saved_errno;
9f637eea 736 }
efb859b4 737 }
e69233c2 738
aa0b6932
JB
739 switch (sock_status)
740 {
741 case 1:
742 /* There's a socket, but it isn't owned by us. This is OK if
743 we are root. */
744 if (0 != geteuid ())
745 {
42073bfb 746 message (TRUE, "%s: Invalid socket owner\n", progname);
aa0b6932
JB
747 return INVALID_SOCKET;
748 }
749 break;
750
751 case 2:
752 /* `stat' failed */
753 if (saved_errno == ENOENT)
42073bfb 754 message (TRUE,
aa0b6932 755 "%s: can't find socket; have you started the server?\n\
45adde32 756To start the server in Emacs, type \"M-x server-start\".\n",
aa0b6932
JB
757 progname);
758 else
42073bfb 759 message (TRUE, "%s: can't stat %s: %s\n",
aa0b6932 760 progname, server.sun_path, strerror (saved_errno));
b03d27bd 761 return INVALID_SOCKET;
aa0b6932 762 }
efb859b4 763 }
46cec291 764
4e23f2ba
JB
765 if (connect (s, (struct sockaddr *) &server, strlen (server.sun_path) + 2)
766 < 0)
46cec291 767 {
42073bfb 768 message (TRUE, "%s: connect: %s\n", progname, strerror (errno));
aa0b6932 769 return INVALID_SOCKET;
46cec291 770 }
23a7488d 771
aa0b6932
JB
772 return s;
773}
774#endif /* ! NO_SOCKETS_IN_FILE_SYSTEM */
775
776HSOCKET
777set_socket ()
778{
b03d27bd
JB
779 HSOCKET s;
780
781 INITIALIZE ();
782
aa0b6932 783#ifndef NO_SOCKETS_IN_FILE_SYSTEM
b03d27bd
JB
784 /* Explicit --socket-name argument. */
785 if (socket_name)
786 {
787 s = set_local_socket ();
788 if ((s != INVALID_SOCKET) || alternate_editor)
789 return s;
790
42073bfb 791 message (TRUE, "%s: error accessing socket \"%s\"",
b03d27bd
JB
792 progname, socket_name);
793 exit (EXIT_FAILURE);
794 }
795#endif
796
797 /* Explicit --server-file arg or EMACS_SERVER_FILE variable. */
798 if (!server_file)
799 server_file = getenv ("EMACS_SERVER_FILE");
800
801 if (server_file)
46cec291 802 {
b03d27bd
JB
803 s = set_tcp_socket ();
804 if ((s != INVALID_SOCKET) || alternate_editor)
805 return s;
806
42073bfb 807 message (TRUE, "%s: error accessing server file \"%s\"",
b03d27bd
JB
808 progname, server_file);
809 exit (EXIT_FAILURE);
46cec291 810 }
b03d27bd
JB
811
812#ifndef NO_SOCKETS_IN_FILE_SYSTEM
813 /* Implicit local socket. */
814 s = set_local_socket ();
815 if (s != INVALID_SOCKET)
816 return s;
817#endif
818
819 /* Implicit server file. */
820 server_file = "server";
821 s = set_tcp_socket ();
822 if ((s != INVALID_SOCKET) || alternate_editor)
823 return s;
824
825 /* No implicit or explicit socket, and no alternate editor. */
42073bfb 826 message (TRUE, "%s: No socket or alternate editor. Please use:\n\n"
b03d27bd
JB
827#ifndef NO_SOCKETS_IN_FILE_SYSTEM
828"\t--socket-name\n"
aa0b6932 829#endif
b03d27bd
JB
830"\t--server-file (or environment variable EMACS_SERVER_FILE)\n\
831\t--alternate-editor (or environment variable ALTERNATE_EDITOR)\n",
832 progname);
833 exit (EXIT_FAILURE);
aa0b6932 834}
46cec291 835
aa0b6932
JB
836int
837main (argc, argv)
838 int argc;
839 char **argv;
840{
841 HSOCKET s;
842 int i, rl, needlf = 0;
843 char *cwd;
844 char string[BUFSIZ+1];
845
846 progname = argv[0];
847
848 /* Process options. */
849 decode_options (argc, argv);
850
851 if ((argc - optind < 1) && !eval)
23a7488d 852 {
42073bfb
JB
853 message (TRUE, "%s: file name or argument required\nTry `%s --help' for more information\n",
854 progname, progname);
aa0b6932 855 exit (EXIT_FAILURE);
23a7488d
RS
856 }
857
aa0b6932
JB
858 if ((s = set_socket ()) == INVALID_SOCKET)
859 fail (argc, argv);
860
38732dba 861#ifdef HAVE_GETCWD
ee6a193c 862 cwd = getcwd (string, sizeof string);
38732dba
RS
863#else
864 cwd = getwd (string);
ee6a193c 865#endif
46cec291
RS
866 if (cwd == 0)
867 {
868 /* getwd puts message in STRING if it fails. */
38732dba 869#ifdef HAVE_GETCWD
42073bfb 870 message (TRUE, "%s: %s (%s)\n", progname,
bb5618fe 871 "Cannot get current working directory", strerror (errno));
38732dba 872#else
42073bfb 873 message (TRUE, "%s: %s (%s)\n", progname, string, strerror (errno));
bd252662 874#endif
97e3214d 875 fail (argc, argv);
46cec291
RS
876 }
877
5212210c 878 if (nowait)
aa0b6932 879 SEND_STRING ("-nowait ");
292d74a3 880
30be2360 881 if (eval)
aa0b6932 882 SEND_STRING ("-eval ");
30be2360
SM
883
884 if (display)
87209357 885 {
aa0b6932
JB
886 SEND_STRING ("-display ");
887 SEND_QUOTED (display);
888 SEND_STRING (" ");
87209357 889 }
30be2360 890
87209357 891 if ((argc - optind > 0))
5212210c 892 {
87209357 893 for (i = optind; i < argc; i++)
46cec291 894 {
87209357
EZ
895 if (eval)
896 ; /* Don't prepend any cwd or anything like that. */
897 else if (*argv[i] == '+')
898 {
899 char *p = argv[i] + 1;
900 while (isdigit ((unsigned char) *p) || *p == ':') p++;
901 if (*p != 0)
902 {
aa0b6932
JB
903 SEND_QUOTED (cwd);
904 SEND_STRING ("/");
87209357
EZ
905 }
906 }
b03d27bd 907 else if (! file_name_absolute_p (argv[i]))
87209357 908 {
aa0b6932
JB
909 SEND_QUOTED (cwd);
910 SEND_STRING ("/");
87209357
EZ
911 }
912
aa0b6932
JB
913 SEND_QUOTED (argv[i]);
914 SEND_STRING (" ");
46cec291 915 }
46cec291 916 }
87209357
EZ
917 else
918 {
aa0b6932 919 while (fgets (string, BUFSIZ, stdin))
87209357 920 {
aa0b6932 921 SEND_QUOTED (string);
87209357 922 }
aa0b6932 923 SEND_STRING (" ");
87209357 924 }
65396510 925
aa0b6932 926 SEND_STRING ("\n");
46cec291 927
292d74a3 928 /* Maybe wait for an answer. */
aa0b6932 929 if (!nowait)
30be2360 930 {
aa0b6932
JB
931 if (!eval)
932 {
933 printf ("Waiting for Emacs...");
934 needlf = 2;
935 }
936 fflush (stdout);
937
938 /* Now, wait for an answer and print any messages. */
939 while ((rl = recv (s, string, BUFSIZ, 0)) > 0)
940 {
941 string[rl] = '\0';
942 if (needlf == 2)
943 printf ("\n");
944 printf ("%s", string);
945 needlf = string[0] == '\0' ? needlf : string[strlen (string) - 1] != '\n';
946 }
947
948 if (needlf)
949 printf ("\n");
950 fflush (stdout);
30be2360 951 }
23a7488d 952
aa0b6932 953 CLOSE_SOCKET (s);
65396510 954 return EXIT_SUCCESS;
46cec291
RS
955}
956
1e7823d0 957#endif /* HAVE_SOCKETS && HAVE_INET_SOCKETS */
aa0b6932 958
27711600
RM
959#ifndef HAVE_STRERROR
960char *
961strerror (errnum)
962 int errnum;
963{
964 extern char *sys_errlist[];
965 extern int sys_nerr;
966
967 if (errnum >= 0 && errnum < sys_nerr)
968 return sys_errlist[errnum];
969 return (char *) "Unknown error";
970}
971
972#endif /* ! HAVE_STRERROR */
ab5796a9
MB
973
974/* arch-tag: f39bb9c4-73eb-477e-896d-50832e2ca9a7
975 (do not change this comment) */
65396510
TTN
976
977/* emacsclient.c ends here */