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 ();
78 fprintf (stderr
, "Usage: %s [+linenumber] filename\n", argv
[0]);
83 * Open up an AF_UNIX socket in this person's home directory
86 if ((s
= socket (AF_UNIX
, SOCK_STREAM
, 0)) < 0)
88 fprintf (stderr
, "%s: ", argv
[0]);
92 server
.sun_family
= AF_UNIX
;
93 #ifndef SERVER_HOME_DIR
97 gethostname (system_name
, sizeof (system_name
));
98 sprintf (server
.sun_path
, "/tmp/esrv%d-%s", geteuid (), system_name
);
100 if (stat (server
.sun_path
, &statbfr
) == -1)
104 "%s: can't find socket; have you started the server?\n",
107 fprintf (stderr
, "%s: can't stat %s: %s\n",
108 argv
[0], server
.sun_path
, strerror (errno
));
111 if (statbfr
.st_uid
!= geteuid ())
113 fprintf (stderr
, "%s: Invalid socket owner\n", argv
[0]);
118 if ((homedir
= getenv ("HOME")) == NULL
)
120 fprintf (stderr
, "%s: No home directory\n", argv
[0]);
123 strcpy (server
.sun_path
, homedir
);
124 strcat (server
.sun_path
, "/.emacs-server-");
125 gethostname (system_name
, sizeof (system_name
));
126 strcat (server
.sun_path
, system_name
);
129 if (connect (s
, (struct sockaddr
*) &server
, strlen (server
.sun_path
) + 2)
132 fprintf (stderr
, "%s: ", argv
[0]);
137 /* We use the stream OUT to send our command to the server. */
138 if ((out
= fdopen (s
, "r+")) == NULL
)
140 fprintf (stderr
, "%s: ", argv
[0]);
145 /* We use the stream IN to read the response.
146 We used to use just one stream for both output and input
147 on the socket, but reversing direction works nonportably:
148 on some systems, the output appears as the first input;
149 on other systems it does not. */
150 if ((in
= fdopen (s
, "r+")) == NULL
)
152 fprintf (stderr
, "%s: ", argv
[0]);
158 cwd
= getwd (string
);
160 cwd
= getcwd (string
, sizeof string
);
164 /* getwd puts message in STRING if it fails. */
165 fprintf (stderr
, "%s: %s (%s)\n", argv
[0], string
, strerror (errno
));
169 for (i
= 1; i
< argc
; i
++)
171 /* If -nowait or --nowait option is used,
172 report it to the server. */
173 if (!strcmp (argv
[i
], "-nowait")
174 || (!strncmp (argv
[i
], "--nowait", strlen (argv
[i
]))
175 && strlen (argv
[i
]) >= 3))
177 fprintf (out
, "-nowait ");
184 char *p
= argv
[i
] + 1;
185 while (*p
>= '0' && *p
<= '9') p
++;
187 fprintf (out
, "%s/", cwd
);
189 else if (*argv
[i
] != '/')
190 fprintf (out
, "%s/", cwd
);
191 fprintf (out
, "%s ", argv
[i
]);
196 /* Maybe wait for an answer. */
200 printf ("Waiting for Emacs...");
203 /* Now, wait for an answer and print any messages. On some systems,
204 the first line we read will actually be the output we just sent.
205 We can't predict whether that will happen, so if it does, we
206 detect it by recognizing `Client: ' at the beginning. */
208 while (str
= fgets (string
, BUFSIZ
, in
))
214 #else /* This is the SYSV IPC section */
216 #include <sys/types.h>
219 #include <sys/utsname.h>
222 char *getwd (), *getcwd (), *getenv ();
223 struct utsname system_name
;
231 /* Size of text allocated in MSGP. */
232 int size_allocated
= BUFSIZ
;
233 /* Amount of text used in MSGP. */
236 = (struct msgbuf
*) malloc (sizeof (struct msgbuf
) + size_allocated
);
237 struct msqid_ds
* msg_st
;
238 char *homedir
, buf
[BUFSIZ
];
242 char *progname
= argv
[0];
247 fprintf (stderr
, "Usage: %s [+linenumber] filename\n", argv
[0]);
252 * Create a message queue using ~/.emacs-server as the path for ftok
254 if ((homedir
= getenv ("HOME")) == NULL
)
256 fprintf (stderr
, "%s: No home directory\n", argv
[0]);
259 strcpy (buf
, homedir
);
260 #ifndef HAVE_LONG_FILE_NAMES
261 /* If file names are short, we can't fit the host name. */
262 strcat (buf
, "/.emacs-server");
264 strcat (buf
, "/.emacs-server-");
265 uname (&system_name
);
266 strcat (buf
, system_name
.nodename
);
269 key
= ftok (buf
, 1); /* unlikely to be anyone else using it */
270 s
= msgget (key
, 0600 | IPC_CREAT
);
273 fprintf (stderr
, "%s: ", argv
[0]);
278 /* Determine working dir, so we can prefix it to all the arguments. */
280 temp
= getwd (gwdirb
);
282 temp
= getcwd (gwdirb
, sizeof gwdirb
);
288 /* On some systems, cwd can look like `@machine/...';
289 ignore everything before the first slash in such a case. */
290 while (*cwd
&& *cwd
!= '/')
296 fprintf (stderr
, "%s: %s\n", argv
[0], cwd
);
306 char *modified_arg
= argv
[0];
308 /* If -nowait or --nowait option is used,
309 report it to the server. */
310 if (!strcmp (modified_arg
, "-nowait")
311 || (!strncmp (modified_arg
, "--nowait", strlen (modified_arg
))
312 && strlen (modified_arg
) >= 3))
314 modified_arg
= "-nowait";
317 else if (*modified_arg
== '+')
319 char *p
= modified_arg
+ 1;
320 while (*p
>= '0' && *p
<= '9') p
++;
324 else if (*modified_arg
!= '/')
328 used
+= strlen (cwd
);
329 used
+= strlen (modified_arg
) + 1;
330 while (used
+ 2 > size_allocated
)
333 msgp
= (struct msgbuf
*) realloc (msgp
,
334 (sizeof (struct msgbuf
)
339 strcat (msgp
->mtext
, cwd
);
341 strcat (msgp
->mtext
, modified_arg
);
342 strcat (msgp
->mtext
, " ");
345 strcat (msgp
->mtext
, "\n");
346 #ifdef HPUX /* HPUX has a bug. */
347 if (strlen (msgp
->mtext
) >= 512)
349 fprintf (stderr
, "%s: args too long for msgsnd\n", progname
);
354 if (msgsnd (s
, msgp
, strlen (msgp
->mtext
)+1, 0) < 0)
356 fprintf (stderr
, "%s: ", progname
);
361 /* Maybe wait for an answer. */
365 printf ("Waiting for Emacs...");
368 msgrcv (s
, msgp
, BUFSIZ
, getpid (), 0); /* wait for anything back */
369 strcpy (buf
, msgp
->mtext
);
373 printf ("%s\n", buf
);
377 #endif /* HAVE_SYSVIPC */
379 #endif /* HAVE_SOCKETS or HAVE_SYSVIPC */
381 #ifndef HAVE_STRERROR
386 extern char *sys_errlist
[];
389 if (errnum
>= 0 && errnum
< sys_nerr
)
390 return sys_errlist
[errnum
];
391 return (char *) "Unknown error";
394 #endif /* ! HAVE_STRERROR */