1 /* Client process that communicates with GNU Emacs acting as server.
2    Copyright (C) 1986, 1987 Free Software Foundation, Inc.
3 
4 This file is part of GNU Emacs.
5 
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 1, or (at your option)
9 any later version.
10 
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.
15 
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, 675 Mass Ave, Cambridge, MA 02139, USA.  */
19 
20 
21 #define NO_SHORTNAMES
22 #include "../src/config.h"
23 #undef read
24 #undef write
25 #undef open
26 #ifdef close
27 #undef close
28 #endif
29 
30 
31 #if !defined(BSD) && !defined(HAVE_SYSVIPC)
32 #include <stdio.h>
33 
34 main (argc, argv)
35      int argc;
36      char **argv;
37 {
38   fprintf (stderr, "%s: Sorry, the Emacs server is supported only\n",
39 	   argv[0]);
40   fprintf (stderr, "on systems with Berkeley sockets or System V IPC.\n");
41   exit (1);
42 }
43 
44 #else /* BSD or HAVE_SYSVIPC */
45 
46 #if defined(BSD) && ! defined (HAVE_SYSVIPC)
47 /* BSD code is very different from SYSV IPC code */
48 
49 #include <sys/types.h>
50 #include <sys/socket.h>
51 #include <sys/un.h>
52 #include <stdio.h>
53 #include <errno.h>
54 #include <sys/stat.h>
55 
56 #ifndef BSD4_4
57 extern int sys_nerr;
58 extern char *sys_errlist[];
59 extern int errno;
60 #endif
61 
62 main (argc, argv)
63      int argc;
64      char **argv;
65 {
66   int s, i;
67   FILE *out;
68   struct sockaddr_un server;
69   char *homedir, *cwd, *str;
70   char string[BUFSIZ];
71   struct stat statbfr;
72 
73   char *getenv (), *getwd ();
74 
75   if (argc < 2)
76     {
77       fprintf (stderr, "Usage: %s filename\n", argv[0]);
78       exit (1);
79     }
80 
81   /*
82    * Open up an AF_UNIX socket in this person's home directory
83    */
84 
85   if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
86     {
87       fprintf (stderr, "%s: ", argv[0]);
88       perror ("socket");
89       exit (1);
90     }
91   server.sun_family = AF_UNIX;
92 #ifndef SERVER_HOME_DIR
93   (void) sprintf (server.sun_path, "/tmp/esrv%d", geteuid());
94   if (stat (server.sun_path, &statbfr) == -1)
95     {
96       perror ("stat");
97       exit (1);
98     }
99   if (statbfr.st_uid != geteuid())
100     {
101       fprintf (stderr, "Illegal socket owner\n");
102       exit (1);
103     }
104 #else
105   if ((homedir = getenv ("HOME")) == NULL)
106     {
107       fprintf (stderr, "%s: No home directory\n", argv[0]);
108       exit (1);
109     }
110   strcpy (server.sun_path, homedir);
111   strcat (server.sun_path, "/.emacs_server");
112 #endif
113 
114   if (connect (s, &server, strlen (server.sun_path) + 2) < 0)
115     {
116       fprintf (stderr, "%s: ", argv[0]);
117       perror ("connect");
118       exit (1);
119     }
120   if ((out = fdopen (s, "r+")) == NULL)
121     {
122       fprintf (stderr, "%s: ", argv[0]);
123       perror ("fdopen");
124       exit (1);
125     }
126 
127   cwd = getwd (string);
128   if (cwd == 0)
129     {
130       /* getwd puts message in STRING if it fails.  */
131       fprintf (stderr, "%s: %s (%s)\n", argv[0], string,
132 	       (errno < sys_nerr) ? sys_errlist[errno] : "unknown error");
133       exit (1);
134     }
135 
136   for (i = 1; i < argc; i++)
137     {
138       if (*argv[i] == '+')
139 	{
140 	  char *p = argv[i] + 1;
141 	  while (*p >= '0' && *p <= '9') p++;
142 	  if (*p != 0)
143 	    fprintf (out, "%s/", cwd);
144 	}
145       else if (*argv[i] != '/')
146 	fprintf (out, "%s/", cwd);
147       fprintf (out, "%s ", argv[i]);
148     }
149   fprintf (out, "\n");
150   fflush (out);
151 
152   printf ("Waiting for Emacs...");
153   fflush (stdout);
154 
155   rewind (out); /* re-read the output */
156   str = fgets (string, BUFSIZ, out);
157 
158   /* Now, wait for an answer and print any messages.  */
159 
160   while (str = fgets (string, BUFSIZ, out))
161     printf ("%s", str);
162 
163   exit (0);
164 }
165 
166 #else /* This is the SYSV IPC section */
167 
168 #include <sys/types.h>
169 #include <sys/ipc.h>
170 #include <sys/msg.h>
171 #include <stdio.h>
172 
173 main (argc, argv)
174      int argc;
175      char **argv;
176 {
177   int s;
178   key_t key;
179   struct msgbuf * msgp =
180       (struct msgbuf *) malloc (sizeof *msgp + BUFSIZ);
181   struct msqid_ds * msg_st;
182   char *homedir, buf[BUFSIZ];
183   char gwdirb[BUFSIZ];
184   char *cwd;
185   char *temp;
186   char *getwd (), *getcwd (), *getenv ();
187 
188   if (argc < 2)
189     {
190       fprintf (stderr, "Usage: %s filename\n", argv[0]);
191       exit (1);
192     }
193 
194   /*
195    * Create a message queue using ~/.emacs_server as the path for ftok
196    */
197   if ((homedir = getenv ("HOME")) == NULL)
198     {
199       fprintf (stderr, "%s: No home directory\n", argv[0]);
200       exit (1);
201     }
202   strcpy (buf, homedir);
203   strcat (buf, "/.emacs_server");
204   creat (buf, 0600);
205   key = ftok (buf, 1);	/* unlikely to be anyone else using it */
206   s = msgget (key, 0600);
207   if (s == -1)
208     {
209       fprintf (stderr, "%s: ", argv[0]);
210       perror ("msgget");
211       exit (1);
212     }
213 
214   /* Determine working dir, so we can prefix it to all the arguments.  */
215 #ifdef BSD
216   temp = getwd (gwdirb);
217 #else
218   temp = getcwd (gwdirb, sizeof gwdirb);
219 #endif
220 
221   cwd = gwdirb;
222   if (temp != 0)
223     {
224       /* On some systems, cwd can look like `@machine/...';
225 	 ignore everything before the first slash in such a case.  */
226       while (*cwd && *cwd != '/')
227 	cwd++;
228       strcat (cwd, "/");
229     }
230   else
231     {
232       fprintf (stderr, cwd);
233       exit (1);
234     }
235 
236   msgp->mtext[0] = 0;
237   argc--; argv++;
238   while (argc)
239     {
240       if (*argv[0] == '+')
241 	{
242 	  char *p = argv[0] + 1;
243 	  while (*p >= '0' && *p <= '9') p++;
244 	  if (*p != 0)
245 	    strcat (msgp->mtext, cwd);
246 	}
247       else if (*argv[0] != '/')
248 	strcat (msgp->mtext, cwd);
249 
250       strcat (msgp->mtext, argv[0]);
251       strcat (msgp->mtext, " ");
252       argv++; argc--;
253     }
254   strcat (msgp->mtext, "\n");
255   msgp->mtype = 1;
256   if (msgsnd (s, msgp, strlen (msgp->mtext)+1, 0) < 0)
257     {
258       fprintf (stderr, "%s: ", argv[0]);
259       perror ("msgsnd");
260       exit (1);
261     }
262   /*
263    * Now, wait for an answer
264    */
265   printf ("Waiting for Emacs...");
266   fflush (stdout);
267 
268   msgrcv (s, msgp, BUFSIZ, getpid (), 0);	/* wait for anything back */
269   strcpy (buf, msgp->mtext);
270 
271   printf ("\n%s\n", buf);
272   exit (0);
273 }
274 
275 #endif /* HAVE_SYSVIPC */
276 
277 #endif /* BSD or HAVE_SYSVIPC */
278