1 /* Client process that communicates with GNU Emacs acting as server.
2 Copyright (C) 1986, 1987, 1994, 1999, 2000 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
23 #include <../src/config.h>
38 char *getenv (), *getwd ();
41 /* This is defined with -D from the compilation command,
42 which extracts it from ../lisp/version.el. */
45 #define VERSION "unspecified"
48 /* Name used to invoke this program. */
51 /* Nonzero means don't wait for a response from Emacs. --no-wait. */
54 void print_help_and_exit ();
56 struct option longopts
[] =
58 { "no-wait", no_argument
, NULL
, 'n' },
59 { "help", no_argument
, NULL
, 'H' },
60 { "version", no_argument
, NULL
, 'V' },
61 { "alternate-editor",required_argument
, NULL
, 'a' },
66 const char * alternate_editor
= NULL
;
68 /* Decode the options from argv and argc.
69 The global variable `optind' will say how many arguments we used up. */
72 decode_options (argc
, argv
)
78 int opt
= getopt_long (argc
, argv
,
79 "VHna:", longopts
, 0);
84 alternate_editor
= getenv ("ALTERNATE_EDITOR");
89 /* If getopt returns 0, then it has already processed a
90 long-named option. We should do nothing. */
94 alternate_editor
= optarg
;
102 fprintf (stderr
, "emacsclient %s\n", VERSION
);
108 print_help_and_exit ();
114 print_help_and_exit ()
117 "Usage: %s [-a ALTERNATE-EDITOR] [-n] [--no-wait] [+LINENUMBER] FILENAME\n",
123 "Report bugs to bug-gnu-emacs@gnu.org.\n");
127 /* Return a copy of NAME, inserting a &
128 before each &, each space, and any initial -.
129 Change spaces to underscores, too, so that the
130 return value never contains a space. */
133 quote_file_name (name
)
136 char *copy
= (char *) malloc (strlen (name
) * 2 + 1);
151 if (*p
== '&' || (*p
== '-' && p
== name
))
162 /* Like malloc but get fatal error if memory is exhausted. */
168 long *result
= (long *) malloc (size
);
178 Try to run a different command, or --if no alternate editor is
179 defined-- exit with an errorcode.
185 if (alternate_editor
)
188 execvp (alternate_editor
, argv
+ i
);
199 #if !defined (HAVE_SOCKETS) && !defined (HAVE_SYSVIPC)
205 fprintf (stderr
, "%s: Sorry, the Emacs server is supported only\n",
207 fprintf (stderr
, "on systems with Berkeley sockets or System V IPC.\n");
212 #else /* HAVE_SOCKETS or HAVE_SYSVIPC */
214 #if defined (HAVE_SOCKETS) && ! defined (NO_SOCKETS_IN_FILE_SYSTEM)
215 /* BSD code is very different from SYSV IPC code */
217 #include <sys/types.h>
218 #include <sys/socket.h>
220 #include <sys/stat.h>
223 extern char *strerror ();
226 /* Three possibilities:
227 2 - can't be `stat'ed (sets errno)
228 1 - isn't owned by us
229 0 - success: none of the above */
232 socket_status (socket_name
)
237 if (stat (socket_name
, &statbfr
) == -1)
240 if (statbfr
.st_uid
!= geteuid ())
252 int system_name_length
;
255 struct sockaddr_un server
;
256 char *homedir
, *cwd
, *str
;
261 /* Process options. */
262 decode_options (argc
, argv
);
264 if (argc
- optind
< 1)
265 print_help_and_exit ();
268 * Open up an AF_UNIX socket in this person's home directory
271 if ((s
= socket (AF_UNIX
, SOCK_STREAM
, 0)) < 0)
273 fprintf (stderr
, "%s: ", argv
[0]);
278 server
.sun_family
= AF_UNIX
;
281 system_name_length
= 32;
285 system_name
= (char *) xmalloc (system_name_length
+ 1);
287 /* system_name must be null-terminated string. */
288 system_name
[system_name_length
] = '\0';
290 if (gethostname (system_name
, system_name_length
) == 0)
294 system_name_length
*= 2;
298 #ifndef SERVER_HOME_DIR
303 sprintf (server
.sun_path
, "/tmp/esrv%d-%s", geteuid (), system_name
);
305 /* See if the socket exists, and if it's owned by us. */
306 sock_status
= socket_status (server
.sun_path
);
309 /* Failing that, see if LOGNAME or USER exist and differ from
310 our euid. If so, look for a socket based on the UID
311 associated with the name. This is reminiscent of the logic
312 that init_editfns uses to set the global Vuser_full_name. */
314 char *user_name
= (char *) getenv ("LOGNAME");
316 user_name
= (char *) getenv ("USER");
320 struct passwd
*pw
= getpwnam (user_name
);
321 if (pw
&& (pw
->pw_uid
!= geteuid ()))
323 /* We're running under su, apparently. */
324 sprintf (server
.sun_path
, "/tmp/esrv%d-%s",
325 pw
->pw_uid
, system_name
);
326 sock_status
= socket_status (server
.sun_path
);
334 /* There's a socket, but it isn't owned by us. This is OK if
338 fprintf (stderr
, "%s: Invalid socket owner\n", argv
[0]);
347 "%s: can't find socket; have you started the server?\n",
350 fprintf (stderr
, "%s: can't stat %s: %s\n",
351 argv
[0], server
.sun_path
, strerror (errno
));
357 if ((homedir
= getenv ("HOME")) == NULL
)
359 fprintf (stderr
, "%s: No home directory\n", argv
[0]);
362 strcpy (server
.sun_path
, homedir
);
363 strcat (server
.sun_path
, "/.emacs-server-");
364 strcat (server
.sun_path
, system_name
);
367 if (connect (s
, (struct sockaddr
*) &server
, strlen (server
.sun_path
) + 2)
370 fprintf (stderr
, "%s: ", argv
[0]);
375 /* We use the stream OUT to send our command to the server. */
376 if ((out
= fdopen (s
, "r+")) == NULL
)
378 fprintf (stderr
, "%s: ", argv
[0]);
383 /* We use the stream IN to read the response.
384 We used to use just one stream for both output and input
385 on the socket, but reversing direction works nonportably:
386 on some systems, the output appears as the first input;
387 on other systems it does not. */
388 if ((in
= fdopen (s
, "r+")) == NULL
)
390 fprintf (stderr
, "%s: ", argv
[0]);
396 cwd
= getwd (string
);
398 cwd
= getcwd (string
, sizeof string
);
402 /* getwd puts message in STRING if it fails. */
403 fprintf (stderr
, "%s: %s (%s)\n", argv
[0],
407 "Cannot get current working directory",
414 fprintf (out
, "-nowait ");
416 for (i
= optind
; i
< argc
; i
++)
420 char *p
= argv
[i
] + 1;
421 while (*p
>= '0' && *p
<= '9') p
++;
423 fprintf (out
, "%s/", quote_file_name (cwd
));
425 else if (*argv
[i
] != '/')
426 fprintf (out
, "%s/", quote_file_name (cwd
));
428 fprintf (out
, "%s ", quote_file_name (argv
[i
]));
433 /* Maybe wait for an answer. */
437 printf ("Waiting for Emacs...");
440 /* Now, wait for an answer and print any messages. On some systems,
441 the first line we read will actually be the output we just sent.
442 We can't predict whether that will happen, so if it does, we
443 detect it by recognizing `Client: ' at the beginning. */
445 while (str
= fgets (string
, BUFSIZ
, in
))
451 #else /* This is the SYSV IPC section */
453 #include <sys/types.h>
456 #include <sys/utsname.h>
461 char *getwd (), *getcwd (), *getenv ();
462 struct utsname system_name
;
470 /* Size of text allocated in MSGP. */
471 int size_allocated
= BUFSIZ
;
472 /* Amount of text used in MSGP. */
475 = (struct msgbuf
*) malloc (sizeof (struct msgbuf
) + size_allocated
);
476 struct msqid_ds
* msg_st
;
477 char *homedir
, buf
[BUFSIZ
];
484 /* Process options. */
485 decode_options (argc
, argv
);
487 if (argc
- optind
< 1)
488 print_help_and_exit ();
491 * Create a message queue using ~/.emacs-server as the path for ftok
493 if ((homedir
= getenv ("HOME")) == NULL
)
495 fprintf (stderr
, "%s: No home directory\n", argv
[0]);
498 strcpy (buf
, homedir
);
499 #ifndef HAVE_LONG_FILE_NAMES
500 /* If file names are short, we can't fit the host name. */
501 strcat (buf
, "/.emacs-server");
503 strcat (buf
, "/.emacs-server-");
504 uname (&system_name
);
505 strcat (buf
, system_name
.nodename
);
508 key
= ftok (buf
, 1); /* unlikely to be anyone else using it */
509 s
= msgget (key
, 0600 | IPC_CREAT
);
512 fprintf (stderr
, "%s: ", argv
[0]);
517 /* Determine working dir, so we can prefix it to all the arguments. */
519 temp
= getwd (gwdirb
);
521 temp
= getcwd (gwdirb
, sizeof gwdirb
);
527 /* On some systems, cwd can look like `@machine/...';
528 ignore everything before the first slash in such a case. */
529 while (*cwd
&& *cwd
!= '/')
536 fprintf (stderr
, "%s: %s\n", argv
[0], cwd
);
538 fprintf (stderr
, "%s: Cannot get current working directory: %s\n",
539 argv
[0], strerror (errno
));
549 strcat (msgp
->mtext
, "-nowait ");
559 char *modified_arg
= argv
[0];
561 if (*modified_arg
== '+')
563 char *p
= modified_arg
+ 1;
564 while (*p
>= '0' && *p
<= '9') p
++;
568 else if (*modified_arg
!= '/')
571 modified_arg
= quote_file_name (modified_arg
);
574 /* Overestimate in case we have to quote something in CWD. */
575 used
+= 2 * strlen (cwd
);
576 used
+= strlen (modified_arg
) + 1;
577 while (used
+ 2 > size_allocated
)
580 msgp
= (struct msgbuf
*) realloc (msgp
,
581 (sizeof (struct msgbuf
)
586 strcat (msgp
->mtext
, quote_file_name (cwd
));
588 strcat (msgp
->mtext
, modified_arg
);
589 strcat (msgp
->mtext
, " ");
592 strcat (msgp
->mtext
, "\n");
593 #ifdef HPUX /* HPUX has a bug. */
594 if (strlen (msgp
->mtext
) >= 512)
596 fprintf (stderr
, "%s: args too long for msgsnd\n", progname
);
601 if (msgsnd (s
, msgp
, strlen (msgp
->mtext
)+1, 0) < 0)
603 fprintf (stderr
, "%s: ", progname
);
608 /* Maybe wait for an answer. */
612 printf ("Waiting for Emacs...");
615 msgrcv (s
, msgp
, BUFSIZ
, getpid (), 0); /* wait for anything back */
616 strcpy (buf
, msgp
->mtext
);
620 printf ("%s\n", buf
);
624 #endif /* HAVE_SYSVIPC */
626 #endif /* HAVE_SOCKETS or HAVE_SYSVIPC */
628 #ifndef HAVE_STRERROR
633 extern char *sys_errlist
[];
636 if (errnum
>= 0 && errnum
< sys_nerr
)
637 return sys_errlist
[errnum
];
638 return (char *) "Unknown error";
641 #endif /* ! HAVE_STRERROR */