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