A few more bugfixes and new features.
[bpt/emacs.git] / lib-src / emacsclient.c
1 /* Client process that communicates with GNU Emacs acting as server.
2 Copyright (C) 1986, 1987, 1994, 1999, 2000, 2001, 2003
3 Free Software Foundation, Inc.
4
5 This file is part of GNU Emacs.
6
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)
10 any later version.
11
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.
16
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., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
21
22
23 #define NO_SHORTNAMES
24
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28
29 #undef signal
30
31 #include <ctype.h>
32 #include <stdio.h>
33 #include <getopt.h>
34 #ifdef HAVE_UNISTD_H
35 #include <unistd.h>
36 #endif
37
38 #ifdef VMS
39 # include "vms-pwd.h"
40 #else
41 # include <pwd.h>
42 #endif /* not VMS */
43
44
45 /****************************************/
46
47 #include <errno.h>
48 #include <signal.h>
49
50 #ifndef INCLUDED_FCNTL
51 #define INCLUDED_FCNTL
52 #include <fcntl.h>
53 #endif
54
55 #ifdef HAVE_TERMIOS
56 #ifndef NO_TERMIO
57 #include <termio.h>
58 #endif
59 #include <termios.h>
60 #endif /* not HAVE_TERMIOS */
61
62 #ifdef __GNU_LIBRARY__
63 #include <sys/ioctl.h>
64 #include <termios.h>
65 #endif
66
67 #if (defined (POSIX) || defined (NEED_UNISTD_H)) && defined (HAVE_UNISTD_H)
68 #include <unistd.h>
69 #endif
70
71
72 \f
73 /* Try to establish the correct character to disable terminal functions
74 in a system-independent manner. Note that USG (at least) define
75 _POSIX_VDISABLE as 0! */
76
77 #ifdef _POSIX_VDISABLE
78 #define CDISABLE _POSIX_VDISABLE
79 #else /* not _POSIX_VDISABLE */
80 #ifdef CDEL
81 #undef CDISABLE
82 #define CDISABLE CDEL
83 #else /* not CDEL */
84 #define CDISABLE 255
85 #endif /* not CDEL */
86 #endif /* not _POSIX_VDISABLE */
87 \f
88
89
90 /****************************************/
91
92 char *getenv (), *getwd ();
93 char *getcwd ();
94
95 /* This is defined with -D from the compilation command,
96 which extracts it from ../lisp/version.el. */
97
98 #ifndef VERSION
99 #define VERSION "unspecified"
100 #endif
101 \f
102 /* Name used to invoke this program. */
103 char *progname;
104
105 /* The first argument to main. */
106 int main_argc;
107
108 /* The second argument to main. */
109 char **main_argv;
110
111 /* Nonzero means don't wait for a response from Emacs. --no-wait. */
112 int nowait = 0;
113
114 /* Nonzero means args are expressions to be evaluated. --eval. */
115 int eval = 0;
116
117 /* The display on which Emacs should work. --display. */
118 char *display = NULL;
119
120 /* Nonzero means open a new Emacs frame on the current terminal. */
121 int frame = 0;
122
123 /* If non-NULL, the name of an editor to fallback to if the server
124 is not running. --alternate-editor. */
125 const char * alternate_editor = NULL;
126
127 /* If non-NULL, the filename of the UNIX socket. */
128 char *socket_name = NULL;
129
130 void print_help_and_exit ();
131
132 struct option longopts[] =
133 {
134 { "no-wait", no_argument, NULL, 'n' },
135 { "eval", no_argument, NULL, 'e' },
136 { "help", no_argument, NULL, 'H' },
137 { "version", no_argument, NULL, 'V' },
138 { "frame", no_argument, NULL, 'f' },
139 { "alternate-editor", required_argument, NULL, 'a' },
140 { "socket-name", required_argument, NULL, 's' },
141 { "display", required_argument, NULL, 'd' },
142 { 0, 0, 0, 0 }
143 };
144
145 /* Decode the options from argv and argc.
146 The global variable `optind' will say how many arguments we used up. */
147
148 void
149 decode_options (argc, argv)
150 int argc;
151 char **argv;
152 {
153 while (1)
154 {
155 int opt = getopt_long (argc, argv,
156 "VHnea:s:d:t", longopts, 0);
157
158 if (opt == EOF)
159 break;
160
161 alternate_editor = getenv ("ALTERNATE_EDITOR");
162
163 switch (opt)
164 {
165 case 0:
166 /* If getopt returns 0, then it has already processed a
167 long-named option. We should do nothing. */
168 break;
169
170 case 'a':
171 alternate_editor = optarg;
172 break;
173
174 case 's':
175 socket_name = optarg;
176 break;
177
178 case 'd':
179 display = optarg;
180 break;
181
182 case 'n':
183 nowait = 1;
184 break;
185
186 case 'e':
187 eval = 1;
188 break;
189
190 case 'V':
191 printf ("emacsclient %s\n", VERSION);
192 exit (0);
193 break;
194
195 case 't':
196 frame = 1;
197 break;
198
199 case 'H':
200 print_help_and_exit ();
201 break;
202
203 default:
204 fprintf (stderr, "Try `%s --help' for more information\n", progname);
205 exit (1);
206 break;
207 }
208 }
209
210 if (frame) {
211 nowait = 0;
212 display = 0;
213 }
214
215 }
216
217 void
218 print_help_and_exit ()
219 {
220 printf (
221 "Usage: %s [OPTIONS] FILE...\n\
222 Tell the Emacs server to visit the specified files.\n\
223 Every FILE can be either just a FILENAME or [+LINE[:COLUMN]] FILENAME.\n\
224 \n\
225 The following OPTIONS are accepted:\n\
226 -V, --version Just print a version info and return\n\
227 -H, --help Print this usage information message\n\
228 -t, --tty Open a new Emacs frame on the current terminal\n\
229 -n, --no-wait Don't wait for the server to return\n\
230 -e, --eval Evaluate the FILE arguments as ELisp expressions\n\
231 -d, --display=DISPLAY Visit the file in the given display\n\
232 -s, --socket-name=FILENAME\n\
233 Set the filename of the UNIX socket for communication\n\
234 -a, --alternate-editor=EDITOR\n\
235 Editor to fallback to if the server is not running\n\
236 \n\
237 Report bugs to bug-gnu-emacs@gnu.org.\n", progname);
238 exit (0);
239 }
240
241 /* In NAME, insert a & before each &, each space, each newline, and
242 any initial -. Change spaces to underscores, too, so that the
243 return value never contains a space. */
244
245 void
246 quote_file_name (name, stream)
247 char *name;
248 FILE *stream;
249 {
250 char *copy = (char *) malloc (strlen (name) * 2 + 1);
251 char *p, *q;
252
253 p = name;
254 q = copy;
255 while (*p)
256 {
257 if (*p == ' ')
258 {
259 *q++ = '&';
260 *q++ = '_';
261 p++;
262 }
263 else if (*p == '\n')
264 {
265 *q++ = '&';
266 *q++ = 'n';
267 p++;
268 }
269 else
270 {
271 if (*p == '&' || (*p == '-' && p == name))
272 *q++ = '&';
273 *q++ = *p++;
274 }
275 }
276 *q++ = 0;
277
278 fprintf (stream, copy);
279
280 free (copy);
281 }
282
283 /* Like malloc but get fatal error if memory is exhausted. */
284
285 long *
286 xmalloc (size)
287 unsigned int size;
288 {
289 long *result = (long *) malloc (size);
290 if (result == NULL)
291 {
292 perror ("malloc");
293 exit (1);
294 }
295 return result;
296 }
297 \f
298 /*
299 Try to run a different command, or --if no alternate editor is
300 defined-- exit with an errorcode.
301 */
302 void
303 fail (void)
304 {
305 if (alternate_editor)
306 {
307 int i = optind - 1;
308 execvp (alternate_editor, main_argv + i);
309 return;
310 }
311 else
312 {
313 exit (1);
314 }
315 }
316
317 \f
318 #ifdef HAVE_TERMIOS
319
320 /* Adapted from emacs_get_tty() in sysdep.c. */
321 int
322 ec_get_tty (int fd, struct termios *settings)
323 {
324 bzero (settings, sizeof (struct termios));
325 if (tcgetattr (fd, settings) < 0)
326 return -1;
327 return 0;
328 }
329
330 /* Adapted from emacs_set_tty() in sysdep.c. */
331 int
332 ec_set_tty (int fd, struct termios *settings, int flushp)
333 {
334 /* Set the primary parameters - baud rate, character size, etcetera. */
335
336 int i;
337 /* We have those nifty POSIX tcmumbleattr functions.
338 William J. Smith <wjs@wiis.wang.com> writes:
339 "POSIX 1003.1 defines tcsetattr to return success if it was
340 able to perform any of the requested actions, even if some
341 of the requested actions could not be performed.
342 We must read settings back to ensure tty setup properly.
343 AIX requires this to keep tty from hanging occasionally." */
344 /* This make sure that we don't loop indefinitely in here. */
345 for (i = 0 ; i < 10 ; i++)
346 if (tcsetattr (fd, flushp ? TCSAFLUSH : TCSADRAIN, settings) < 0)
347 {
348 if (errno == EINTR)
349 continue;
350 else
351 return -1;
352 }
353 else
354 {
355 struct termios new;
356
357 bzero (&new, sizeof (new));
358 /* Get the current settings, and see if they're what we asked for. */
359 tcgetattr (fd, &new);
360 /* We cannot use memcmp on the whole structure here because under
361 * aix386 the termios structure has some reserved field that may
362 * not be filled in.
363 */
364 if ( new.c_iflag == settings->c_iflag
365 && new.c_oflag == settings->c_oflag
366 && new.c_cflag == settings->c_cflag
367 && new.c_lflag == settings->c_lflag
368 && memcmp (new.c_cc, settings->c_cc, NCCS) == 0)
369 break;
370 else
371 continue;
372 }
373 return 0;
374 }
375
376 int master;
377 char *pty_name;
378
379 struct termios old_tty;
380 struct termios tty;
381 int old_tty_valid;
382
383 int tty_erase_char;
384 int quit_char = 'g' & 037;
385 int flow_control = 0;
386 int meta_key = 0;
387 char _sobuf[BUFSIZ];
388 int emacs_pid;
389
390 /* Adapted from init_sys_modes() in sysdep.c. */
391 int
392 init_tty ()
393 {
394 if (! isatty (0))
395 {
396 fprintf (stderr, "%s: Input is not a terminal", "init_tty");
397 return 0;
398 }
399
400 ec_get_tty (0, &old_tty);
401 old_tty_valid = 1;
402 tty = old_tty;
403
404 tty_erase_char = old_tty.c_cc[VERASE];
405
406 tty.c_iflag |= (IGNBRK); /* Ignore break condition */
407 tty.c_iflag &= ~ICRNL; /* Disable map of CR to NL on input */
408 #ifdef INLCR
409 tty.c_iflag &= ~INLCR; /* Disable map of NL to CR on input */
410 #endif
411 #ifdef ISTRIP
412 tty.c_iflag &= ~ISTRIP; /* don't strip 8th bit on input */
413 #endif
414 tty.c_lflag &= ~ECHO; /* Disable echo */
415 tty.c_lflag &= ~ICANON; /* Disable erase/kill processing */
416 #ifdef IEXTEN
417 tty.c_lflag &= ~IEXTEN; /* Disable other editing characters. */
418 #endif
419 tty.c_lflag |= ISIG; /* Enable signals */
420 if (flow_control)
421 {
422 tty.c_iflag |= IXON; /* Enable start/stop output control */
423 #ifdef IXANY
424 tty.c_iflag &= ~IXANY;
425 #endif /* IXANY */
426 }
427 else
428 tty.c_iflag &= ~IXON; /* Disable start/stop output control */
429 tty.c_oflag &= ~ONLCR; /* Disable map of NL to CR-NL
430 on output */
431 tty.c_oflag &= ~TAB3; /* Disable tab expansion */
432 #ifdef CS8
433 if (meta_key)
434 {
435 tty.c_cflag |= CS8; /* allow 8th bit on input */
436 tty.c_cflag &= ~PARENB; /* Don't check parity */
437 }
438 #endif
439 tty.c_cc[VINTR] = quit_char; /* C-g (usually) gives SIGINT */
440 /* Set up C-g for both SIGQUIT and SIGINT.
441 We don't know which we will get, but we handle both alike
442 so which one it really gives us does not matter. */
443 tty.c_cc[VQUIT] = quit_char;
444 tty.c_cc[VMIN] = 1; /* Input should wait for at least 1 char */
445 tty.c_cc[VTIME] = 0; /* no matter how long that takes. */
446 #ifdef VSWTCH
447 tty.c_cc[VSWTCH] = CDISABLE; /* Turn off shell layering use of C-z */
448 #endif
449
450 #ifdef VSUSP
451 tty.c_cc[VSUSP] = CDISABLE; /* Turn off mips handling of C-z. */
452 #endif /* VSUSP */
453 #ifdef V_DSUSP
454 tty.c_cc[V_DSUSP] = CDISABLE; /* Turn off mips handling of C-y. */
455 #endif /* V_DSUSP */
456 #ifdef VDSUSP /* Some systems have VDSUSP, some have V_DSUSP. */
457 tty.c_cc[VDSUSP] = CDISABLE;
458 #endif /* VDSUSP */
459 #ifdef VLNEXT
460 tty.c_cc[VLNEXT] = CDISABLE;
461 #endif /* VLNEXT */
462 #ifdef VREPRINT
463 tty.c_cc[VREPRINT] = CDISABLE;
464 #endif /* VREPRINT */
465 #ifdef VWERASE
466 tty.c_cc[VWERASE] = CDISABLE;
467 #endif /* VWERASE */
468 #ifdef VDISCARD
469 tty.c_cc[VDISCARD] = CDISABLE;
470 #endif /* VDISCARD */
471
472 if (flow_control)
473 {
474 #ifdef VSTART
475 tty.c_cc[VSTART] = '\021';
476 #endif /* VSTART */
477 #ifdef VSTOP
478 tty.c_cc[VSTOP] = '\023';
479 #endif /* VSTOP */
480 }
481 else
482 {
483 #ifdef VSTART
484 tty.c_cc[VSTART] = CDISABLE;
485 #endif /* VSTART */
486 #ifdef VSTOP
487 tty.c_cc[VSTOP] = CDISABLE;
488 #endif /* VSTOP */
489 }
490
491 #ifdef SET_LINE_DISCIPLINE
492 /* Need to explicitly request TERMIODISC line discipline or
493 Ultrix's termios does not work correctly. */
494 tty.c_line = SET_LINE_DISCIPLINE;
495 #endif
496
497 #ifdef AIX
498 #ifndef IBMR2AIX
499 /* AIX enhanced edit loses NULs, so disable it. */
500 tty.c_line = 0;
501 tty.c_iflag &= ~ASCEDIT;
502 #else
503 tty.c_cc[VSTRT] = 255;
504 tty.c_cc[VSTOP] = 255;
505 tty.c_cc[VSUSP] = 255;
506 tty.c_cc[VDSUSP] = 255;
507 #endif /* IBMR2AIX */
508 if (flow_control)
509 {
510 #ifdef VSTART
511 tty.c_cc[VSTART] = '\021';
512 #endif /* VSTART */
513 #ifdef VSTOP
514 tty.c_cc[VSTOP] = '\023';
515 #endif /* VSTOP */
516 }
517 /* Also, PTY overloads NUL and BREAK.
518 don't ignore break, but don't signal either, so it looks like NUL.
519 This really serves a purpose only if running in an XTERM window
520 or via TELNET or the like, but does no harm elsewhere. */
521 tty.c_iflag &= ~IGNBRK;
522 tty.c_iflag &= ~BRKINT;
523 #endif /* AIX */
524
525 ec_set_tty (0, &tty, 0);
526
527 /* This code added to insure that, if flow-control is not to be used,
528 we have an unlocked terminal at the start. */
529
530 #ifdef TCXONC
531 if (!flow_control) ioctl (0, TCXONC, 1);
532 #endif
533 #ifndef APOLLO
534 #ifdef TIOCSTART
535 if (!flow_control) ioctl (0, TIOCSTART, 0);
536 #endif
537 #endif
538
539 #if defined (HAVE_TERMIOS) || defined (HPUX9)
540 #ifdef TCOON
541 if (!flow_control) tcflow (0, TCOON);
542 #endif
543 #endif
544
545 #ifdef _IOFBF
546 /* This symbol is defined on recent USG systems.
547 Someone says without this call USG won't really buffer the file
548 even with a call to setbuf. */
549 setvbuf (stdout, (char *) _sobuf, _IOFBF, sizeof _sobuf);
550 #else
551 setbuf (stdout, (char *) _sobuf);
552 #endif
553
554 return 1;
555 }
556
557 void
558 window_change ()
559 {
560 int width = 0, height = 0;
561
562 #ifdef TIOCGWINSZ
563 {
564 /* BSD-style. */
565 struct winsize size;
566
567 if (ioctl (0, TIOCGWINSZ, &size) == -1)
568 width = height = 0;
569 else
570 {
571 width = size.ws_col;
572 height = size.ws_row;
573 }
574 }
575 #else
576 #ifdef TIOCGSIZE
577 {
578 /* SunOS - style. */
579 struct ttysize size;
580
581 if (ioctl (0, TIOCGSIZE, &size) == -1)
582 width = height = 0;
583 else
584 {
585 width = size.ts_cols;
586 height = size.ts_lines;
587 }
588 }
589 #endif /* not SunOS-style */
590 #endif /* not BSD-style */
591
592 #ifdef TIOCSWINSZ
593 {
594 /* BSD-style. */
595 struct winsize size;
596 size.ws_row = height;
597 size.ws_col = width;
598
599 ioctl (master, TIOCSWINSZ, &size);
600 }
601 #else
602 #ifdef TIOCSSIZE
603 {
604 /* SunOS - style. */
605 struct ttysize size;
606 size.ts_lines = height;
607 size.ts_cols = width;
608
609 ioctl (master, TIOCGSIZE, &size);
610 }
611 #endif /* not SunOS-style */
612 #endif /* not BSD-style */
613
614 if (emacs_pid && width && height)
615 kill (emacs_pid, SIGWINCH);
616 }
617
618 int in_conversation = 0;
619 int quit_conversation = 0;
620
621 SIGTYPE
622 hang_up_signal (int signalnum)
623 {
624 int old_errno = errno;
625
626 if (! in_conversation)
627 return;
628
629 quit_conversation = 1;
630
631 errno = old_errno;
632 }
633
634 SIGTYPE
635 window_change_signal (int signalnum)
636 {
637 int old_errno = errno;
638
639 if (! in_conversation)
640 goto end;
641
642 window_change();
643
644 end:
645 signal (SIGWINCH, window_change_signal);
646 errno = old_errno;
647 }
648
649 SIGTYPE
650 interrupt_signal (int signalnum)
651 {
652 int old_errno = errno;
653
654 /* Forward it to Emacs. */
655 if (emacs_pid)
656 kill (emacs_pid, SIGINT);
657
658 errno = old_errno;
659 }
660
661 int
662 init_signals ()
663 {
664 /* Set up signal handlers. */
665 signal (SIGWINCH, window_change_signal);
666 signal (SIGHUP, hang_up_signal);
667 signal (SIGINT, interrupt_signal);
668 return 1;
669 }
670
671
672
673 /* Adapted from reset_sys_modes in sysdep.c. */
674 int
675 reset_tty ()
676 {
677 fflush (stdout);
678 #ifdef BSD_SYSTEM
679 #ifndef BSD4_1
680 /* Avoid possible loss of output when changing terminal modes. */
681 fsync (fileno (stdout));
682 #endif
683 #endif
684
685 #ifdef F_SETFL
686 #ifdef O_NDELAY
687 fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~O_NDELAY);
688 #endif
689 #endif /* F_SETFL */
690
691 if (old_tty_valid)
692 while (ec_set_tty (0, &old_tty, 0) < 0 && errno == EINTR)
693 ;
694
695 return 1;
696 }
697
698
699 int
700 init_pty ()
701 {
702 master = getpt ();
703 if (master < 0)
704 return 0;
705
706 if (grantpt (master) < 0 || unlockpt (master) < 0)
707 goto close_master;
708 pty_name = strdup (ptsname (master));
709 if (! pty_name)
710 goto close_master;
711
712 /* Propagate window size. */
713 window_change ();
714
715 return 1;
716
717 close_master:
718 close (master);
719 return 0;
720 }
721
722 int
723 copy_from_to (int in, int out)
724 {
725 static char buf[BUFSIZ];
726 int nread = read (in, &buf, BUFSIZ);
727 if (nread == 0)
728 return 1; /* EOF */
729 else if (nread < 0 && errno != EAGAIN)
730 return 0;
731 else if (nread > 0)
732 {
733 int r = 0;
734 int written = 0;
735
736 do {
737 r = write (out, &buf, nread);
738 } while ((r < 0 && errno == EINTR)
739 || (r > 0 && (written += r) && written != nread));
740
741 if (r < 0)
742 return 0;
743 }
744 return 1;
745 }
746
747 int
748 pty_conversation (FILE *in)
749 {
750 char *str;
751 char string[BUFSIZ];
752 fd_set set, rset;
753 int res;
754
755 FD_ZERO (&set);
756 FD_SET (master, &set);
757 FD_SET (1, &set);
758 FD_SET (fileno (in), &set);
759
760 in_conversation = 1;
761
762 while (! quit_conversation) {
763 rset = set;
764 res = select (FD_SETSIZE, &rset, NULL, NULL, NULL);
765 if (res < 0 && errno != EINTR)
766 {
767 reset_tty ();
768 fprintf (stderr, "%s: ", progname);
769 perror ("select");
770 return 0; /* Error */
771 }
772 else if (res > 0)
773 {
774 if (FD_ISSET (master, &rset))
775 {
776 /* Copy Emacs output to stdout. */
777 if (! copy_from_to (master, 0))
778 {
779 FD_CLR (master, &set);
780 }
781 }
782 if (FD_ISSET (1, &rset))
783 {
784 /* Forward user input to Emacs. */
785 if (! copy_from_to (1, master))
786 {
787 FD_CLR (master, &set);
788 }
789 }
790 if (FD_ISSET (fileno (in), &rset))
791 {
792 do {
793 res = read (fileno (in), string, BUFSIZ-1);
794 } while (res == EINTR);
795 if (res < 0)
796 {
797 reset_tty ();
798 fprintf (stderr, "%s: ", progname);
799 perror ("read");
800 return 0;
801 }
802 if (!res)
803 {
804 return 1;
805 }
806
807 string[res] = 0;
808 if (string[res-1] == '\n')
809 string[res-1] = 0;
810
811 if (! emacs_pid)
812 {
813 /* Get the pid of the Emacs process.
814 XXX Is there some nifty libc/kernel feature for doing this?
815 */
816 if (! string[0])
817 {
818 reset_tty ();
819 fprintf (stderr, "%s: could not get Emacs process id\n"
820 "Maybe this Emacs does not support multiple terminals.\n", progname);
821 return 0;
822 }
823 emacs_pid = strtol (string, NULL, 10);
824 }
825
826 if (! emacs_pid) /* emacs_pid should be set above */
827 {
828 reset_tty ();
829 fprintf (stderr, "%s: %s\n", progname, string);
830 return 0;
831 }
832 }
833 }
834 }
835 return 1;
836 }
837
838 #endif /* HAVE_TERMIOS */
839
840 \f
841 #if !defined (HAVE_SOCKETS) || defined (NO_SOCKETS_IN_FILE_SYSTEM)
842
843 int
844 main (argc, argv)
845 int argc;
846 char **argv;
847 {
848 fprintf (stderr, "%s: Sorry, the Emacs server is supported only\n",
849 argv[0]);
850 fprintf (stderr, "on systems with Berkeley sockets.\n");
851
852 fail ();
853 }
854
855 #else /* HAVE_SOCKETS */
856
857 #include <sys/types.h>
858 #include <sys/socket.h>
859 #include <sys/un.h>
860 #include <sys/stat.h>
861 #include <errno.h>
862
863 extern char *strerror ();
864 extern int errno;
865
866 /* Three possibilities:
867 2 - can't be `stat'ed (sets errno)
868 1 - isn't owned by us
869 0 - success: none of the above */
870
871 static int
872 socket_status (socket_name)
873 char *socket_name;
874 {
875 struct stat statbfr;
876
877 if (stat (socket_name, &statbfr) == -1)
878 return 2;
879
880 if (statbfr.st_uid != geteuid ())
881 return 1;
882
883 return 0;
884 }
885
886 int
887 main (argc, argv)
888 int argc;
889 char **argv;
890 {
891 char *system_name;
892 int system_name_length;
893 int s, i, needlf = 0;
894 FILE *out, *in;
895 struct sockaddr_un server;
896 char *cwd, *str;
897 char string[BUFSIZ];
898
899 main_argc = argc;
900 main_argv = argv;
901 progname = argv[0];
902
903 /* Process options. */
904 decode_options (argc, argv);
905
906 if ((argc - optind < 1) && !eval && !frame)
907 {
908 fprintf (stderr, "%s: file name or argument required\n", progname);
909 fprintf (stderr, "Try `%s --help' for more information\n", progname);
910 exit (1);
911 }
912
913 /*
914 * Open up an AF_UNIX socket in this person's home directory
915 */
916
917 if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
918 {
919 fprintf (stderr, "%s: ", argv[0]);
920 perror ("socket");
921 fail ();
922 }
923
924 server.sun_family = AF_UNIX;
925
926 {
927 char *dot;
928 system_name_length = 32;
929
930 while (1)
931 {
932 system_name = (char *) xmalloc (system_name_length + 1);
933
934 /* system_name must be null-terminated string. */
935 system_name[system_name_length] = '\0';
936
937 if (gethostname (system_name, system_name_length) == 0)
938 break;
939
940 free (system_name);
941 system_name_length *= 2;
942 }
943
944 /* We always use the non-dotted host name, for simplicity. */
945 dot = index (system_name, '.');
946 if (dot)
947 *dot = '\0';
948 }
949
950 {
951 int sock_status = 0;
952 int oerrno = 0;
953
954 if (! socket_name)
955 {
956 socket_name = alloca (system_name_length + 100);
957 sprintf (socket_name, "/tmp/emacs%d-%s/server",
958 (int) geteuid (), system_name);
959 }
960
961 if (strlen (socket_name) < sizeof (server.sun_path))
962 strcpy (server.sun_path, socket_name);
963 else
964 {
965 fprintf (stderr, "%s: socket-name %s too long",
966 argv[0], socket_name);
967 fail ();
968 }
969
970 /* See if the socket exists, and if it's owned by us. */
971 sock_status = socket_status (server.sun_path);
972 oerrno = errno;
973 if (sock_status)
974 {
975 /* Failing that, see if LOGNAME or USER exist and differ from
976 our euid. If so, look for a socket based on the UID
977 associated with the name. This is reminiscent of the logic
978 that init_editfns uses to set the global Vuser_full_name. */
979
980 char *user_name = (char *) getenv ("LOGNAME");
981 if (!user_name)
982 user_name = (char *) getenv ("USER");
983
984 if (user_name)
985 {
986 struct passwd *pw = getpwnam (user_name);
987 if (pw && (pw->pw_uid != geteuid ()))
988 {
989 /* We're running under su, apparently. */
990 sprintf (server.sun_path, "/tmp/esrv%d-%s",
991 (int) pw->pw_uid, system_name);
992 sock_status = socket_status (server.sun_path);
993 oerrno = errno;
994 }
995 }
996 }
997
998 switch (sock_status)
999 {
1000 case 1:
1001 /* There's a socket, but it isn't owned by us. This is OK if
1002 we are root. */
1003 if (0 != geteuid ())
1004 {
1005 fprintf (stderr, "%s: Invalid socket owner\n", argv[0]);
1006 fail ();
1007 }
1008 break;
1009
1010 case 2:
1011 /* `stat' failed */
1012 if (errno == ENOENT)
1013 fprintf (stderr,
1014 "%s: Can't find socket; have you started the server?\n\
1015 To start the server in Emacs, type \"M-x server-start\".\n",
1016 argv[0]);
1017 else
1018 fprintf (stderr, "%s: Can't stat %s: %s\n",
1019 argv[0], server.sun_path, strerror (oerrno));
1020 fail ();
1021 break;
1022 }
1023 }
1024
1025 if (connect (s, (struct sockaddr *) &server, strlen (server.sun_path) + 2)
1026 < 0)
1027 {
1028 fprintf (stderr, "%s: ", argv[0]);
1029 perror ("connect");
1030 fail ();
1031 }
1032
1033 /* We use the stream OUT to send our command to the server. */
1034 if ((out = fdopen (s, "r+")) == NULL)
1035 {
1036 fprintf (stderr, "%s: ", argv[0]);
1037 perror ("fdopen");
1038 fail ();
1039 }
1040
1041 /* We use the stream IN to read the response.
1042 We used to use just one stream for both output and input
1043 on the socket, but reversing direction works nonportably:
1044 on some systems, the output appears as the first input;
1045 on other systems it does not. */
1046 if ((in = fdopen (s, "r+")) == NULL)
1047 {
1048 fprintf (stderr, "%s: ", argv[0]);
1049 perror ("fdopen");
1050 fail ();
1051 }
1052
1053 #ifdef HAVE_GETCWD
1054 cwd = getcwd (string, sizeof string);
1055 #else
1056 cwd = getwd (string);
1057 #endif
1058 if (cwd == 0)
1059 {
1060 /* getwd puts message in STRING if it fails. */
1061
1062 #ifdef HAVE_GETCWD
1063 fprintf (stderr, "%s: %s (%s)\n", argv[0],
1064 "Cannot get current working directory", strerror (errno));
1065 #else
1066 fprintf (stderr, "%s: %s (%s)\n", argv[0], string, strerror (errno));
1067 #endif
1068 fail ();
1069 }
1070
1071 if (nowait)
1072 fprintf (out, "-nowait ");
1073
1074 if (eval)
1075 fprintf (out, "-eval ");
1076
1077 if (display)
1078 {
1079 fprintf (out, "-display ");
1080 quote_file_name (display, out);
1081 fprintf (out, " ");
1082 }
1083
1084 if (frame)
1085 {
1086 if (! init_signals ())
1087 {
1088 fprintf (stderr, "%s: ", argv[0]);
1089 perror ("fdopen");
1090 fail ();
1091 }
1092
1093 if (! init_tty ())
1094 {
1095 reset_tty ();
1096 fprintf (stderr, "%s: ", argv[0]);
1097 perror ("fdopen");
1098 fail ();
1099 }
1100
1101 if (! init_pty ())
1102 {
1103 reset_tty ();
1104 fprintf (stderr, "%s: ", argv[0]);
1105 perror ("fdopen");
1106 fail ();
1107 }
1108
1109 fprintf (out, "-tty ");
1110 quote_file_name (pty_name, out);
1111 fprintf (out, " ");
1112 quote_file_name (getenv("TERM"), out);
1113 fprintf (out, " ");
1114 }
1115
1116 if ((argc - optind > 0))
1117 {
1118 for (i = optind; i < argc; i++)
1119 {
1120 if (eval)
1121 ; /* Don't prepend any cwd or anything like that. */
1122 else if (*argv[i] == '+')
1123 {
1124 char *p = argv[i] + 1;
1125 while (isdigit ((unsigned char) *p) || *p == ':') p++;
1126 if (*p != 0)
1127 {
1128 quote_file_name (cwd, out);
1129 fprintf (out, "/");
1130 }
1131 }
1132 else if (*argv[i] != '/')
1133 {
1134 quote_file_name (cwd, out);
1135 fprintf (out, "/");
1136 }
1137
1138 quote_file_name (argv[i], out);
1139 fprintf (out, " ");
1140 }
1141 }
1142 else
1143 {
1144 if (!frame)
1145 {
1146 while ((str = fgets (string, BUFSIZ, stdin)))
1147 {
1148 quote_file_name (str, out);
1149 }
1150 fprintf (out, " ");
1151 }
1152 }
1153
1154 fprintf (out, "\n");
1155 fflush (out);
1156
1157 /* Maybe wait for an answer. */
1158 if (nowait)
1159 {
1160 reset_tty ();
1161 return 0;
1162 }
1163
1164 if (frame)
1165 {
1166 if (! pty_conversation (out))
1167 {
1168 reset_tty ();
1169 fail ();
1170 }
1171 reset_tty ();
1172 return 0;
1173 }
1174
1175 if (!eval)
1176 {
1177 printf ("Waiting for Emacs...");
1178 needlf = 2;
1179 }
1180 fflush (stdout);
1181
1182 /* Now, wait for an answer and print any messages. */
1183 while ((str = fgets (string, BUFSIZ, in)))
1184 {
1185 if (needlf == 2)
1186 printf ("\n");
1187 printf ("%s", str);
1188 needlf = str[0] == '\0' ? needlf : str[strlen (str) - 1] != '\n';
1189 }
1190
1191 if (needlf)
1192 printf ("\n");
1193 fflush (stdout);
1194
1195 reset_tty ();
1196 return 0;
1197 }
1198
1199 #endif /* HAVE_SOCKETS */
1200 \f
1201 #ifndef HAVE_STRERROR
1202 char *
1203 strerror (errnum)
1204 int errnum;
1205 {
1206 extern char *sys_errlist[];
1207 extern int sys_nerr;
1208
1209 if (errnum >= 0 && errnum < sys_nerr)
1210 return sys_errlist[errnum];
1211 return (char *) "Unknown error";
1212 }
1213
1214 #endif /* ! HAVE_STRERROR */
1215
1216 /* arch-tag: f39bb9c4-73eb-477e-896d-50832e2ca9a7
1217 (do not change this comment) */