1 /* Client process that communicates with GNU Emacs acting as server.
2 Copyright (C) 1986, 1987, 1994 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>
31 #if !defined (HAVE_SOCKETS) && !defined (HAVE_SYSVIPC)
38 fprintf (stderr
, "%s: Sorry, the Emacs server is supported only\n",
40 fprintf (stderr
, "on systems with Berkeley sockets or System V IPC.\n");
44 #else /* HAVE_SOCKETS or HAVE_SYSVIPC */
46 #if defined (HAVE_SOCKETS) && ! defined (NO_SOCKETS_IN_FILE_SYSTEM)
47 /* BSD code is very different from SYSV IPC code */
49 #include <sys/types.h>
50 #include <sys/socket.h>
56 extern char *strerror ();
67 struct sockaddr_un server
;
68 char *homedir
, *cwd
, *str
;
71 char *getenv (), *getwd ();
77 fprintf (stderr
, "Usage: %s [+linenumber] filename\n", argv
[0]);
82 * Open up an AF_UNIX socket in this person's home directory
85 if ((s
= socket (AF_UNIX
, SOCK_STREAM
, 0)) < 0)
87 fprintf (stderr
, "%s: ", argv
[0]);
91 server
.sun_family
= AF_UNIX
;
92 #ifndef SERVER_HOME_DIR
96 gethostname (system_name
, sizeof (system_name
));
97 sprintf (server
.sun_path
, "/tmp/esrv%d-%s", geteuid (), system_name
);
99 if (stat (server
.sun_path
, &statbfr
) == -1)
103 "%s: can't find socket; have you started the server?\n",
106 fprintf (stderr
, "%s: can't stat %s: %s\n",
107 argv
[0], server
.sun_path
, strerror (errno
));
110 if (statbfr
.st_uid
!= geteuid ())
112 fprintf (stderr
, "%s: Invalid socket owner\n", argv
[0]);
117 if ((homedir
= getenv ("HOME")) == NULL
)
119 fprintf (stderr
, "%s: No home directory\n", argv
[0]);
122 strcpy (server
.sun_path
, homedir
);
123 strcat (server
.sun_path
, "/.emacs-server-");
124 gethostname (system_name
, sizeof (system_name
));
125 strcat (server
.sun_path
, system_name
);
128 if (connect (s
, (struct sockaddr
*) &server
, strlen (server
.sun_path
) + 2)
131 fprintf (stderr
, "%s: ", argv
[0]);
136 /* We use the stream OUT to send our command to the server. */
137 if ((out
= fdopen (s
, "r+")) == NULL
)
139 fprintf (stderr
, "%s: ", argv
[0]);
144 /* We use the stream IN to read the response.
145 We used to use just one stream for both output and input
146 on the socket, but reversing direction works nonportably:
147 on some systems, the output appears as the first input;
148 on other systems it does not. */
149 if ((in
= fdopen (s
, "r+")) == NULL
)
151 fprintf (stderr
, "%s: ", argv
[0]);
157 cwd
= getwd (string
);
159 cwd
= getcwd (string
, sizeof string
);
163 /* getwd puts message in STRING if it fails. */
164 fprintf (stderr
, "%s: %s (%s)\n", argv
[0], string
, strerror (errno
));
168 for (i
= 1; i
< argc
; i
++)
172 char *p
= argv
[i
] + 1;
173 while (*p
>= '0' && *p
<= '9') p
++;
175 fprintf (out
, "%s/", cwd
);
177 else if (*argv
[i
] != '/')
178 fprintf (out
, "%s/", cwd
);
179 fprintf (out
, "%s ", argv
[i
]);
184 printf ("Waiting for Emacs...");
187 /* Now, wait for an answer and print any messages. On some systems,
188 the first line we read will actually be the output we just sent.
189 We can't predict whether that will happen, so if it does, we
190 detect it by recognizing `Client: ' at the beginning. */
192 while (str
= fgets (string
, BUFSIZ
, in
))
198 #else /* This is the SYSV IPC section */
200 #include <sys/types.h>
203 #include <sys/utsname.h>
206 char *getwd (), *getcwd (), *getenv ();
207 struct utsname system_name
;
215 /* Size of text allocated in MSGP. */
216 int size_allocated
= BUFSIZ
;
217 /* Amount of text used in MSGP. */
220 = (struct msgbuf
*) malloc (sizeof (struct msgbuf
) + size_allocated
);
221 struct msqid_ds
* msg_st
;
222 char *homedir
, buf
[BUFSIZ
];
226 char *progname
= argv
[0];
230 fprintf (stderr
, "Usage: %s [+linenumber] filename\n", argv
[0]);
235 * Create a message queue using ~/.emacs-server as the path for ftok
237 if ((homedir
= getenv ("HOME")) == NULL
)
239 fprintf (stderr
, "%s: No home directory\n", argv
[0]);
242 strcpy (buf
, homedir
);
243 #ifndef HAVE_LONG_FILE_NAMES
244 /* If file names are short, we can't fit the host name. */
245 strcat (buf
, "/.emacs-server");
247 strcat (buf
, "/.emacs-server-");
248 uname (&system_name
);
249 strcat (buf
, system_name
.nodename
);
252 key
= ftok (buf
, 1); /* unlikely to be anyone else using it */
253 s
= msgget (key
, 0600 | IPC_CREAT
);
256 fprintf (stderr
, "%s: ", argv
[0]);
261 /* Determine working dir, so we can prefix it to all the arguments. */
263 temp
= getwd (gwdirb
);
265 temp
= getcwd (gwdirb
, sizeof gwdirb
);
271 /* On some systems, cwd can look like `@machine/...';
272 ignore everything before the first slash in such a case. */
273 while (*cwd
&& *cwd
!= '/')
279 fprintf (stderr
, "%s: %s\n", argv
[0], cwd
);
289 char *modified_arg
= argv
[0];
290 if (*modified_arg
== '+')
292 char *p
= modified_arg
+ 1;
293 while (*p
>= '0' && *p
<= '9') p
++;
297 else if (*modified_arg
!= '/')
301 used
+= strlen (cwd
);
302 used
+= strlen (modified_arg
) + 1;
303 while (used
+ 2 > size_allocated
)
306 msgp
= (struct msgbuf
*) realloc (msgp
,
307 (sizeof (struct msgbuf
)
312 strcat (msgp
->mtext
, cwd
);
314 strcat (msgp
->mtext
, modified_arg
);
315 strcat (msgp
->mtext
, " ");
318 strcat (msgp
->mtext
, "\n");
319 #ifdef HPUX /* HPUX has a bug. */
320 if (strlen (msgp
->mtext
) >= 512)
322 fprintf (stderr
, "%s: args too long for msgsnd\n", progname
);
327 if (msgsnd (s
, msgp
, strlen (msgp
->mtext
)+1, 0) < 0)
329 fprintf (stderr
, "%s: ", progname
);
334 * Now, wait for an answer
336 printf ("Waiting for Emacs...");
339 msgrcv (s
, msgp
, BUFSIZ
, getpid (), 0); /* wait for anything back */
340 strcpy (buf
, msgp
->mtext
);
344 printf ("%s\n", buf
);
348 #endif /* HAVE_SYSVIPC */
350 #endif /* HAVE_SOCKETS or HAVE_SYSVIPC */
352 #ifndef HAVE_STRERROR
357 extern char *sys_errlist
[];
360 if (errnum
>= 0 && errnum
< sys_nerr
)
361 return sys_errlist
[errnum
];
362 return (char *) "Unknown error";
365 #endif /* ! HAVE_STRERROR */