home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / emacs-18.59-bin.lha / lib / emacs / 18.59 / etc / server.c < prev    next >
C/C++ Source or Header  |  1992-03-23  |  8KB  |  331 lines

  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.  
  331.