|
|
1.1 ! root 1: /* Communication subprocess for 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: /* The GNU Emacs edit server process is run as a subprocess of Emacs ! 22: under control of the file lisp/server.el. ! 23: This program accepts communication from client (program emacsclient.c) ! 24: and passes their commands (consisting of keyboard characters) ! 25: up to the Emacs which then executes them. */ ! 26: ! 27: /* This must precede sys/signal.h on certain machines. */ ! 28: #include <sys/types.h> ! 29: /* This must precede config.h on certain machines. */ ! 30: #include <sys/signal.h> ! 31: ! 32: #define NO_SHORTNAMES ! 33: #include "../src/config.h" ! 34: #undef read ! 35: #undef write ! 36: #undef open ! 37: #undef close ! 38: ! 39: ! 40: #if !defined(BSD) && !defined(HAVE_SYSVIPC) ! 41: #include <stdio.h> ! 42: ! 43: main () ! 44: { ! 45: fprintf (stderr, "Sorry, the Emacs server is supported only on Berkeley Unix\n"); ! 46: fprintf (stderr, "or System V systems with IPC\n"); ! 47: exit (1); ! 48: } ! 49: ! 50: #else /* BSD or HAVE_SYSVIPC */ ! 51: ! 52: #if defined (BSD) && ! defined (HAVE_SYSVIPC) ! 53: /* BSD code is very different from SYSV IPC code */ ! 54: ! 55: #include <sys/file.h> ! 56: #include <sys/types.h> ! 57: #include <sys/socket.h> ! 58: #include <sys/un.h> ! 59: #include <stdio.h> ! 60: #include <errno.h> ! 61: ! 62: extern int errno; ! 63: ! 64: main () ! 65: { ! 66: char system_name[32]; ! 67: int s, infd, fromlen; ! 68: struct sockaddr_un server, fromunix; ! 69: char *homedir; ! 70: char *str, string[BUFSIZ], code[BUFSIZ]; ! 71: FILE *infile; ! 72: FILE **openfiles; ! 73: int openfiles_size; ! 74: ! 75: char *getenv (); ! 76: ! 77: openfiles_size = 20; ! 78: openfiles = (FILE **) malloc (openfiles_size * sizeof (FILE *)); ! 79: if (openfiles == 0) ! 80: abort (); ! 81: ! 82: /* ! 83: * Open up an AF_UNIX socket in this person's home directory ! 84: */ ! 85: ! 86: if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) < 0) ! 87: { ! 88: perror ("socket"); ! 89: exit (1); ! 90: } ! 91: server.sun_family = AF_UNIX; ! 92: #ifndef SERVER_HOME_DIR ! 93: gethostname (system_name, sizeof (system_name)); ! 94: sprintf (server.sun_path, "/tmp/esrv%d-%s", geteuid (), system_name); ! 95: ! 96: if (unlink (server.sun_path) == -1 && errno != ENOENT) ! 97: { ! 98: perror ("unlink"); ! 99: exit (1); ! 100: } ! 101: #else ! 102: if ((homedir = getenv ("HOME")) == NULL) ! 103: { ! 104: fprintf (stderr,"No home directory\n"); ! 105: exit (1); ! 106: } ! 107: strcpy (server.sun_path, homedir); ! 108: strcat (server.sun_path, "/.emacs_server"); ! 109: /* Delete anyone else's old server. */ ! 110: unlink (server.sun_path); ! 111: #endif ! 112: ! 113: if (bind (s, &server, strlen (server.sun_path) + 2) < 0) ! 114: { ! 115: perror ("bind"); ! 116: exit (1); ! 117: } ! 118: /* ! 119: * Now, just wait for everything to come in.. ! 120: */ ! 121: if (listen (s, 5) < 0) ! 122: { ! 123: perror ("listen"); ! 124: exit (1); ! 125: } ! 126: ! 127: /* Disable sigpipes in case luser kills client... */ ! 128: signal (SIGPIPE, SIG_IGN); ! 129: for (;;) ! 130: { ! 131: int rmask = (1 << s) + 1; ! 132: if (select (s + 1, &rmask, 0, 0, 0) < 0) ! 133: perror ("select"); ! 134: if (rmask & (1 << s)) /* client sends list of filenames */ ! 135: { ! 136: fromlen = sizeof (fromunix); ! 137: fromunix.sun_family = AF_UNIX; ! 138: infd = accept (s, &fromunix, &fromlen); /* open socket fd */ ! 139: if (infd < 0) ! 140: { ! 141: if (errno == EMFILE || errno == ENFILE) ! 142: printf ("Too many clients.\n"); ! 143: else ! 144: perror ("accept"); ! 145: continue; ! 146: } ! 147: ! 148: if (infd >= openfiles_size) ! 149: { ! 150: openfiles_size *= 2; ! 151: openfiles = (FILE **) realloc (openfiles, ! 152: openfiles_size * sizeof (FILE *)); ! 153: if (openfiles == 0) ! 154: abort (); ! 155: } ! 156: ! 157: infile = fdopen (infd, "r+"); /* open stream */ ! 158: if (infile == NULL) ! 159: { ! 160: printf ("Too many clients.\n"); ! 161: write (infd, "Too many clients.\n", 18); ! 162: close (infd); /* Prevent descriptor leak.. */ ! 163: continue; ! 164: } ! 165: str = fgets (string, BUFSIZ, infile); ! 166: if (str == NULL) ! 167: { ! 168: perror ("fgets"); ! 169: close (infd); /* Prevent descriptor leak.. */ ! 170: continue; ! 171: } ! 172: openfiles[infd] = infile; ! 173: printf ("Client: %d %s", infd, string); ! 174: /* If what we read did not end in a newline, ! 175: it means there is more. Keep reading from the socket ! 176: and outputting to Emacs, until we get the newline. */ ! 177: while (string[strlen (string) - 1] != '\n') ! 178: { ! 179: if (fgets (string, BUFSIZ, infile) == 0) ! 180: break; ! 181: printf ("%s", string); ! 182: } ! 183: fflush (stdout); ! 184: fflush (infile); ! 185: continue; ! 186: } ! 187: else if (rmask & 1) /* emacs sends codeword, fd, and string message */ ! 188: { ! 189: /* Read command codeword and fd */ ! 190: clearerr (stdin); ! 191: scanf ("%s %d%*c", code, &infd); ! 192: if (ferror (stdin) || feof (stdin)) ! 193: { ! 194: fprintf (stderr, "server: error reading from standard input\n"); ! 195: exit (1); ! 196: } ! 197: ! 198: /* Transfer text from Emacs to the client, up to a newline. */ ! 199: infile = openfiles[infd]; ! 200: while (1) ! 201: { ! 202: if (fgets (string, BUFSIZ, stdin) == 0) ! 203: break; ! 204: fprintf (infile, "%s", string); ! 205: if (string[strlen (string) - 1] == '\n') ! 206: break; ! 207: } ! 208: fflush (infile); ! 209: ! 210: /* If command is close, close connection to client. */ ! 211: if (strncmp (code, "Close:", 6) == 0) ! 212: if (infd > 2) ! 213: { ! 214: fclose (infile); ! 215: close (infd); ! 216: } ! 217: continue; ! 218: } ! 219: } ! 220: } ! 221: ! 222: #else /* This is the SYSV IPC section */ ! 223: ! 224: #include <sys/types.h> ! 225: #include <sys/ipc.h> ! 226: #include <sys/msg.h> ! 227: #include <setjmp.h> ! 228: ! 229: jmp_buf msgenv; ! 230: ! 231: void /* void here fixes bug on sgi. ! 232: Let's hope this doesn't break other systems. */ ! 233: msgcatch () ! 234: { ! 235: longjmp (msgenv, 1); ! 236: } ! 237: ! 238: ! 239: /* "THIS has to be fixed. Remember, stderr may not exist...-rlk." ! 240: Incorrect. This program runs as an inferior of Emacs. ! 241: Its stderr always exists--rms. */ ! 242: #include <stdio.h> ! 243: ! 244: main () ! 245: { ! 246: int s, infd, fromlen; ! 247: key_t key; ! 248: struct msgbuf * msgp = ! 249: (struct msgbuf *) malloc (sizeof *msgp + BUFSIZ); ! 250: struct msqid_ds msg_st; ! 251: int p; ! 252: char *homedir, *getenv (); ! 253: char string[BUFSIZ]; ! 254: FILE *infile; ! 255: ! 256: /* ! 257: * Create a message queue using ~/.emacs_server as the path for ftok ! 258: */ ! 259: if ((homedir = getenv ("HOME")) == NULL) ! 260: { ! 261: fprintf (stderr,"No home directory\n"); ! 262: exit (1); ! 263: } ! 264: strcpy (string, homedir); ! 265: strcat (string, "/.emacs_server"); ! 266: creat (string, 0600); ! 267: key = ftok (string, 1); /* unlikely to be anyone else using it */ ! 268: s = msgget (key, 0600 | IPC_CREAT); ! 269: if (s == -1) ! 270: { ! 271: perror ("msgget"); ! 272: exit (1); ! 273: } ! 274: ! 275: /* Fork so we can close connection even if parent dies */ ! 276: p = fork (); ! 277: if (setjmp (msgenv)) ! 278: { ! 279: msgctl (s, IPC_RMID, 0); ! 280: kill (p, SIGKILL); ! 281: exit (0); ! 282: } ! 283: signal (SIGTERM, msgcatch); ! 284: signal (SIGINT, msgcatch); ! 285: /* If parent goes away, remove message box and exit */ ! 286: if (p == 0) ! 287: { ! 288: p = getppid (); ! 289: setpgrp (); /* Gnu kills process group on exit */ ! 290: while (1) ! 291: { ! 292: if (kill (p, 0) < 0) ! 293: { ! 294: msgctl (s, IPC_RMID, 0); ! 295: exit (0); ! 296: } ! 297: sleep (10); ! 298: } ! 299: } ! 300: ! 301: while (1) ! 302: { ! 303: if ((fromlen = msgrcv (s, msgp, BUFSIZ - 1, 1, 0)) < 0) ! 304: { ! 305: perror ("msgrcv"); ! 306: exit (1); ! 307: } ! 308: else ! 309: { ! 310: msgctl (s, IPC_STAT, &msg_st); ! 311: strncpy (string, msgp->mtext, fromlen); ! 312: string[fromlen] = 0; /* make sure */ ! 313: /* Newline is part of string.. */ ! 314: printf ("Client: %d %s", s, string); ! 315: fflush (stdout); ! 316: /* Now, wait for a wakeup */ ! 317: fgets (msgp->mtext, BUFSIZ, stdin); ! 318: msgp->mtext[strlen (msgp->mtext)-1] = 0; ! 319: /* strcpy (msgp->mtext, "done");*/ ! 320: msgp->mtype = msg_st.msg_lspid; ! 321: msgsnd (s, msgp, strlen (msgp->mtext)+1, 0); ! 322: } ! 323: } ! 324: } ! 325: ! 326: #endif /* SYSV IPC */ ! 327: ! 328: #endif /* BSD && IPC */ ! 329: ! 330:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.