Annotation of GNUtools/emacs/etc/server.c, revision 1.1

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.