MULTI_KBOARD support for ttys. Input-related bugfixes for X+tty sessions.
[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, int sigio)
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 if (sigio && emacs_pid)
745 kill (emacs_pid, SIGIO);
746 }
747 return 1;
748 }
749
750 int
751 pty_conversation (FILE *in)
752 {
753 char *str;
754 char string[BUFSIZ];
755 fd_set set, rset;
756 int res;
757
758 FD_ZERO (&set);
759 FD_SET (master, &set);
760 FD_SET (1, &set);
761 FD_SET (fileno (in), &set);
762
763 in_conversation = 1;
764
765 while (! quit_conversation) {
766 rset = set;
767 res = select (FD_SETSIZE, &rset, NULL, NULL, NULL);
768 if (res < 0 && errno != EINTR)
769 {
770 reset_tty ();
771 fprintf (stderr, "%s: ", progname);
772 perror ("select");
773 return 0; /* Error */
774 }
775 else if (res > 0)
776 {
777 if (FD_ISSET (master, &rset))
778 {
779 /* Copy Emacs output to stdout. */
780 if (! copy_from_to (master, 0, 0))
781 {
782 FD_CLR (master, &set);
783 }
784 }
785 if (FD_ISSET (1, &rset))
786 {
787 /* Forward user input to Emacs. */
788 if (! copy_from_to (1, master, 1))
789 {
790 FD_CLR (master, &set);
791 }
792 }
793 if (FD_ISSET (fileno (in), &rset))
794 {
795 do {
796 res = read (fileno (in), string, BUFSIZ-1);
797 } while (res < 0 && errno == EINTR);
798 if (res < 0)
799 {
800 reset_tty ();
801 fprintf (stderr, "%s: ", progname);
802 perror ("read");
803 return 0;
804 }
805 if (!res)
806 {
807 return 1;
808 }
809
810 string[res] = 0;
811 if (string[res-1] == '\n')
812 string[res-1] = 0;
813
814 if (! emacs_pid)
815 {
816 /* Get the pid of the Emacs process.
817 XXX Is there some nifty libc/kernel feature for doing this?
818 */
819 if (! string[0])
820 {
821 reset_tty ();
822 fprintf (stderr, "%s: could not get Emacs process id\n"
823 "Maybe this Emacs does not support multiple terminals.\n", progname);
824 return 0;
825 }
826 emacs_pid = strtol (string, NULL, 10);
827 }
828
829 if (! emacs_pid) /* emacs_pid should be set above */
830 {
831 reset_tty ();
832 fprintf (stderr, "%s: %s\n", progname, string);
833 return 0;
834 }
835 }
836 }
837 }
838 return 1;
839 }
840
841 #endif /* HAVE_TERMIOS */
842
843 \f
844 #if !defined (HAVE_SOCKETS) || defined (NO_SOCKETS_IN_FILE_SYSTEM)
845
846 int
847 main (argc, argv)
848 int argc;
849 char **argv;
850 {
851 fprintf (stderr, "%s: Sorry, the Emacs server is supported only\n",
852 argv[0]);
853 fprintf (stderr, "on systems with Berkeley sockets.\n");
854
855 fail ();
856 }
857
858 #else /* HAVE_SOCKETS */
859
860 #include <sys/types.h>
861 #include <sys/socket.h>
862 #include <sys/un.h>
863 #include <sys/stat.h>
864 #include <errno.h>
865
866 extern char *strerror ();
867 extern int errno;
868
869 /* Three possibilities:
870 2 - can't be `stat'ed (sets errno)
871 1 - isn't owned by us
872 0 - success: none of the above */
873
874 static int
875 socket_status (socket_name)
876 char *socket_name;
877 {
878 struct stat statbfr;
879
880 if (stat (socket_name, &statbfr) == -1)
881 return 2;
882
883 if (statbfr.st_uid != geteuid ())
884 return 1;
885
886 return 0;
887 }
888
889 int
890 main (argc, argv)
891 int argc;
892 char **argv;
893 {
894 char *system_name;
895 int system_name_length;
896 int s, i, needlf = 0;
897 FILE *out, *in;
898 struct sockaddr_un server;
899 char *cwd, *str;
900 char string[BUFSIZ];
901
902 main_argc = argc;
903 main_argv = argv;
904 progname = argv[0];
905
906 /* Process options. */
907 decode_options (argc, argv);
908
909 if ((argc - optind < 1) && !eval && !frame)
910 {
911 fprintf (stderr, "%s: file name or argument required\n", progname);
912 fprintf (stderr, "Try `%s --help' for more information\n", progname);
913 exit (1);
914 }
915
916 /*
917 * Open up an AF_UNIX socket in this person's home directory
918 */
919
920 if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
921 {
922 fprintf (stderr, "%s: ", argv[0]);
923 perror ("socket");
924 fail ();
925 }
926
927 server.sun_family = AF_UNIX;
928
929 {
930 char *dot;
931 system_name_length = 32;
932
933 while (1)
934 {
935 system_name = (char *) xmalloc (system_name_length + 1);
936
937 /* system_name must be null-terminated string. */
938 system_name[system_name_length] = '\0';
939
940 if (gethostname (system_name, system_name_length) == 0)
941 break;
942
943 free (system_name);
944 system_name_length *= 2;
945 }
946
947 /* We always use the non-dotted host name, for simplicity. */
948 dot = index (system_name, '.');
949 if (dot)
950 *dot = '\0';
951 }
952
953 {
954 int sock_status = 0;
955 int oerrno = 0;
956
957 if (! socket_name)
958 {
959 socket_name = alloca (system_name_length + 100);
960 sprintf (socket_name, "/tmp/emacs%d-%s/server",
961 (int) geteuid (), system_name);
962 }
963
964 if (strlen (socket_name) < sizeof (server.sun_path))
965 strcpy (server.sun_path, socket_name);
966 else
967 {
968 fprintf (stderr, "%s: socket-name %s too long",
969 argv[0], socket_name);
970 fail ();
971 }
972
973 /* See if the socket exists, and if it's owned by us. */
974 sock_status = socket_status (server.sun_path);
975 oerrno = errno;
976 if (sock_status)
977 {
978 /* Failing that, see if LOGNAME or USER exist and differ from
979 our euid. If so, look for a socket based on the UID
980 associated with the name. This is reminiscent of the logic
981 that init_editfns uses to set the global Vuser_full_name. */
982
983 char *user_name = (char *) getenv ("LOGNAME");
984 if (!user_name)
985 user_name = (char *) getenv ("USER");
986
987 if (user_name)
988 {
989 struct passwd *pw = getpwnam (user_name);
990 if (pw && (pw->pw_uid != geteuid ()))
991 {
992 /* We're running under su, apparently. */
993 sprintf (server.sun_path, "/tmp/esrv%d-%s",
994 (int) pw->pw_uid, system_name);
995 sock_status = socket_status (server.sun_path);
996 oerrno = errno;
997 }
998 }
999 }
1000
1001 switch (sock_status)
1002 {
1003 case 1:
1004 /* There's a socket, but it isn't owned by us. This is OK if
1005 we are root. */
1006 if (0 != geteuid ())
1007 {
1008 fprintf (stderr, "%s: Invalid socket owner\n", argv[0]);
1009 fail ();
1010 }
1011 break;
1012
1013 case 2:
1014 /* `stat' failed */
1015 if (errno == ENOENT)
1016 fprintf (stderr,
1017 "%s: Can't find socket; have you started the server?\n\
1018 To start the server in Emacs, type \"M-x server-start\".\n",
1019 argv[0]);
1020 else
1021 fprintf (stderr, "%s: Can't stat %s: %s\n",
1022 argv[0], server.sun_path, strerror (oerrno));
1023 fail ();
1024 break;
1025 }
1026 }
1027
1028 if (connect (s, (struct sockaddr *) &server, strlen (server.sun_path) + 2)
1029 < 0)
1030 {
1031 fprintf (stderr, "%s: ", argv[0]);
1032 perror ("connect");
1033 fail ();
1034 }
1035
1036 /* We use the stream OUT to send our command to the server. */
1037 if ((out = fdopen (s, "r+")) == NULL)
1038 {
1039 fprintf (stderr, "%s: ", argv[0]);
1040 perror ("fdopen");
1041 fail ();
1042 }
1043
1044 /* We use the stream IN to read the response.
1045 We used to use just one stream for both output and input
1046 on the socket, but reversing direction works nonportably:
1047 on some systems, the output appears as the first input;
1048 on other systems it does not. */
1049 if ((in = fdopen (s, "r+")) == NULL)
1050 {
1051 fprintf (stderr, "%s: ", argv[0]);
1052 perror ("fdopen");
1053 fail ();
1054 }
1055
1056 #ifdef HAVE_GETCWD
1057 cwd = getcwd (string, sizeof string);
1058 #else
1059 cwd = getwd (string);
1060 #endif
1061 if (cwd == 0)
1062 {
1063 /* getwd puts message in STRING if it fails. */
1064
1065 #ifdef HAVE_GETCWD
1066 fprintf (stderr, "%s: %s (%s)\n", argv[0],
1067 "Cannot get current working directory", strerror (errno));
1068 #else
1069 fprintf (stderr, "%s: %s (%s)\n", argv[0], string, strerror (errno));
1070 #endif
1071 fail ();
1072 }
1073
1074 if (nowait)
1075 fprintf (out, "-nowait ");
1076
1077 if (eval)
1078 fprintf (out, "-eval ");
1079
1080 if (display)
1081 {
1082 fprintf (out, "-display ");
1083 quote_file_name (display, out);
1084 fprintf (out, " ");
1085 }
1086
1087 if (frame)
1088 {
1089 if (! init_signals ())
1090 {
1091 fprintf (stderr, "%s: ", argv[0]);
1092 perror ("fdopen");
1093 fail ();
1094 }
1095
1096 if (! init_tty ())
1097 {
1098 reset_tty ();
1099 fprintf (stderr, "%s: ", argv[0]);
1100 perror ("fdopen");
1101 fail ();
1102 }
1103
1104 if (! init_pty ())
1105 {
1106 reset_tty ();
1107 fprintf (stderr, "%s: ", argv[0]);
1108 perror ("fdopen");
1109 fail ();
1110 }
1111
1112 fprintf (out, "-tty ");
1113 quote_file_name (pty_name, out);
1114 fprintf (out, " ");
1115 quote_file_name (getenv("TERM"), out);
1116 fprintf (out, " ");
1117 }
1118
1119 if ((argc - optind > 0))
1120 {
1121 for (i = optind; i < argc; i++)
1122 {
1123 if (eval)
1124 ; /* Don't prepend any cwd or anything like that. */
1125 else if (*argv[i] == '+')
1126 {
1127 char *p = argv[i] + 1;
1128 while (isdigit ((unsigned char) *p) || *p == ':') p++;
1129 if (*p != 0)
1130 {
1131 quote_file_name (cwd, out);
1132 fprintf (out, "/");
1133 }
1134 }
1135 else if (*argv[i] != '/')
1136 {
1137 quote_file_name (cwd, out);
1138 fprintf (out, "/");
1139 }
1140
1141 quote_file_name (argv[i], out);
1142 fprintf (out, " ");
1143 }
1144 }
1145 else
1146 {
1147 if (!frame)
1148 {
1149 while ((str = fgets (string, BUFSIZ, stdin)))
1150 {
1151 quote_file_name (str, out);
1152 }
1153 fprintf (out, " ");
1154 }
1155 }
1156
1157 fprintf (out, "\n");
1158 fflush (out);
1159
1160 /* Maybe wait for an answer. */
1161 if (nowait)
1162 {
1163 reset_tty ();
1164 return 0;
1165 }
1166
1167 if (frame)
1168 {
1169 if (! pty_conversation (out))
1170 {
1171 reset_tty ();
1172 fail ();
1173 }
1174 reset_tty ();
1175 return 0;
1176 }
1177
1178 if (!eval)
1179 {
1180 printf ("Waiting for Emacs...");
1181 needlf = 2;
1182 }
1183 fflush (stdout);
1184
1185 /* Now, wait for an answer and print any messages. */
1186 while ((str = fgets (string, BUFSIZ, in)))
1187 {
1188 if (needlf == 2)
1189 printf ("\n");
1190 printf ("%s", str);
1191 needlf = str[0] == '\0' ? needlf : str[strlen (str) - 1] != '\n';
1192 }
1193
1194 if (needlf)
1195 printf ("\n");
1196 fflush (stdout);
1197
1198 reset_tty ();
1199 return 0;
1200 }
1201
1202 #endif /* HAVE_SOCKETS */
1203 \f
1204 #ifndef HAVE_STRERROR
1205 char *
1206 strerror (errnum)
1207 int errnum;
1208 {
1209 extern char *sys_errlist[];
1210 extern int sys_nerr;
1211
1212 if (errnum >= 0 && errnum < sys_nerr)
1213 return sys_errlist[errnum];
1214 return (char *) "Unknown error";
1215 }
1216
1217 #endif /* ! HAVE_STRERROR */
1218
1219 /* arch-tag: f39bb9c4-73eb-477e-896d-50832e2ca9a7
1220 (do not change this comment) */