159815Shibler /* Client process that communicates with GNU Emacs acting as server.
259815Shibler    Copyright (C) 1986, 1987 Free Software Foundation, Inc.
359815Shibler 
459815Shibler This file is part of GNU Emacs.
559815Shibler 
659815Shibler GNU Emacs is free software; you can redistribute it and/or modify
759815Shibler it under the terms of the GNU General Public License as published by
859815Shibler the Free Software Foundation; either version 1, or (at your option)
959815Shibler any later version.
1059815Shibler 
1159815Shibler GNU Emacs is distributed in the hope that it will be useful,
1259815Shibler but WITHOUT ANY WARRANTY; without even the implied warranty of
1359815Shibler MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1459815Shibler GNU General Public License for more details.
1559815Shibler 
1659815Shibler You should have received a copy of the GNU General Public License
1759815Shibler along with GNU Emacs; see the file COPYING.  If not, write to
1859815Shibler the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
1959815Shibler 
2059815Shibler 
2159815Shibler #define NO_SHORTNAMES
2259815Shibler #include "../src/config.h"
2359815Shibler #undef read
2459815Shibler #undef write
2559815Shibler #undef open
2659815Shibler #ifdef close
2759815Shibler #undef close
2859815Shibler #endif
2959815Shibler 
3059815Shibler 
3159815Shibler #if !defined(BSD) && !defined(HAVE_SYSVIPC)
3259815Shibler #include <stdio.h>
3359815Shibler 
main(argc,argv)3459815Shibler main (argc, argv)
3559815Shibler      int argc;
3659815Shibler      char **argv;
3759815Shibler {
3859815Shibler   fprintf (stderr, "%s: Sorry, the Emacs server is supported only\n",
3959815Shibler 	   argv[0]);
4059815Shibler   fprintf (stderr, "on systems with Berkeley sockets or System V IPC.\n");
4159815Shibler   exit (1);
4259815Shibler }
4359815Shibler 
4459815Shibler #else /* BSD or HAVE_SYSVIPC */
4559815Shibler 
4659815Shibler #if defined(BSD) && ! defined (HAVE_SYSVIPC)
4759815Shibler /* BSD code is very different from SYSV IPC code */
4859815Shibler 
4959815Shibler #include <sys/types.h>
5059815Shibler #include <sys/socket.h>
5159815Shibler #include <sys/un.h>
5259815Shibler #include <stdio.h>
5359815Shibler #include <errno.h>
5459815Shibler #include <sys/stat.h>
5559815Shibler 
56*60290Shibler #ifndef BSD4_4
5759815Shibler extern int sys_nerr;
5859815Shibler extern char *sys_errlist[];
5959815Shibler extern int errno;
60*60290Shibler #endif
6159815Shibler 
main(argc,argv)6259815Shibler main (argc, argv)
6359815Shibler      int argc;
6459815Shibler      char **argv;
6559815Shibler {
6659815Shibler   int s, i;
6759815Shibler   FILE *out;
6859815Shibler   struct sockaddr_un server;
6959815Shibler   char *homedir, *cwd, *str;
7059815Shibler   char string[BUFSIZ];
7159815Shibler   struct stat statbfr;
7259815Shibler 
7359815Shibler   char *getenv (), *getwd ();
7459815Shibler 
7559815Shibler   if (argc < 2)
7659815Shibler     {
7759815Shibler       fprintf (stderr, "Usage: %s filename\n", argv[0]);
7859815Shibler       exit (1);
7959815Shibler     }
8059815Shibler 
8159815Shibler   /*
8259815Shibler    * Open up an AF_UNIX socket in this person's home directory
8359815Shibler    */
8459815Shibler 
8559815Shibler   if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
8659815Shibler     {
8759815Shibler       fprintf (stderr, "%s: ", argv[0]);
8859815Shibler       perror ("socket");
8959815Shibler       exit (1);
9059815Shibler     }
9159815Shibler   server.sun_family = AF_UNIX;
9259815Shibler #ifndef SERVER_HOME_DIR
9359815Shibler   (void) sprintf (server.sun_path, "/tmp/esrv%d", geteuid());
9459815Shibler   if (stat (server.sun_path, &statbfr) == -1)
9559815Shibler     {
9659815Shibler       perror ("stat");
9759815Shibler       exit (1);
9859815Shibler     }
9959815Shibler   if (statbfr.st_uid != geteuid())
10059815Shibler     {
10159815Shibler       fprintf (stderr, "Illegal socket owner\n");
10259815Shibler       exit (1);
10359815Shibler     }
10459815Shibler #else
10559815Shibler   if ((homedir = getenv ("HOME")) == NULL)
10659815Shibler     {
10759815Shibler       fprintf (stderr, "%s: No home directory\n", argv[0]);
10859815Shibler       exit (1);
10959815Shibler     }
11059815Shibler   strcpy (server.sun_path, homedir);
11159815Shibler   strcat (server.sun_path, "/.emacs_server");
11259815Shibler #endif
11359815Shibler 
11459815Shibler   if (connect (s, &server, strlen (server.sun_path) + 2) < 0)
11559815Shibler     {
11659815Shibler       fprintf (stderr, "%s: ", argv[0]);
11759815Shibler       perror ("connect");
11859815Shibler       exit (1);
11959815Shibler     }
12059815Shibler   if ((out = fdopen (s, "r+")) == NULL)
12159815Shibler     {
12259815Shibler       fprintf (stderr, "%s: ", argv[0]);
12359815Shibler       perror ("fdopen");
12459815Shibler       exit (1);
12559815Shibler     }
12659815Shibler 
12759815Shibler   cwd = getwd (string);
12859815Shibler   if (cwd == 0)
12959815Shibler     {
13059815Shibler       /* getwd puts message in STRING if it fails.  */
13159815Shibler       fprintf (stderr, "%s: %s (%s)\n", argv[0], string,
13259815Shibler 	       (errno < sys_nerr) ? sys_errlist[errno] : "unknown error");
13359815Shibler       exit (1);
13459815Shibler     }
13559815Shibler 
13659815Shibler   for (i = 1; i < argc; i++)
13759815Shibler     {
13859815Shibler       if (*argv[i] == '+')
13959815Shibler 	{
14059815Shibler 	  char *p = argv[i] + 1;
14159815Shibler 	  while (*p >= '0' && *p <= '9') p++;
14259815Shibler 	  if (*p != 0)
14359815Shibler 	    fprintf (out, "%s/", cwd);
14459815Shibler 	}
14559815Shibler       else if (*argv[i] != '/')
14659815Shibler 	fprintf (out, "%s/", cwd);
14759815Shibler       fprintf (out, "%s ", argv[i]);
14859815Shibler     }
14959815Shibler   fprintf (out, "\n");
15059815Shibler   fflush (out);
15159815Shibler 
15259815Shibler   printf ("Waiting for Emacs...");
15359815Shibler   fflush (stdout);
15459815Shibler 
15559815Shibler   rewind (out); /* re-read the output */
15659815Shibler   str = fgets (string, BUFSIZ, out);
15759815Shibler 
15859815Shibler   /* Now, wait for an answer and print any messages.  */
15959815Shibler 
16059815Shibler   while (str = fgets (string, BUFSIZ, out))
16159815Shibler     printf ("%s", str);
16259815Shibler 
16359815Shibler   exit (0);
16459815Shibler }
16559815Shibler 
16659815Shibler #else /* This is the SYSV IPC section */
16759815Shibler 
16859815Shibler #include <sys/types.h>
16959815Shibler #include <sys/ipc.h>
17059815Shibler #include <sys/msg.h>
17159815Shibler #include <stdio.h>
17259815Shibler 
main(argc,argv)17359815Shibler main (argc, argv)
17459815Shibler      int argc;
17559815Shibler      char **argv;
17659815Shibler {
17759815Shibler   int s;
17859815Shibler   key_t key;
17959815Shibler   struct msgbuf * msgp =
18059815Shibler       (struct msgbuf *) malloc (sizeof *msgp + BUFSIZ);
18159815Shibler   struct msqid_ds * msg_st;
18259815Shibler   char *homedir, buf[BUFSIZ];
18359815Shibler   char gwdirb[BUFSIZ];
18459815Shibler   char *cwd;
18559815Shibler   char *temp;
18659815Shibler   char *getwd (), *getcwd (), *getenv ();
18759815Shibler 
18859815Shibler   if (argc < 2)
18959815Shibler     {
19059815Shibler       fprintf (stderr, "Usage: %s filename\n", argv[0]);
19159815Shibler       exit (1);
19259815Shibler     }
19359815Shibler 
19459815Shibler   /*
19559815Shibler    * Create a message queue using ~/.emacs_server as the path for ftok
19659815Shibler    */
19759815Shibler   if ((homedir = getenv ("HOME")) == NULL)
19859815Shibler     {
19959815Shibler       fprintf (stderr, "%s: No home directory\n", argv[0]);
20059815Shibler       exit (1);
20159815Shibler     }
20259815Shibler   strcpy (buf, homedir);
20359815Shibler   strcat (buf, "/.emacs_server");
20459815Shibler   creat (buf, 0600);
20559815Shibler   key = ftok (buf, 1);	/* unlikely to be anyone else using it */
20659815Shibler   s = msgget (key, 0600);
20759815Shibler   if (s == -1)
20859815Shibler     {
20959815Shibler       fprintf (stderr, "%s: ", argv[0]);
21059815Shibler       perror ("msgget");
21159815Shibler       exit (1);
21259815Shibler     }
21359815Shibler 
21459815Shibler   /* Determine working dir, so we can prefix it to all the arguments.  */
21559815Shibler #ifdef BSD
21659815Shibler   temp = getwd (gwdirb);
21759815Shibler #else
21859815Shibler   temp = getcwd (gwdirb, sizeof gwdirb);
21959815Shibler #endif
22059815Shibler 
22159815Shibler   cwd = gwdirb;
22259815Shibler   if (temp != 0)
22359815Shibler     {
22459815Shibler       /* On some systems, cwd can look like `@machine/...';
22559815Shibler 	 ignore everything before the first slash in such a case.  */
22659815Shibler       while (*cwd && *cwd != '/')
22759815Shibler 	cwd++;
22859815Shibler       strcat (cwd, "/");
22959815Shibler     }
23059815Shibler   else
23159815Shibler     {
23259815Shibler       fprintf (stderr, cwd);
23359815Shibler       exit (1);
23459815Shibler     }
23559815Shibler 
23659815Shibler   msgp->mtext[0] = 0;
23759815Shibler   argc--; argv++;
23859815Shibler   while (argc)
23959815Shibler     {
24059815Shibler       if (*argv[0] == '+')
24159815Shibler 	{
24259815Shibler 	  char *p = argv[0] + 1;
24359815Shibler 	  while (*p >= '0' && *p <= '9') p++;
24459815Shibler 	  if (*p != 0)
24559815Shibler 	    strcat (msgp->mtext, cwd);
24659815Shibler 	}
24759815Shibler       else if (*argv[0] != '/')
24859815Shibler 	strcat (msgp->mtext, cwd);
24959815Shibler 
25059815Shibler       strcat (msgp->mtext, argv[0]);
25159815Shibler       strcat (msgp->mtext, " ");
25259815Shibler       argv++; argc--;
25359815Shibler     }
25459815Shibler   strcat (msgp->mtext, "\n");
25559815Shibler   msgp->mtype = 1;
25659815Shibler   if (msgsnd (s, msgp, strlen (msgp->mtext)+1, 0) < 0)
25759815Shibler     {
25859815Shibler       fprintf (stderr, "%s: ", argv[0]);
25959815Shibler       perror ("msgsnd");
26059815Shibler       exit (1);
26159815Shibler     }
26259815Shibler   /*
26359815Shibler    * Now, wait for an answer
26459815Shibler    */
26559815Shibler   printf ("Waiting for Emacs...");
26659815Shibler   fflush (stdout);
26759815Shibler 
26859815Shibler   msgrcv (s, msgp, BUFSIZ, getpid (), 0);	/* wait for anything back */
26959815Shibler   strcpy (buf, msgp->mtext);
27059815Shibler 
27159815Shibler   printf ("\n%s\n", buf);
27259815Shibler   exit (0);
27359815Shibler }
27459815Shibler 
27559815Shibler #endif /* HAVE_SYSVIPC */
27659815Shibler 
27759815Shibler #endif /* BSD or HAVE_SYSVIPC */
278