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