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