Mercurial > hg > xemacs-beta
diff lib-src/emacsclient.c @ 0:376386a54a3c r19-14
Import from CVS: tag r19-14
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:45:50 +0200 |
parents | |
children | bcdc7deadc19 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib-src/emacsclient.c Mon Aug 13 08:45:50 2007 +0200 @@ -0,0 +1,349 @@ +/* Client process that communicates with GNU Emacs acting as server. + Copyright (C) 1986, 1987, 1993, 1994 Free Software Foundation, Inc. + +This file is part of GNU Emacs. + +GNU Emacs is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Emacs is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Emacs; see the file COPYING. If not, write to +the Free the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* Synched up with: FSF 19.28. */ + +#define NO_SHORTNAMES +#include <../src/config.h> +#undef read +#undef write +#undef open +#undef close +#undef signal + +#if __STDC__ || defined(STDC_HEADERS) +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> /* for creat() */ +#include <string.h> +#endif + +#if !defined(HAVE_SOCKETS) && !defined(HAVE_SYSVIPC) +#include <stdio.h> + +main (argc, argv) + int argc; + char **argv; +{ + fprintf (stderr, "%s: Sorry, the Emacs server is supported only\n", + argv[0]); + fprintf (stderr, "on systems with Berkeley sockets or System V IPC.\n"); + exit (1); +} + +#else /* HAVE_SOCKETS or HAVE_SYSVIPC */ + +#if ! defined (HAVE_SYSVIPC) +/* BSD code is very different from SYSV IPC code */ + +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <sys/stat.h> +#include <stdio.h> +#include <errno.h> + +extern char *strerror (); +extern int errno; + +void +main (argc, argv) + int argc; + char **argv; +{ + char system_name[256]; + int s, i; + FILE *out; + struct sockaddr_un server; + char *cwd, *str; + char string[BUFSIZ]; + + if (argc < 2) + { + fprintf (stderr, "Usage: %s [+linenumber] filename\n", argv[0]); + exit (1); + } + + /* + * Open up an AF_UNIX socket in this person's home directory + */ + + if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) < 0) + { + fprintf (stderr, "%s: ", argv[0]); + perror ("socket"); + exit (1); + } + server.sun_family = AF_UNIX; +#ifndef SERVER_HOME_DIR + { + struct stat statbfr; + + gethostname (system_name, sizeof (system_name)); + sprintf (server.sun_path, "/tmp/esrv%d-%s", (int) geteuid (), system_name); + + if (stat (server.sun_path, &statbfr) == -1) + { + if (errno == ENOENT) + fprintf (stderr, + "Can't find socket; have you started the server?\n"); + else + perror ("stat"); + exit (1); + } + if (statbfr.st_uid != geteuid()) + { + fprintf (stderr, "Illegal socket owner\n"); + exit (1); + } + } +#else + if (getenv ("HOME") == NULL) + { + fprintf (stderr, "%s: No home directory\n", argv[0]); + exit (1); + } + sprintf (server.sun_path, "/tmp/esrv%d", geteuid ()); +#if 0 + strcpy (server.sun_path, getenv ("HOME")); + strcat (server.sun_path, "/.emacs_server"); +#endif +#endif /* SERVER_HOME_DIR */ + if (connect (s, (struct sockaddr *) &server, strlen (server.sun_path) + 2) + < 0) + { + fprintf (stderr, "%s: ", argv[0]); + perror ("connect"); + exit (1); + } + if ((out = (FILE *) fdopen (s, "r+")) == NULL) + { + fprintf (stderr, "%s: ", argv[0]); + perror ("fdopen"); + exit (1); + } + +#ifdef BSD + cwd = (char *) getwd (string); +#else + cwd = (char *) getcwd (string, sizeof (string)); +#endif + + if (cwd == 0) + { + /* getwd puts message in STRING if it fails. */ + fprintf (stderr, "%s: %s (%s)\n", argv[0], string, strerror (errno)); + exit (1); + } + + for (i = 1; i < argc; i++) + { + if (*argv[i] == '+') + { + char *p = argv[i] + 1; + while (*p >= '0' && *p <= '9') p++; + if (*p != 0) + fprintf (out, "%s/", cwd); + } + else if (*argv[i] != '/') + fprintf (out, "%s/", cwd); + fprintf (out, "%s ", argv[i]); + } + fprintf (out, "\n"); + fflush (out); + + printf ("Waiting for Emacs..."); + fflush (stdout); + + rewind (out); /* re-read the output */ + str = fgets (string, BUFSIZ, out); + + /* Now, wait for an answer and print any messages. */ + + while ((str = fgets (string, BUFSIZ, out))) + printf ("%s", str); + + exit (0); +} + +#else /* This is the SYSV IPC section */ + +#include <sys/types.h> +#include <sys/ipc.h> +#include <sys/msg.h> +#include <stdio.h> + +char *getwd (); +#if !__STDC__ && !defined(STDC_HEADERS) +char *getcwd (), *getenv (); +#endif + +void +main (argc, argv) + int argc; + char **argv; +{ + int s; + key_t key; + /* Size of text allocated in MSGP. */ + int size_allocated = BUFSIZ; + /* Amount of text used in MSGP. */ + int used; + struct msgbuf *msgp + = (struct msgbuf *) malloc (sizeof (struct msgbuf) + size_allocated); +#if 0 + struct msqid_ds * msg_st; +#endif /* 0 */ + char *homedir, buf[BUFSIZ]; + char gwdirb[BUFSIZ]; + char *cwd; + char *temp; + char progname[BUFSIZ]; + + strcpy (progname, argv[0]); + + if (argc < 2) + { + fprintf (stderr, "Usage: %s [+linenumber] filename\n", argv[0]); + exit (1); + } + + /* + * Create a message queue using ~/.emacs_server as the path for ftok + */ + if ((homedir = getenv ("HOME")) == NULL) + { + fprintf (stderr, "%s: No home directory\n", argv[0]); + exit (1); + } + strcpy (buf, homedir); + strcat (buf, "/.emacs_server"); + creat (buf, 0600); + key = ftok (buf, 1); /* unlikely to be anyone else using it */ + s = msgget (key, 0600 | IPC_CREAT); + if (s == -1) + { + fprintf (stderr, "%s: ", argv[0]); + perror ("msgget"); + exit (1); + } + + /* Determine working dir, so we can prefix it to all the arguments. */ +#ifdef BSD + temp = getwd (gwdirb); +#else + temp = getcwd (gwdirb, sizeof gwdirb); +#endif + + cwd = gwdirb; + if (temp != 0) + { + /* On some systems, cwd can look like `@machine/...'; + ignore everything before the first slash in such a case. */ + while (*cwd && *cwd != '/') + cwd++; + strcat (cwd, "/"); + } + else + { + fprintf (stderr, cwd); + exit (1); + } + + msgp->mtext[0] = 0; + used = 0; + argc--; argv++; + while (argc) + { + int need_cwd = 0; + char *modified_arg = argv[0]; + if (*modified_arg == '+') + { + char *p = modified_arg + 1; + while (*p >= '0' && *p <= '9') p++; + if (*p != 0) + need_cwd = 1; + } + else if (*modified_arg != '/') + need_cwd = 1; + + if (need_cwd) + used += strlen (cwd); + used += strlen (modified_arg) + 1; + while (used + 2 > size_allocated) + { + size_allocated *= 2; + msgp = (struct msgbuf *) realloc (msgp, + (sizeof (struct msgbuf) + + size_allocated)); + } + if (need_cwd) + strcat (msgp->mtext, cwd); + + strcat (msgp->mtext, modified_arg); + strcat (msgp->mtext, " "); + argv++; argc--; + } + strcat (msgp->mtext, "\n"); +#ifdef HPUX /* HPUX has a bug. */ + if (strlen (msgp->mtext) >= 512) + { + fprintf (stderr, "emacsclient: args too long for msgsnd\n"); + exit (1); + } +#endif + msgp->mtype = 1; + if (msgsnd (s, msgp, strlen (msgp->mtext)+1, 0) < 0) + { + fprintf (stderr, "%s: ", progname); + perror ("msgsnd"); + exit (1); + } + /* + * Now, wait for an answer + */ + printf ("Waiting for Emacs..."); + fflush (stdout); + + msgrcv (s, msgp, BUFSIZ, getpid (), 0); /* wait for anything back */ + strcpy (buf, msgp->mtext); + + printf ("\n%s\n", buf); + exit (0); +} + +#endif /* HAVE_SYSVIPC */ + +#endif /* HAVE_SOCKETS or HAVE_SYSVIPC */ + +#ifndef HAVE_STRERROR +char * +strerror (errnum) + int errnum; +{ + extern char *sys_errlist[]; + extern int sys_nerr; + + if (errnum >= 0 && errnum < sys_nerr) + return sys_errlist[errnum]; + return (char *) "Unknown error"; +} + +#endif /* ! HAVE_STRERROR */