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