]>
code.delx.au - gnu-emacs/blob - lib-src/emacsclient.c
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. */
35 # define HAVE_INET_SOCKETS
36 # define NO_SOCKETS_IN_FILE_SYSTEM
38 # define HSOCKET SOCKET
39 # define CLOSE_SOCKET closesocket
40 # define INITIALIZE() (initialize_sockets ())
42 #else /* !WINDOWSNT */
44 # ifdef HAVE_INET_SOCKETS
45 # include <netinet/in.h>
48 # define INVALID_SOCKET -1
50 # define CLOSE_SOCKET close
53 #endif /* !WINDOWSNT */
69 #else /* not WINDOWSNT */
71 #endif /* not WINDOWSNT */
74 char *getenv (), *getwd ();
78 #define VERSION "unspecified"
81 #define SEND_STRING(data) (send_to_emacs (s, (data)))
82 #define SEND_QUOTED(data) (quote_file_name (s, (data)))
85 #define EXIT_SUCCESS 0
89 #define EXIT_FAILURE 1
104 /* Name used to invoke this program. */
107 /* Nonzero means don't wait for a response from Emacs. --no-wait. */
110 /* Nonzero means args are expressions to be evaluated. --eval. */
113 /* The display on which Emacs should work. --display. */
114 char *display
= NULL
;
116 /* If non-NULL, the name of an editor to fallback to if the server
117 is not running. --alternate-editor. */
118 const char * alternate_editor
= NULL
;
120 /* If non-NULL, the filename of the UNIX socket. */
121 char *socket_name
= NULL
;
123 /* If non-NULL, the filename of the authentication file. */
124 char *server_file
= NULL
;
126 void print_help_and_exit () NO_RETURN
;
128 struct option longopts
[] =
130 { "no-wait", no_argument
, NULL
, 'n' },
131 { "eval", no_argument
, NULL
, 'e' },
132 { "help", no_argument
, NULL
, 'H' },
133 { "version", no_argument
, NULL
, 'V' },
134 { "alternate-editor", required_argument
, NULL
, 'a' },
135 { "socket-name", required_argument
, NULL
, 's' },
136 { "server-file", required_argument
, NULL
, 'f' },
137 { "display", required_argument
, NULL
, 'd' },
141 /* Decode the options from argv and argc.
142 The global variable `optind' will say how many arguments we used up. */
145 decode_options (argc
, argv
)
149 alternate_editor
= getenv ("ALTERNATE_EDITOR");
150 server_file
= getenv ("EMACS_SERVER_FILE");
154 int opt
= getopt_long (argc
, argv
,
155 "VHnea:s:f:d:", longopts
, 0);
163 /* If getopt returns 0, then it has already processed a
164 long-named option. We should do nothing. */
168 alternate_editor
= optarg
;
172 socket_name
= optarg
;
176 server_file
= optarg
;
192 printf ("emacsclient %s\n", VERSION
);
197 print_help_and_exit ();
201 fprintf (stderr
, "Try `%s --help' for more information\n", progname
);
209 print_help_and_exit ()
212 "Usage: %s [OPTIONS] FILE...\n\
213 Tell the Emacs server to visit the specified files.\n\
214 Every FILE can be either just a FILENAME or [+LINE[:COLUMN]] FILENAME.\n\
216 The following OPTIONS are accepted:\n\
217 -V, --version Just print a version info and return\n\
218 -H, --help Print this usage information message\n\
219 -n, --no-wait Don't wait for the server to return\n\
220 -e, --eval Evaluate the FILE arguments as ELisp expressions\n\
221 -d, --display=DISPLAY Visit the file in the given display\n"
222 #ifndef NO_SOCKETS_IN_FILE_SYSTEM
223 "-s, --socket-name=FILENAME\n\
224 Set the filename of the UNIX socket for communication\n"
226 "-f, --server-file=FILENAME\n\
227 Set the filename of the TCP configuration file\n\
228 -a, --alternate-editor=EDITOR\n\
229 Editor to fallback to if the server is not running\n\
231 Report bugs to bug-gnu-emacs@gnu.org.\n", progname
);
237 Try to run a different command, or --if no alternate editor is
238 defined-- exit with an errorcode.
245 if (alternate_editor
)
249 argv
[i
] = (char *)alternate_editor
;
251 execvp (alternate_editor
, argv
+ i
);
252 fprintf (stderr
, "%s: error executing alternate editor \"%s\"\n",
253 progname
, alternate_editor
);
257 fprintf (stderr
, "%s: No socket or alternate editor. Please use:\n\n"
258 #if !defined (NO_SOCKETS_IN_FILE_SYSTEM)
261 "\t--server-file (or environment variable EMACS_SERVER_FILE)\n\
262 \t--alternate-editor (or environment variable ALTERNATE_EDITOR)\n",
269 #if !defined (HAVE_SOCKETS) || !defined (HAVE_INET_SOCKETS)
276 fprintf (stderr
, "%s: Sorry, the Emacs server is supported only\n",
278 fprintf (stderr
, "on systems with Berkeley sockets.\n");
283 #else /* HAVE_SOCKETS && HAVE_INET_SOCKETS */
286 # include <winsock2.h>
288 # include <sys/types.h>
289 # include <sys/socket.h>
291 # include <sys/stat.h>
295 #define AUTH_KEY_LENGTH 64
296 #define SEND_BUFFER_SIZE 4096
298 extern char *strerror ();
301 /* Buffer to accumulate data to send in TCP connections. */
302 char send_buffer
[SEND_BUFFER_SIZE
+ 1];
303 int sblen
= 0; /* Fill pointer for the send buffer. */
305 /* Let's send the data to Emacs when either
306 - the data ends in "\n", or
307 - the buffer is full (but this shouldn't happen)
308 Otherwise, we just accumulate it. */
309 void send_to_emacs (s
, data
)
315 int dlen
= strlen (data
);
316 if (dlen
+ sblen
>= SEND_BUFFER_SIZE
)
318 int part
= SEND_BUFFER_SIZE
- sblen
;
319 strncpy (&send_buffer
[sblen
], data
, part
);
321 sblen
= SEND_BUFFER_SIZE
;
325 strcpy (&send_buffer
[sblen
], data
);
332 if (sblen
== SEND_BUFFER_SIZE
333 || (sblen
> 0 && send_buffer
[sblen
-1] == '\n'))
335 int sent
= send (s
, send_buffer
, sblen
, 0);
337 strcpy (send_buffer
, &send_buffer
[sent
]);
343 /* In NAME, insert a & before each &, each space, each newline, and
344 any initial -. Change spaces to underscores, too, so that the
345 return value never contains a space. */
347 quote_file_name (s
, name
)
351 char *copy
= (char *) malloc (strlen (name
) * 2 + 1);
372 if (*p
== '&' || (*p
== '-' && p
== name
))
385 /* Wrapper to make WSACleanup a cdecl, as required by atexit(). */
386 void __cdecl
close_winsock ()
391 void initialize_sockets ()
395 /* Initialize the WinSock2 library. */
396 if (WSAStartup (MAKEWORD (2, 0), &wsaData
))
398 fprintf (stderr
, "%s: error initializing WinSock2", progname
);
402 atexit (close_winsock
);
404 #endif /* WINDOWSNT */
407 * Read the information needed to set up a TCP comm channel with
408 * the Emacs server: host, port and authentication string.
410 int get_server_config (server
, authentication
)
411 struct sockaddr_in
*server
;
412 char *authentication
;
418 if (! (config
= fopen (server_file
, "rb")))
420 char *home
= getenv ("HOME");
423 home
= getenv ("APPDATA");
427 char *path
= alloca (32 + strlen (home
) + strlen (server_file
));
428 sprintf (path
, "%s/.emacs.d/server/%s", home
, server_file
);
429 config
= fopen (path
, "rb");
436 if (fgets (dotted
, sizeof dotted
, config
)
437 && (port
= strchr (dotted
, ':')))
443 fprintf (stderr
, "%s: invalid configuration info", progname
);
447 server
->sin_family
= AF_INET
;
448 server
->sin_addr
.s_addr
= inet_addr (dotted
);
449 server
->sin_port
= htons (atoi (port
));
451 if (! fread (authentication
, AUTH_KEY_LENGTH
, 1, config
))
453 fprintf (stderr
, "%s: cannot read authentication info", progname
);
466 struct sockaddr_in server
;
467 struct linger l_arg
= {1, 1};
468 char auth_string
[AUTH_KEY_LENGTH
+ 1];
472 if (! get_server_config (&server
, auth_string
))
473 return INVALID_SOCKET
;
476 * Open up an AF_INET socket
478 if ((s
= socket (AF_INET
, SOCK_STREAM
, IPPROTO_TCP
)) < 0)
480 fprintf (stderr
, "%s: ", progname
);
482 return INVALID_SOCKET
;
488 if (connect (s
, (struct sockaddr
*) &server
, sizeof server
) < 0)
490 fprintf (stderr
, "%s: ", progname
);
492 return INVALID_SOCKET
;
495 setsockopt (s
, SOL_SOCKET
, SO_LINGER
, (char *) &l_arg
, sizeof l_arg
);
498 * Send the authentication
500 auth_string
[AUTH_KEY_LENGTH
] = '\0';
502 SEND_STRING ("-auth ");
503 SEND_STRING (auth_string
);
509 #if !defined (NO_SOCKETS_IN_FILE_SYSTEM)
511 /* Three possibilities:
512 2 - can't be `stat'ed (sets errno)
513 1 - isn't owned by us
514 0 - success: none of the above */
517 socket_status (socket_name
)
522 if (stat (socket_name
, &statbfr
) == -1)
525 if (statbfr
.st_uid
!= geteuid ())
535 struct sockaddr_un server
;
538 * Open up an AF_UNIX socket in this person's home directory
541 if ((s
= socket (AF_UNIX
, SOCK_STREAM
, 0)) < 0)
543 fprintf (stderr
, "%s: ", progname
);
545 return INVALID_SOCKET
;
548 server
.sun_family
= AF_UNIX
;
552 int default_sock
= !socket_name
;
554 char *server_name
= "server";
556 if (socket_name
&& !index (socket_name
, '/') && !index (socket_name
, '\\'))
557 { /* socket_name is a file name component. */
558 server_name
= socket_name
;
560 default_sock
= 1; /* Try both UIDs. */
565 socket_name
= alloca (100 + strlen (server_name
));
566 sprintf (socket_name
, "/tmp/emacs%d/%s",
567 (int) geteuid (), server_name
);
570 if (strlen (socket_name
) < sizeof (server
.sun_path
))
571 strcpy (server
.sun_path
, socket_name
);
574 fprintf (stderr
, "%s: socket-name %s too long",
575 progname
, socket_name
);
579 /* See if the socket exists, and if it's owned by us. */
580 sock_status
= socket_status (server
.sun_path
);
582 if (sock_status
&& default_sock
)
584 /* Failing that, see if LOGNAME or USER exist and differ from
585 our euid. If so, look for a socket based on the UID
586 associated with the name. This is reminiscent of the logic
587 that init_editfns uses to set the global Vuser_full_name. */
589 char *user_name
= (char *) getenv ("LOGNAME");
592 user_name
= (char *) getenv ("USER");
596 struct passwd
*pw
= getpwnam (user_name
);
598 if (pw
&& (pw
->pw_uid
!= geteuid ()))
600 /* We're running under su, apparently. */
601 socket_name
= alloca (100 + strlen (server_name
));
602 sprintf (socket_name
, "/tmp/emacs%d/%s",
603 (int) pw
->pw_uid
, server_name
);
605 if (strlen (socket_name
) < sizeof (server
.sun_path
))
606 strcpy (server
.sun_path
, socket_name
);
609 fprintf (stderr
, "%s: socket-name %s too long",
610 progname
, socket_name
);
614 sock_status
= socket_status (server
.sun_path
);
625 /* There's a socket, but it isn't owned by us. This is OK if
629 fprintf (stderr
, "%s: Invalid socket owner\n", progname
);
630 return INVALID_SOCKET
;
636 if (saved_errno
== ENOENT
)
638 "%s: can't find socket; have you started the server?\n\
639 To start the server in Emacs, type \"M-x server-start\".\n",
642 fprintf (stderr
, "%s: can't stat %s: %s\n",
643 progname
, server
.sun_path
, strerror (saved_errno
));
644 return INVALID_SOCKET
;
648 if (connect (s
, (struct sockaddr
*) &server
, strlen (server
.sun_path
) + 2)
651 fprintf (stderr
, "%s: ", progname
);
653 return INVALID_SOCKET
;
658 #endif /* ! NO_SOCKETS_IN_FILE_SYSTEM */
664 return set_tcp_socket ();
666 #ifndef NO_SOCKETS_IN_FILE_SYSTEM
667 return set_local_socket ();
670 server_file
= "server";
671 return set_tcp_socket ();
682 int i
, rl
, needlf
= 0;
684 char string
[BUFSIZ
+1];
688 /* Process options. */
689 decode_options (argc
, argv
);
691 if ((argc
- optind
< 1) && !eval
)
693 fprintf (stderr
, "%s: file name or argument required\n", progname
);
694 fprintf (stderr
, "Try `%s --help' for more information\n", progname
);
698 if ((s
= set_socket ()) == INVALID_SOCKET
)
702 cwd
= getcwd (string
, sizeof string
);
704 cwd
= getwd (string
);
708 /* getwd puts message in STRING if it fails. */
710 fprintf (stderr
, "%s: %s (%s)\n", progname
,
711 "Cannot get current working directory", strerror (errno
));
713 fprintf (stderr
, "%s: %s (%s)\n", progname
, string
, strerror (errno
));
719 SEND_STRING ("-nowait ");
722 SEND_STRING ("-eval ");
726 SEND_STRING ("-display ");
727 SEND_QUOTED (display
);
731 if ((argc
- optind
> 0))
733 for (i
= optind
; i
< argc
; i
++)
736 ; /* Don't prepend any cwd or anything like that. */
737 else if (*argv
[i
] == '+')
739 char *p
= argv
[i
] + 1;
740 while (isdigit ((unsigned char) *p
) || *p
== ':') p
++;
748 else if (*argv
[i
] != '/')
750 else if ((*argv
[i
] != '/')
751 /* Absolute paths can also start with backslash
753 && (*argv
[i
] != '\\')
754 && (!islower (tolower (*argv
[i
]))
755 || (argv
[i
][1] != ':')))
762 SEND_QUOTED (argv
[i
]);
768 while (fgets (string
, BUFSIZ
, stdin
))
770 SEND_QUOTED (string
);
777 /* Maybe wait for an answer. */
782 printf ("Waiting for Emacs...");
787 /* Now, wait for an answer and print any messages. */
788 while ((rl
= recv (s
, string
, BUFSIZ
, 0)) > 0)
793 printf ("%s", string
);
794 needlf
= string
[0] == '\0' ? needlf
: string
[strlen (string
) - 1] != '\n';
806 #endif /* HAVE_SOCKETS && HAVE_INET_SOCKETS */
808 #ifndef HAVE_STRERROR
813 extern char *sys_errlist
[];
816 if (errnum
>= 0 && errnum
< sys_nerr
)
817 return sys_errlist
[errnum
];
818 return (char *) "Unknown error";
821 #endif /* ! HAVE_STRERROR */
823 /* arch-tag: f39bb9c4-73eb-477e-896d-50832e2ca9a7
824 (do not change this comment) */
826 /* emacsclient.c ends here */