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