/[emacs]/emacs/lib-src/emacsclient.c
ViewVC logotype

Diff of /emacs/lib-src/emacsclient.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.50 by pj, Sat Dec 29 22:20:06 2001 UTC revision 1.50.4.1 by miles, Fri Apr 4 06:19:54 2003 UTC
# Line 1  Line 1 
1  /* Client process that communicates with GNU Emacs acting as server.  /* Client process that communicates with GNU Emacs acting as server.
2     Copyright (C) 1986, 1987, 1994, 1999, 2000, 2001     Copyright (C) 1986, 1987, 1994, 1999, 2000, 2001, 2003
3     Free Software Foundation, Inc.     Free Software Foundation, Inc.
4    
5  This file is part of GNU Emacs.  This file is part of GNU Emacs.
# Line 57  char *progname; Line 57  char *progname;
57  /* Nonzero means don't wait for a response from Emacs.  --no-wait.  */  /* Nonzero means don't wait for a response from Emacs.  --no-wait.  */
58  int nowait = 0;  int nowait = 0;
59    
60    /* Nonzero means args are expressions to be evaluated.  --eval.  */
61    int eval = 0;
62    
63    /* The display on which Emacs should work.  --display.  */
64    char *display = NULL;
65    
66    /* If non-NULL, the name of an editor to fallback to if the server
67       is not running.  --alternate-editor.   */
68    const char * alternate_editor = NULL;
69    
70  void print_help_and_exit ();  void print_help_and_exit ();
71    
72  struct option longopts[] =  struct option longopts[] =
73  {  {
74    { "no-wait",  no_argument,       NULL, 'n' },    { "no-wait",  no_argument,       NULL, 'n' },
75      { "eval",     no_argument,       NULL, 'e' },
76    { "help",     no_argument,       NULL, 'H' },    { "help",     no_argument,       NULL, 'H' },
77    { "version",  no_argument,       NULL, 'V' },    { "version",  no_argument,       NULL, 'V' },
78    { "alternate-editor",required_argument, NULL, 'a' },    { "alternate-editor", required_argument, NULL, 'a' },
79    { 0 }    { "display",  required_argument, NULL, 'd' },
80      { 0, 0, 0, 0 }
81  };  };
82    
   
 const char * alternate_editor = NULL;  
   
83  /* Decode the options from argv and argc.  /* Decode the options from argv and argc.
84     The global variable `optind' will say how many arguments we used up.  */     The global variable `optind' will say how many arguments we used up.  */
85    
# Line 82  decode_options (argc, argv) Line 91  decode_options (argc, argv)
91    while (1)    while (1)
92      {      {
93        int opt = getopt_long (argc, argv,        int opt = getopt_long (argc, argv,
94                               "VHna:", longopts, 0);                               "VHnea:d:", longopts, 0);
95    
96        if (opt == EOF)        if (opt == EOF)
97          break;          break;
# Line 100  decode_options (argc, argv) Line 109  decode_options (argc, argv)
109            alternate_editor = optarg;            alternate_editor = optarg;
110            break;            break;
111    
112            case 'd':
113              display = optarg;
114              break;
115    
116          case 'n':          case 'n':
117            nowait = 1;            nowait = 1;
118            break;            break;
119    
120            case 'e':
121              eval = 1;
122              break;
123    
124          case 'V':          case 'V':
125            fprintf (stderr, "emacsclient %s\n", VERSION);            printf ("emacsclient %s\n", VERSION);
126            exit (1);            exit (0);
127            break;            break;
128    
129          case 'H':          case 'H':
         default:  
130            print_help_and_exit ();            print_help_and_exit ();
131              break;
132    
133            default:
134              fprintf (stderr, "Try `%s --help' for more information\n", progname);
135              exit (1);
136              break;
137          }          }
138      }      }
139  }  }
# Line 119  decode_options (argc, argv) Line 141  decode_options (argc, argv)
141  void  void
142  print_help_and_exit ()  print_help_and_exit ()
143  {  {
144    fprintf (stderr,    printf (
145             "Usage: %s [-a ALTERNATE-EDITOR] [-n] [--no-wait] [+LINE[:COLUMN]] FILENAME\n",            "Usage: %s [OPTIONS] FILE...\n\
146             progname);  Tell the Emacs server to visit the specified files.\n\
147    fprintf (stderr,  Every FILE can be either just a FILENAME or [+LINE[:COLUMN]] FILENAME.\n\
148             "Or %s --version\n",  \n\
149             progname);  The following OPTIONS are accepted:\n\
150    fprintf (stderr,  -V, --version           Just print a version info and return\n\
151             "Report bugs to bug-gnu-emacs@gnu.org.\n");  -H, --help              Print this usage information message\n\
152    exit (1);  -n, --no-wait           Don't wait for the server to return\n\
153    -e, --eval              Evaluate the FILE arguments as ELisp expressions\n\
154    -d, --display=DISPLAY   Visit the file in the given display\n\
155    -a, --alternate-editor=EDITOR\n\
156                            Editor to fallback to if the server is not running\n\
157    \n\
158    Report bugs to bug-gnu-emacs@gnu.org.\n", progname);
159      exit (0);
160  }  }
161    
162  /* Return a copy of NAME, inserting a &  /* Return a copy of NAME, inserting a &
163     before each &, each space, and any initial -.     before each &, each space, each newline, and any initial -.
164     Change spaces to underscores, too, so that the     Change spaces to underscores, too, so that the
165     return value never contains a space.  */     return value never contains a space.  */
166    
# Line 152  quote_file_name (name) Line 181  quote_file_name (name)
181            *q++ = '_';            *q++ = '_';
182            p++;            p++;
183          }          }
184          else if (*p == '\n')
185            {
186              *q++ = '&';
187              *q++ = 'n';
188              p++;
189            }
190        else        else
191          {          {
192            if (*p == '&' || (*p == '-' && p == name))            if (*p == '&' || (*p == '-' && p == name))
# Line 190  fail (argc, argv) Line 225  fail (argc, argv)
225  {  {
226    if (alternate_editor)    if (alternate_editor)
227      {      {
228        int i = optind -1 ;        int i = optind - 1;
229        execvp (alternate_editor, argv + i);        execvp (alternate_editor, argv + i);
230        return;        return;
231      }      }
# Line 202  fail (argc, argv) Line 237  fail (argc, argv)
237    
238    
239    
240  #if !defined (HAVE_SOCKETS) && !defined (HAVE_SYSVIPC)  #if !defined (HAVE_SOCKETS) || defined (NO_SOCKETS_IN_FILE_SYSTEM)
241    
242  int  int
243  main (argc, argv)  main (argc, argv)
# Line 211  main (argc, argv) Line 246  main (argc, argv)
246  {  {
247    fprintf (stderr, "%s: Sorry, the Emacs server is supported only\n",    fprintf (stderr, "%s: Sorry, the Emacs server is supported only\n",
248             argv[0]);             argv[0]);
249    fprintf (stderr, "on systems with Berkeley sockets or System V IPC.\n");    fprintf (stderr, "on systems with Berkeley sockets.\n");
250    
251    fail (argc, argv);    fail (argc, argv);
252  }  }
253    
254  #else /* HAVE_SOCKETS or HAVE_SYSVIPC */  #else /* HAVE_SOCKETS */
   
 #if defined (HAVE_SOCKETS) && ! defined (NO_SOCKETS_IN_FILE_SYSTEM)  
 /* BSD code is very different from SYSV IPC code */  
255    
256  #include <sys/types.h>  #include <sys/types.h>
257  #include <sys/socket.h>  #include <sys/socket.h>
# Line 257  main (argc, argv) Line 289  main (argc, argv)
289  {  {
290    char *system_name;    char *system_name;
291    int system_name_length;    int system_name_length;
292    int s, i;    int s, i, needlf = 0;
293    FILE *out, *in;    FILE *out, *in;
294    struct sockaddr_un server;    struct sockaddr_un server;
 #ifdef SERVER_HOME_DIR  
   char *homedir;  
 #endif  
295    char *cwd, *str;    char *cwd, *str;
296    char string[BUFSIZ];    char string[BUFSIZ];
297    
# Line 272  main (argc, argv) Line 301  main (argc, argv)
301    decode_options (argc, argv);    decode_options (argc, argv);
302    
303    if (argc - optind < 1)    if (argc - optind < 1)
304      print_help_and_exit ();      {
305          fprintf (stderr, "%s: file name or argument required\n", progname);
306          fprintf (stderr, "Try `%s --help' for more information\n", progname);
307          exit (1);
308        }
309    
310    /*    /*
311     * Open up an AF_UNIX socket in this person's home directory     * Open up an AF_UNIX socket in this person's home directory
# Line 288  main (argc, argv) Line 321  main (argc, argv)
321    server.sun_family = AF_UNIX;    server.sun_family = AF_UNIX;
322    
323    {    {
324        char *dot;
325      system_name_length = 32;      system_name_length = 32;
326    
327      while (1)      while (1)
# Line 303  main (argc, argv) Line 337  main (argc, argv)
337          free (system_name);          free (system_name);
338          system_name_length *= 2;          system_name_length *= 2;
339        }        }
340    
341        /* We always use the non-dotted host name, for simplicity.  */
342        dot = index (system_name, '.');
343        if (dot)
344          *dot = '\0';
345    }    }
346    
 #ifndef SERVER_HOME_DIR  
347    {    {
348      int sock_status = 0;      int sock_status = 0;
349    
# Line 353  main (argc, argv) Line 391  main (argc, argv)
391           /* `stat' failed */           /* `stat' failed */
392           if (errno == ENOENT)           if (errno == ENOENT)
393             fprintf (stderr,             fprintf (stderr,
394                      "%s: can't find socket; have you started the server?\n",                      "%s: can't find socket; have you started the server?\n\
395    To start the server in Emacs, type \"M-x server-start\".\n",
396                      argv[0]);                      argv[0]);
397           else           else
398             fprintf (stderr, "%s: can't stat %s: %s\n",             fprintf (stderr, "%s: can't stat %s: %s\n",
# Line 362  main (argc, argv) Line 401  main (argc, argv)
401           break;           break;
402         }         }
403    }    }
 #else  
   if ((homedir = getenv ("HOME")) == NULL)  
     {  
       fprintf (stderr, "%s: No home directory\n", argv[0]);  
       fail (argc, argv);  
     }  
   strcpy (server.sun_path, homedir);  
   strcat (server.sun_path, "/.emacs-server-");  
   strcat (server.sun_path, system_name);  
 #endif  
404    
405    if (connect (s, (struct sockaddr *) &server, strlen (server.sun_path) + 2)    if (connect (s, (struct sockaddr *) &server, strlen (server.sun_path) + 2)
406        < 0)        < 0)
# Line 401  main (argc, argv) Line 430  main (argc, argv)
430        fail (argc, argv);        fail (argc, argv);
431      }      }
432    
433  #ifdef BSD_SYSTEM  #ifdef HAVE_GETCWD
   cwd = getwd (string);  
 #else  
434    cwd = getcwd (string, sizeof string);    cwd = getcwd (string, sizeof string);
435    #else
436      cwd = getwd (string);
437  #endif  #endif
438    if (cwd == 0)    if (cwd == 0)
439      {      {
440        /* getwd puts message in STRING if it fails.  */        /* getwd puts message in STRING if it fails.  */
441        fprintf (stderr, "%s: %s (%s)\n", argv[0],        fprintf (stderr, "%s: %s (%s)\n", argv[0],
442  #ifdef BSD_SYSTEM  #ifdef HAVE_GETCWD
                string,  
 #else  
443                 "Cannot get current working directory",                 "Cannot get current working directory",
444    #else
445                   string,
446  #endif  #endif
447                 strerror (errno));                 strerror (errno));
448        fail (argc, argv);        fail (argc, argv);
# Line 422  main (argc, argv) Line 451  main (argc, argv)
451    if (nowait)    if (nowait)
452      fprintf (out, "-nowait ");      fprintf (out, "-nowait ");
453    
454      if (eval)
455        fprintf (out, "-eval ");
456    
457      if (display)
458        fprintf (out, "-display %s ", quote_file_name (display));
459    
460    for (i = optind; i < argc; i++)    for (i = optind; i < argc; i++)
461      {      {
462        if (*argv[i] == '+')        if (eval)
463            ; /* Don't prepend any cwd or anything like that.  */
464          else if (*argv[i] == '+')
465          {          {
466            char *p = argv[i] + 1;            char *p = argv[i] + 1;
467            while (isdigit ((unsigned char) *p) || *p == ':') p++;            while (isdigit ((unsigned char) *p) || *p == ':') p++;
# Line 443  main (argc, argv) Line 480  main (argc, argv)
480    if (nowait)    if (nowait)
481      return 0;      return 0;
482    
483    printf ("Waiting for Emacs...");    if (!eval)
   fflush (stdout);  
   
   /* Now, wait for an answer and print any messages.  On some systems,  
      the first line we read will actually be the output we just sent.  
      We can't predict whether that will happen, so if it does, we  
      detect it by recognizing `Client: ' at the beginning.  */  
   
   while ((str = fgets (string, BUFSIZ, in)))  
     printf ("%s", str);  
   
   return 0;  
 }  
   
 #else /* This is the SYSV IPC section */  
   
 #include <sys/types.h>  
 #include <sys/ipc.h>  
 #include <sys/msg.h>  
 #include <sys/utsname.h>  
 #include <stdio.h>  
 #include <errno.h>  
 extern int errno;  
   
 char *getwd (), *getcwd (), *getenv ();  
 struct utsname system_name;  
   
 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);  
   struct msqid_ds * msg_st;  
   char *homedir, buf[BUFSIZ];  
   char gwdirb[BUFSIZ];  
   char *cwd;  
   char *temp;  
   
   progname = argv[0];  
   
   /* Process options.  */  
   decode_options (argc, argv);  
   
   if (argc - optind < 1)  
     print_help_and_exit ();  
   
   /*  
    * 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);  
 #ifndef HAVE_LONG_FILE_NAMES  
   /* If file names are short, we can't fit the host name.  */  
   strcat (buf, "/.emacs-server");  
 #else  
   strcat (buf, "/.emacs-server-");  
   uname (&system_name);  
   strcat (buf, system_name.nodename);  
 #endif  
   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_SYSTEM  
   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  
     {  
 #ifdef BSD_SYSTEM  
       fprintf (stderr, "%s: %s\n", argv[0], cwd);  
 #else  
       fprintf (stderr, "%s: Cannot get current working directory: %s\n",  
                argv[0], strerror (errno));  
 #endif  
       fail (argc, argv);  
     }  
   
   msgp->mtext[0] = 0;  
   used = 0;  
   
   if (nowait)  
484      {      {
485        strcat (msgp->mtext, "-nowait ");        printf ("Waiting for Emacs...");
486        used += 8;        needlf = 2;
487      }      }
488      fflush (stdout);
489    
490    argc -= optind;    /* Now, wait for an answer and print any messages.  */
491    argv += optind;    while ((str = fgets (string, BUFSIZ, in)))
   
   while (argc)  
     {  
       int need_cwd = 0;  
       char *modified_arg = argv[0];  
   
       if (*modified_arg == '+')  
         {  
           char *p = modified_arg + 1;  
           while (isdigit (*p) || *p == ':')  
             p++;  
           if (*p != 0)  
             need_cwd = 1;  
         }  
       else if (*modified_arg != '/')  
         need_cwd = 1;  
   
       modified_arg = quote_file_name (modified_arg);  
   
       if (need_cwd)  
         /* Overestimate in case we have to quote something in CWD.  */  
         used += 2 * 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, quote_file_name (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, "%s: args too long for msgsnd\n", progname);  
       fail (argc, argv);  
     }  
 #endif  
   msgp->mtype = 1;  
   if (msgsnd (s, msgp, strlen (msgp->mtext)+1, 0) < 0)  
492      {      {
493        fprintf (stderr, "%s: ", progname);        if (needlf == 2)
494        perror ("msgsnd");          printf ("\n");
495        fail (argc, argv);        printf ("%s", str);
496          needlf = str[0] == '\0' ? needlf : str[strlen (str) - 1] != '\n';
497      }      }
498    
499    /* Maybe wait for an answer.   */    if (needlf)
500    if (nowait)      printf ("\n");
     return 0;  
   
   printf ("Waiting for Emacs...");  
501    fflush (stdout);    fflush (stdout);
502    
503    msgrcv (s, msgp, BUFSIZ, getpid (), 0);       /* wait for anything back */    return 0;
   strcpy (buf, msgp->mtext);  
   
   printf ("\n");  
   if (*buf)  
     printf ("%s\n", buf);  
   exit (0);  
504  }  }
505    
506  #endif /* HAVE_SYSVIPC */  #endif /* HAVE_SOCKETS */
   
 #endif /* HAVE_SOCKETS or HAVE_SYSVIPC */  
507    
508  #ifndef HAVE_STRERROR  #ifndef HAVE_STRERROR
509  char *  char *

Legend:
Removed from v.1.50  
changed lines
  Added in v.1.50.4.1

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26