diff options
| author | Miles Bader | 2007-08-29 05:28:10 +0000 |
|---|---|---|
| committer | Miles Bader | 2007-08-29 05:28:10 +0000 |
| commit | 8d9cc0b7ea1893059df8788129998e9a71ec07f3 (patch) | |
| tree | 4caa326ed8de37c8c0a859c7071593362832d37e /lib-src | |
| parent | cb5b9015b372175f1fc90cb7ba3f43298c621509 (diff) | |
| parent | 5142de65ce179e846514ec7355274ab22822a85c (diff) | |
| download | emacs-8d9cc0b7ea1893059df8788129998e9a71ec07f3.tar.gz emacs-8d9cc0b7ea1893059df8788129998e9a71ec07f3.zip | |
Merge multi-tty branch
Revision: emacs@sv.gnu.org/emacs--devo--0--patch-866
Diffstat (limited to 'lib-src')
| -rw-r--r-- | lib-src/ChangeLog | 54 | ||||
| -rw-r--r-- | lib-src/emacsclient.c | 805 | ||||
| -rw-r--r-- | lib-src/makefile.w32-in | 2 |
3 files changed, 693 insertions, 168 deletions
diff --git a/lib-src/ChangeLog b/lib-src/ChangeLog index 9d7d076ca46..266453ae975 100644 --- a/lib-src/ChangeLog +++ b/lib-src/ChangeLog | |||
| @@ -1,3 +1,57 @@ | |||
| 1 | 2007-08-29 Dan Nicolaescu <dann@ics.uci.edu> | ||
| 2 | |||
| 3 | * emacsclient.c (w32_execvp): Move definition before use. | ||
| 4 | (decode_options): Don't use a tty on mac carbon or windows. | ||
| 5 | |||
| 6 | 2007-08-29 Jason Rumney <jasonr@gnu.org> | ||
| 7 | |||
| 8 | * emacsclient.c (SEND_STRING, SEND_QUOTED): Remove obfuscation | ||
| 9 | macros. | ||
| 10 | (quote_argument, set_tcp_socket, handle_sigcont, handle_sigtstp): | ||
| 11 | (main): Expand removed macros inline. | ||
| 12 | (main) [WINDOWSNT]: Don't call ttyname. Don't recognize -suspend | ||
| 13 | option. | ||
| 14 | (main) [NO_SOCKETS_IN_FILE_SYSTEM]: Don't call init_signals. | ||
| 15 | |||
| 16 | 2007-08-29 Karoly Lorentey <lorentey@elte.hu> | ||
| 17 | |||
| 18 | * emacsclient.c (signal.h): New include. | ||
| 19 | (sys/stat.h, errno.h): Always include, even on WINDOWSNT. | ||
| 20 | (DIRECTORY_SEP, IS_DIRECTORY_SEP, IS_DEVICE_SEP, IS_ANY_SEP): Copy | ||
| 21 | definitions here from src/lisp.h. | ||
| 22 | (main_argc, main_argv, current_frame, window_system, tty): New | ||
| 23 | variables. | ||
| 24 | (longopts): Add tty, current-frame. | ||
| 25 | (xmalloc, xstrdup): New functions. | ||
| 26 | (get_current_dir_name): New function, copied from src/sysdep.c. | ||
| 27 | (decode_options): Set display from environment. Add tty and | ||
| 28 | current_frame options. Make --no-wait imply --current-frame, | ||
| 29 | except when it is the only option given. Make sure no frame is | ||
| 30 | opened when --current-frame is set. | ||
| 31 | (print_help_and_exit): Document tty and current-frame options. | ||
| 32 | (fail): Change arguments to void. | ||
| 33 | (main): When sockets are not defined, set main_argc, main_argv, | ||
| 34 | and call fail() with no arguments. | ||
| 35 | (emacs_socket): New variable (moved out from main `s'). | ||
| 36 | (quote_file_name): Rename to quote_argument. | ||
| 37 | (quote_argument): New name for old quote_file_name. | ||
| 38 | (unquote_argument, strprefix, pass_signal_to_emacs) | ||
| 39 | (handle_sigcont, handle_sigtstp, init_signals): New functions. | ||
| 40 | (set_local_socket): Initialize saved_errno to 0. If socket-name | ||
| 41 | is too long, call `fail' rather than `exit'. | ||
| 42 | (main): Doc update. Set main_argc, main_argv. New var `str'. | ||
| 43 | Don't need a filename or argument if tty or window_system set. | ||
| 44 | Call fail with no arguments. Use get_current_dir_name to send | ||
| 45 | over the current directory. Send version number to Emacs for | ||
| 46 | verification. If tty is set, check TERM, and pass name and type | ||
| 47 | to Emacs. Pass window_system to Emacs. Move sending of eval to | ||
| 48 | optind loop. Send -position, -file to Emacs. Call fsync after | ||
| 49 | fflush. Check for a client/server version match. Handle | ||
| 50 | -emacs-pid, -window-system-unsupported, -print, -error, -suspend | ||
| 51 | commands. Don't exit prematurely on --no-wait, let Emacs close | ||
| 52 | the connection for us. When creating a new frame, send | ||
| 53 | environment and pwd to Emacs. Send current-frame to Emacs. | ||
| 54 | |||
| 1 | 2007-08-25 Eli Zaretskii <eliz@gnu.org> | 55 | 2007-08-25 Eli Zaretskii <eliz@gnu.org> |
| 2 | 56 | ||
| 3 | * Makefile.in (rcs2log, rcs-checkin, grep-changelog, vcdiff): | 57 | * Makefile.in (rcs2log, rcs-checkin, grep-changelog, vcdiff): |
diff --git a/lib-src/emacsclient.c b/lib-src/emacsclient.c index 9edba132134..ae7ff12e17d 100644 --- a/lib-src/emacsclient.c +++ b/lib-src/emacsclient.c | |||
| @@ -76,7 +76,31 @@ Boston, MA 02110-1301, USA. */ | |||
| 76 | # include <pwd.h> | 76 | # include <pwd.h> |
| 77 | #endif /* not WINDOWSNT */ | 77 | #endif /* not WINDOWSNT */ |
| 78 | #endif /* not VMS */ | 78 | #endif /* not VMS */ |
| 79 | #include <sys/stat.h> | ||
| 79 | 80 | ||
| 81 | #include <signal.h> | ||
| 82 | #include <errno.h> | ||
| 83 | |||
| 84 | /* From lisp.h */ | ||
| 85 | #ifndef DIRECTORY_SEP | ||
| 86 | #define DIRECTORY_SEP '/' | ||
| 87 | #endif | ||
| 88 | #ifndef IS_DIRECTORY_SEP | ||
| 89 | #define IS_DIRECTORY_SEP(_c_) ((_c_) == DIRECTORY_SEP) | ||
| 90 | #endif | ||
| 91 | #ifndef IS_DEVICE_SEP | ||
| 92 | #ifndef DEVICE_SEP | ||
| 93 | #define IS_DEVICE_SEP(_c_) 0 | ||
| 94 | #else | ||
| 95 | #define IS_DEVICE_SEP(_c_) ((_c_) == DEVICE_SEP) | ||
| 96 | #endif | ||
| 97 | #endif | ||
| 98 | #ifndef IS_ANY_SEP | ||
| 99 | #define IS_ANY_SEP(_c_) (IS_DIRECTORY_SEP (_c_)) | ||
| 100 | #endif | ||
| 101 | |||
| 102 | |||
| 103 | |||
| 80 | char *getenv (), *getwd (); | 104 | char *getenv (), *getwd (); |
| 81 | char *(getcwd) (); | 105 | char *(getcwd) (); |
| 82 | 106 | ||
| @@ -84,8 +108,6 @@ char *(getcwd) (); | |||
| 84 | #define VERSION "unspecified" | 108 | #define VERSION "unspecified" |
| 85 | #endif | 109 | #endif |
| 86 | 110 | ||
| 87 | #define SEND_STRING(data) (send_to_emacs (s, (data))) | ||
| 88 | #define SEND_QUOTED(data) (quote_file_name (s, (data))) | ||
| 89 | 111 | ||
| 90 | #ifndef EXIT_SUCCESS | 112 | #ifndef EXIT_SUCCESS |
| 91 | #define EXIT_SUCCESS 0 | 113 | #define EXIT_SUCCESS 0 |
| @@ -110,15 +132,30 @@ char *(getcwd) (); | |||
| 110 | /* Name used to invoke this program. */ | 132 | /* Name used to invoke this program. */ |
| 111 | char *progname; | 133 | char *progname; |
| 112 | 134 | ||
| 135 | /* The first argument to main. */ | ||
| 136 | int main_argc; | ||
| 137 | |||
| 138 | /* The second argument to main. */ | ||
| 139 | char **main_argv; | ||
| 140 | |||
| 113 | /* Nonzero means don't wait for a response from Emacs. --no-wait. */ | 141 | /* Nonzero means don't wait for a response from Emacs. --no-wait. */ |
| 114 | int nowait = 0; | 142 | int nowait = 0; |
| 115 | 143 | ||
| 116 | /* Nonzero means args are expressions to be evaluated. --eval. */ | 144 | /* Nonzero means args are expressions to be evaluated. --eval. */ |
| 117 | int eval = 0; | 145 | int eval = 0; |
| 118 | 146 | ||
| 147 | /* Nonzero means don't open a new frame. --current-frame. */ | ||
| 148 | int current_frame = 0; | ||
| 149 | |||
| 150 | /* Nonzero means open a new graphical frame. */ | ||
| 151 | int window_system = 0; | ||
| 152 | |||
| 119 | /* The display on which Emacs should work. --display. */ | 153 | /* The display on which Emacs should work. --display. */ |
| 120 | char *display = NULL; | 154 | char *display = NULL; |
| 121 | 155 | ||
| 156 | /* Nonzero means open a new Emacs frame on the current terminal. */ | ||
| 157 | int tty = 0; | ||
| 158 | |||
| 122 | /* If non-NULL, the name of an editor to fallback to if the server | 159 | /* If non-NULL, the name of an editor to fallback to if the server |
| 123 | is not running. --alternate-editor. */ | 160 | is not running. --alternate-editor. */ |
| 124 | const char *alternate_editor = NULL; | 161 | const char *alternate_editor = NULL; |
| @@ -140,6 +177,8 @@ struct option longopts[] = | |||
| 140 | { "eval", no_argument, NULL, 'e' }, | 177 | { "eval", no_argument, NULL, 'e' }, |
| 141 | { "help", no_argument, NULL, 'H' }, | 178 | { "help", no_argument, NULL, 'H' }, |
| 142 | { "version", no_argument, NULL, 'V' }, | 179 | { "version", no_argument, NULL, 'V' }, |
| 180 | { "tty", no_argument, NULL, 't' }, | ||
| 181 | { "current-frame", no_argument, NULL, 'c' }, | ||
| 143 | { "alternate-editor", required_argument, NULL, 'a' }, | 182 | { "alternate-editor", required_argument, NULL, 'a' }, |
| 144 | #ifndef NO_SOCKETS_IN_FILE_SYSTEM | 183 | #ifndef NO_SOCKETS_IN_FILE_SYSTEM |
| 145 | { "socket-name", required_argument, NULL, 's' }, | 184 | { "socket-name", required_argument, NULL, 's' }, |
| @@ -149,6 +188,111 @@ struct option longopts[] = | |||
| 149 | { 0, 0, 0, 0 } | 188 | { 0, 0, 0, 0 } |
| 150 | }; | 189 | }; |
| 151 | 190 | ||
| 191 | |||
| 192 | /* Like malloc but get fatal error if memory is exhausted. */ | ||
| 193 | |||
| 194 | long * | ||
| 195 | xmalloc (size) | ||
| 196 | unsigned int size; | ||
| 197 | { | ||
| 198 | long *result = (long *) malloc (size); | ||
| 199 | if (result == NULL) | ||
| 200 | { | ||
| 201 | perror ("malloc"); | ||
| 202 | exit (EXIT_FAILURE); | ||
| 203 | } | ||
| 204 | return result; | ||
| 205 | } | ||
| 206 | |||
| 207 | /* Like strdup but get a fatal error if memory is exhausted. */ | ||
| 208 | |||
| 209 | char * | ||
| 210 | xstrdup (const char *s) | ||
| 211 | { | ||
| 212 | char *result = strdup (s); | ||
| 213 | if (result == NULL) | ||
| 214 | { | ||
| 215 | perror ("strdup"); | ||
| 216 | exit (EXIT_FAILURE); | ||
| 217 | } | ||
| 218 | return result; | ||
| 219 | } | ||
| 220 | |||
| 221 | /* From sysdep.c */ | ||
| 222 | #if !defined (HAVE_GET_CURRENT_DIR_NAME) || defined (BROKEN_GET_CURRENT_DIR_NAME) | ||
| 223 | |||
| 224 | /* Return the current working directory. Returns NULL on errors. | ||
| 225 | Any other returned value must be freed with free. This is used | ||
| 226 | only when get_current_dir_name is not defined on the system. */ | ||
| 227 | char* | ||
| 228 | get_current_dir_name () | ||
| 229 | { | ||
| 230 | char *buf; | ||
| 231 | char *pwd; | ||
| 232 | struct stat dotstat, pwdstat; | ||
| 233 | /* If PWD is accurate, use it instead of calling getwd. PWD is | ||
| 234 | sometimes a nicer name, and using it may avoid a fatal error if a | ||
| 235 | parent directory is searchable but not readable. */ | ||
| 236 | if ((pwd = getenv ("PWD")) != 0 | ||
| 237 | && (IS_DIRECTORY_SEP (*pwd) || (*pwd && IS_DEVICE_SEP (pwd[1]))) | ||
| 238 | && stat (pwd, &pwdstat) == 0 | ||
| 239 | && stat (".", &dotstat) == 0 | ||
| 240 | && dotstat.st_ino == pwdstat.st_ino | ||
| 241 | && dotstat.st_dev == pwdstat.st_dev | ||
| 242 | #ifdef MAXPATHLEN | ||
| 243 | && strlen (pwd) < MAXPATHLEN | ||
| 244 | #endif | ||
| 245 | ) | ||
| 246 | { | ||
| 247 | buf = (char *) xmalloc (strlen (pwd) + 1); | ||
| 248 | if (!buf) | ||
| 249 | return NULL; | ||
| 250 | strcpy (buf, pwd); | ||
| 251 | } | ||
| 252 | #ifdef HAVE_GETCWD | ||
| 253 | else | ||
| 254 | { | ||
| 255 | size_t buf_size = 1024; | ||
| 256 | buf = (char *) xmalloc (buf_size); | ||
| 257 | if (!buf) | ||
| 258 | return NULL; | ||
| 259 | for (;;) | ||
| 260 | { | ||
| 261 | if (getcwd (buf, buf_size) == buf) | ||
| 262 | break; | ||
| 263 | if (errno != ERANGE) | ||
| 264 | { | ||
| 265 | int tmp_errno = errno; | ||
| 266 | free (buf); | ||
| 267 | errno = tmp_errno; | ||
| 268 | return NULL; | ||
| 269 | } | ||
| 270 | buf_size *= 2; | ||
| 271 | buf = (char *) realloc (buf, buf_size); | ||
| 272 | if (!buf) | ||
| 273 | return NULL; | ||
| 274 | } | ||
| 275 | } | ||
| 276 | #else | ||
| 277 | else | ||
| 278 | { | ||
| 279 | /* We need MAXPATHLEN here. */ | ||
| 280 | buf = (char *) xmalloc (MAXPATHLEN + 1); | ||
| 281 | if (!buf) | ||
| 282 | return NULL; | ||
| 283 | if (getwd (buf) == NULL) | ||
| 284 | { | ||
| 285 | int tmp_errno = errno; | ||
| 286 | free (buf); | ||
| 287 | errno = tmp_errno; | ||
| 288 | return NULL; | ||
| 289 | } | ||
| 290 | } | ||
| 291 | #endif | ||
| 292 | return buf; | ||
| 293 | } | ||
| 294 | #endif | ||
| 295 | |||
| 152 | /* Message functions. */ | 296 | /* Message functions. */ |
| 153 | 297 | ||
| 154 | #ifdef WINDOWSNT | 298 | #ifdef WINDOWSNT |
| @@ -165,7 +309,41 @@ w32_window_app () | |||
| 165 | 309 | ||
| 166 | return window_app; | 310 | return window_app; |
| 167 | } | 311 | } |
| 168 | #endif | 312 | |
| 313 | /* | ||
| 314 | execvp wrapper for Windows. Quotes arguments with embedded spaces. | ||
| 315 | |||
| 316 | This is necessary due to the broken implementation of exec* routines in | ||
| 317 | the Microsoft libraries: they concatenate the arguments together without | ||
| 318 | quoting special characters, and pass the result to CreateProcess, with | ||
| 319 | predictably bad results. By contrast, Posix execvp passes the arguments | ||
| 320 | directly into the argv array of the child process. | ||
| 321 | */ | ||
| 322 | int | ||
| 323 | w32_execvp (path, argv) | ||
| 324 | char *path; | ||
| 325 | char **argv; | ||
| 326 | { | ||
| 327 | int i; | ||
| 328 | |||
| 329 | /* Required to allow a .BAT script as alternate editor. */ | ||
| 330 | argv[0] = (char *) alternate_editor; | ||
| 331 | |||
| 332 | for (i = 0; argv[i]; i++) | ||
| 333 | if (strchr (argv[i], ' ')) | ||
| 334 | { | ||
| 335 | char *quoted = alloca (strlen (argv[i]) + 3); | ||
| 336 | sprintf (quoted, "\"%s\"", argv[i]); | ||
| 337 | argv[i] = quoted; | ||
| 338 | } | ||
| 339 | |||
| 340 | return execvp (path, argv); | ||
| 341 | } | ||
| 342 | |||
| 343 | #undef execvp | ||
| 344 | #define execvp w32_execvp | ||
| 345 | |||
| 346 | #endif /* WINDOWSNT */ | ||
| 169 | 347 | ||
| 170 | void | 348 | void |
| 171 | message (int is_error, char *message, ...) | 349 | message (int is_error, char *message, ...) |
| @@ -204,16 +382,19 @@ decode_options (argc, argv) | |||
| 204 | char **argv; | 382 | char **argv; |
| 205 | { | 383 | { |
| 206 | alternate_editor = getenv ("ALTERNATE_EDITOR"); | 384 | alternate_editor = getenv ("ALTERNATE_EDITOR"); |
| 385 | display = getenv ("DISPLAY"); | ||
| 386 | if (display && strlen (display) == 0) | ||
| 387 | display = NULL; | ||
| 207 | 388 | ||
| 208 | while (1) | 389 | while (1) |
| 209 | { | 390 | { |
| 210 | int opt = getopt_long (argc, argv, | 391 | int opt = getopt_long (argc, argv, |
| 211 | #ifndef NO_SOCKETS_IN_FILE_SYSTEM | 392 | #ifndef NO_SOCKETS_IN_FILE_SYSTEM |
| 212 | "VHnea:s:f:d:", | 393 | "VHnea:s:f:d:tc", |
| 213 | #else | 394 | #else |
| 214 | "VHnea:f:d:", | 395 | "VHnea:f:d:tc", |
| 215 | #endif | 396 | #endif |
| 216 | longopts, 0); | 397 | longopts, 0); |
| 217 | 398 | ||
| 218 | if (opt == EOF) | 399 | if (opt == EOF) |
| 219 | break; | 400 | break; |
| @@ -256,6 +437,14 @@ decode_options (argc, argv) | |||
| 256 | exit (EXIT_SUCCESS); | 437 | exit (EXIT_SUCCESS); |
| 257 | break; | 438 | break; |
| 258 | 439 | ||
| 440 | case 't': | ||
| 441 | tty = 1; | ||
| 442 | break; | ||
| 443 | |||
| 444 | case 'c': | ||
| 445 | current_frame = 1; | ||
| 446 | break; | ||
| 447 | |||
| 259 | case 'H': | 448 | case 'H': |
| 260 | print_help_and_exit (); | 449 | print_help_and_exit (); |
| 261 | break; | 450 | break; |
| @@ -266,21 +455,49 @@ decode_options (argc, argv) | |||
| 266 | break; | 455 | break; |
| 267 | } | 456 | } |
| 268 | } | 457 | } |
| 458 | |||
| 459 | if (!tty && display) | ||
| 460 | window_system = 1; | ||
| 461 | #if !defined (WINDOWSNT) && !defined (HAVE_CARBON) | ||
| 462 | else | ||
| 463 | tty = 1; | ||
| 464 | #endif | ||
| 465 | |||
| 466 | /* --no-wait implies --current-frame on ttys when there are file | ||
| 467 | arguments or expressions given. */ | ||
| 468 | if (nowait && tty && argc - optind > 0) | ||
| 469 | current_frame = 1; | ||
| 470 | |||
| 471 | if (current_frame) | ||
| 472 | { | ||
| 473 | tty = 0; | ||
| 474 | window_system = 0; | ||
| 475 | } | ||
| 476 | |||
| 477 | if (tty) | ||
| 478 | window_system = 0; | ||
| 269 | } | 479 | } |
| 270 | 480 | ||
| 481 | |||
| 271 | void | 482 | void |
| 272 | print_help_and_exit () | 483 | print_help_and_exit () |
| 273 | { | 484 | { |
| 485 | /* Spaces and tabs are significant in this message; they're chosen so the | ||
| 486 | message aligns properly both in a tty and in a Windows message box. | ||
| 487 | Please try to preserve them; otherwise the output is very hard to read | ||
| 488 | when using emacsclientw. */ | ||
| 274 | message (FALSE, | 489 | message (FALSE, |
| 275 | "Usage: %s [OPTIONS] FILE...\n\ | 490 | "Usage: %s [OPTIONS] FILE...\n\ |
| 276 | Tell the Emacs server to visit the specified files.\n\ | 491 | Tell the Emacs server to visit the specified files.\n\ |
| 277 | Every FILE can be either just a FILENAME or [+LINE[:COLUMN]] FILENAME.\n\ | 492 | Every FILE can be either just a FILENAME or [+LINE[:COLUMN]] FILENAME.\n\ |
| 278 | \n\ | 493 | \n\ |
| 279 | The following OPTIONS are accepted:\n\ | 494 | The following OPTIONS are accepted:\n\ |
| 280 | \n\ | ||
| 281 | -V, --version Just print version info and return\n\ | 495 | -V, --version Just print version info and return\n\ |
| 282 | -H, --help Print this usage information message\n\ | 496 | -H, --help Print this usage information message\n\ |
| 283 | -e, --eval Evaluate FILE arguments as Lisp expressions\n\ | 497 | -t, --tty Open a new Emacs frame on the current terminal\n\ |
| 498 | -c, --current-frame Do not create a new frame;\n\ | ||
| 499 | use the current Emacs frame\n\ | ||
| 500 | -e, --eval Evaluate the FILE arguments as ELisp expressions\n\ | ||
| 284 | -n, --no-wait Don't wait for the server to return\n\ | 501 | -n, --no-wait Don't wait for the server to return\n\ |
| 285 | -d, --display=DISPLAY Visit the file in the given display\n" | 502 | -d, --display=DISPLAY Visit the file in the given display\n" |
| 286 | #ifndef NO_SOCKETS_IN_FILE_SYSTEM | 503 | #ifndef NO_SOCKETS_IN_FILE_SYSTEM |
| @@ -290,66 +507,26 @@ The following OPTIONS are accepted:\n\ | |||
| 290 | "-f, --server-file=FILENAME\n\ | 507 | "-f, --server-file=FILENAME\n\ |
| 291 | Set filename of the TCP authentication file\n\ | 508 | Set filename of the TCP authentication file\n\ |
| 292 | -a, --alternate-editor=EDITOR\n\ | 509 | -a, --alternate-editor=EDITOR\n\ |
| 293 | Editor to fallback to if server is not running\n\ | 510 | Editor to fallback to if the server is not running\n\ |
| 294 | \n\ | 511 | \n\ |
| 295 | Report bugs to bug-gnu-emacs@gnu.org.\n", progname); | 512 | Report bugs to bug-gnu-emacs@gnu.org.\n", progname); |
| 296 | exit (EXIT_SUCCESS); | 513 | exit (EXIT_SUCCESS); |
| 297 | } | 514 | } |
| 298 | 515 | ||
| 299 | |||
| 300 | #ifdef WINDOWSNT | ||
| 301 | |||
| 302 | /* | ||
| 303 | execvp wrapper for Windows. Quotes arguments with embedded spaces. | ||
| 304 | |||
| 305 | This is necessary due to the broken implementation of exec* routines in | ||
| 306 | the Microsoft libraries: they concatenate the arguments together without | ||
| 307 | quoting special characters, and pass the result to CreateProcess, with | ||
| 308 | predictably bad results. By contrast, Posix execvp passes the arguments | ||
| 309 | directly into the argv array of the child process. | ||
| 310 | */ | ||
| 311 | int | ||
| 312 | w32_execvp (path, argv) | ||
| 313 | char *path; | ||
| 314 | char **argv; | ||
| 315 | { | ||
| 316 | int i; | ||
| 317 | |||
| 318 | /* Required to allow a .BAT script as alternate editor. */ | ||
| 319 | argv[0] = (char *) alternate_editor; | ||
| 320 | |||
| 321 | for (i = 0; argv[i]; i++) | ||
| 322 | if (strchr (argv[i], ' ')) | ||
| 323 | { | ||
| 324 | char *quoted = alloca (strlen (argv[i]) + 3); | ||
| 325 | sprintf (quoted, "\"%s\"", argv[i]); | ||
| 326 | argv[i] = quoted; | ||
| 327 | } | ||
| 328 | |||
| 329 | return execvp (path, argv); | ||
| 330 | } | ||
| 331 | |||
| 332 | #undef execvp | ||
| 333 | #define execvp w32_execvp | ||
| 334 | |||
| 335 | #endif /* WINDOWSNT */ | ||
| 336 | |||
| 337 | /* | 516 | /* |
| 338 | Try to run a different command, or --if no alternate editor is | 517 | Try to run a different command, or --if no alternate editor is |
| 339 | defined-- exit with an errorcode. | 518 | defined-- exit with an errorcode. |
| 340 | */ | 519 | */ |
| 341 | void | 520 | void |
| 342 | fail (argc, argv) | 521 | fail (void) |
| 343 | int argc; | ||
| 344 | char **argv; | ||
| 345 | { | 522 | { |
| 346 | if (alternate_editor) | 523 | if (alternate_editor) |
| 347 | { | 524 | { |
| 348 | int i = optind - 1; | 525 | int i = optind - 1; |
| 349 | 526 | ||
| 350 | execvp (alternate_editor, argv + i); | 527 | execvp (alternate_editor, main_argv + i); |
| 351 | message (TRUE, "%s: error executing alternate editor \"%s\"\n", | 528 | message (TRUE, "%s: error executing alternate editor \"%s\"\n", |
| 352 | progname, alternate_editor); | 529 | progname, alternate_editor); |
| 353 | } | 530 | } |
| 354 | exit (EXIT_FAILURE); | 531 | exit (EXIT_FAILURE); |
| 355 | } | 532 | } |
| @@ -362,10 +539,13 @@ main (argc, argv) | |||
| 362 | int argc; | 539 | int argc; |
| 363 | char **argv; | 540 | char **argv; |
| 364 | { | 541 | { |
| 365 | message (TRUE, "%s: Sorry, the Emacs server is supported only\non systems with Berkely sockets.\n", | 542 | main_argc = argc; |
| 543 | main_argv = argv; | ||
| 544 | progname = argv[0]; | ||
| 545 | message (TRUE, "%s: Sorry, the Emacs server is supported only\n" | ||
| 546 | "on systems with Berkeley sockets.\n", | ||
| 366 | argv[0]); | 547 | argv[0]); |
| 367 | 548 | fail (); | |
| 368 | fail (argc, argv); | ||
| 369 | } | 549 | } |
| 370 | 550 | ||
| 371 | #else /* HAVE_SOCKETS && HAVE_INET_SOCKETS */ | 551 | #else /* HAVE_SOCKETS && HAVE_INET_SOCKETS */ |
| @@ -376,8 +556,6 @@ main (argc, argv) | |||
| 376 | # include <sys/types.h> | 556 | # include <sys/types.h> |
| 377 | # include <sys/socket.h> | 557 | # include <sys/socket.h> |
| 378 | # include <sys/un.h> | 558 | # include <sys/un.h> |
| 379 | # include <sys/stat.h> | ||
| 380 | # include <errno.h> | ||
| 381 | #endif | 559 | #endif |
| 382 | 560 | ||
| 383 | #define AUTH_KEY_LENGTH 64 | 561 | #define AUTH_KEY_LENGTH 64 |
| @@ -389,6 +567,8 @@ extern int errno; | |||
| 389 | /* Buffer to accumulate data to send in TCP connections. */ | 567 | /* Buffer to accumulate data to send in TCP connections. */ |
| 390 | char send_buffer[SEND_BUFFER_SIZE + 1]; | 568 | char send_buffer[SEND_BUFFER_SIZE + 1]; |
| 391 | int sblen = 0; /* Fill pointer for the send buffer. */ | 569 | int sblen = 0; /* Fill pointer for the send buffer. */ |
| 570 | /* Socket used to communicate with the Emacs server process. */ | ||
| 571 | HSOCKET emacs_socket = 0; | ||
| 392 | 572 | ||
| 393 | /* Let's send the data to Emacs when either | 573 | /* Let's send the data to Emacs when either |
| 394 | - the data ends in "\n", or | 574 | - the data ends in "\n", or |
| @@ -429,18 +609,21 @@ send_to_emacs (s, data) | |||
| 429 | } | 609 | } |
| 430 | } | 610 | } |
| 431 | 611 | ||
| 432 | /* In NAME, insert a & before each &, each space, each newline, and | 612 | |
| 613 | /* In STR, insert a & before each &, each space, each newline, and | ||
| 433 | any initial -. Change spaces to underscores, too, so that the | 614 | any initial -. Change spaces to underscores, too, so that the |
| 434 | return value never contains a space. */ | 615 | return value never contains a space. |
| 616 | |||
| 617 | Does not change the string. Outputs the result to STREAM. */ | ||
| 435 | void | 618 | void |
| 436 | quote_file_name (s, name) | 619 | quote_argument (s, str) |
| 437 | HSOCKET s; | 620 | HSOCKET s; |
| 438 | char *name; | 621 | char *str; |
| 439 | { | 622 | { |
| 440 | char *copy = (char *) malloc (strlen (name) * 2 + 1); | 623 | char *copy = (char *) xmalloc (strlen (str) * 2 + 1); |
| 441 | char *p, *q; | 624 | char *p, *q; |
| 442 | 625 | ||
| 443 | p = name; | 626 | p = str; |
| 444 | q = copy; | 627 | q = copy; |
| 445 | while (*p) | 628 | while (*p) |
| 446 | { | 629 | { |
| @@ -458,18 +641,54 @@ quote_file_name (s, name) | |||
| 458 | } | 641 | } |
| 459 | else | 642 | else |
| 460 | { | 643 | { |
| 461 | if (*p == '&' || (*p == '-' && p == name)) | 644 | if (*p == '&' || (*p == '-' && p == str)) |
| 462 | *q++ = '&'; | 645 | *q++ = '&'; |
| 463 | *q++ = *p++; | 646 | *q++ = *p++; |
| 464 | } | 647 | } |
| 465 | } | 648 | } |
| 466 | *q++ = 0; | 649 | *q++ = 0; |
| 467 | 650 | ||
| 468 | SEND_STRING (copy); | 651 | send_to_emacs (s, copy); |
| 469 | 652 | ||
| 470 | free (copy); | 653 | free (copy); |
| 471 | } | 654 | } |
| 472 | 655 | ||
| 656 | |||
| 657 | /* The inverse of quote_argument. Removes quoting in string STR by | ||
| 658 | modifying the string in place. Returns STR. */ | ||
| 659 | |||
| 660 | char * | ||
| 661 | unquote_argument (str) | ||
| 662 | char *str; | ||
| 663 | { | ||
| 664 | char *p, *q; | ||
| 665 | |||
| 666 | if (! str) | ||
| 667 | return str; | ||
| 668 | |||
| 669 | p = str; | ||
| 670 | q = str; | ||
| 671 | while (*p) | ||
| 672 | { | ||
| 673 | if (*p == '&') | ||
| 674 | { | ||
| 675 | p++; | ||
| 676 | if (*p == '&') | ||
| 677 | *p = '&'; | ||
| 678 | else if (*p == '_') | ||
| 679 | *p = ' '; | ||
| 680 | else if (*p == 'n') | ||
| 681 | *p = '\n'; | ||
| 682 | else if (*p == '-') | ||
| 683 | *p = '-'; | ||
| 684 | } | ||
| 685 | *q++ = *p++; | ||
| 686 | } | ||
| 687 | *q = 0; | ||
| 688 | return str; | ||
| 689 | } | ||
| 690 | |||
| 691 | |||
| 473 | int | 692 | int |
| 474 | file_name_absolute_p (filename) | 693 | file_name_absolute_p (filename) |
| 475 | const unsigned char *filename; | 694 | const unsigned char *filename; |
| @@ -551,6 +770,7 @@ initialize_sockets () | |||
| 551 | atexit (close_winsock); | 770 | atexit (close_winsock); |
| 552 | } | 771 | } |
| 553 | #endif /* WINDOWSNT */ | 772 | #endif /* WINDOWSNT */ |
| 773 | |||
| 554 | 774 | ||
| 555 | /* | 775 | /* |
| 556 | * Read the information needed to set up a TCP comm channel with | 776 | * Read the information needed to set up a TCP comm channel with |
| @@ -661,13 +881,32 @@ set_tcp_socket () | |||
| 661 | */ | 881 | */ |
| 662 | auth_string[AUTH_KEY_LENGTH] = '\0'; | 882 | auth_string[AUTH_KEY_LENGTH] = '\0'; |
| 663 | 883 | ||
| 664 | SEND_STRING ("-auth "); | 884 | send_to_emacs (s, "-auth "); |
| 665 | SEND_STRING (auth_string); | 885 | send_to_emacs (s, auth_string); |
| 666 | SEND_STRING ("\n"); | 886 | send_to_emacs (s, "\n"); |
| 667 | 887 | ||
| 668 | return s; | 888 | return s; |
| 669 | } | 889 | } |
| 670 | 890 | ||
| 891 | |||
| 892 | /* Returns 1 if PREFIX is a prefix of STRING. */ | ||
| 893 | static int | ||
| 894 | strprefix (char *prefix, char *string) | ||
| 895 | { | ||
| 896 | int i; | ||
| 897 | if (! prefix) | ||
| 898 | return 1; | ||
| 899 | |||
| 900 | if (!string) | ||
| 901 | return 0; | ||
| 902 | |||
| 903 | for (i = 0; prefix[i]; i++) | ||
| 904 | if (!string[i] || string[i] != prefix[i]) | ||
| 905 | return 0; | ||
| 906 | return 1; | ||
| 907 | } | ||
| 908 | |||
| 909 | |||
| 671 | #if !defined (NO_SOCKETS_IN_FILE_SYSTEM) | 910 | #if !defined (NO_SOCKETS_IN_FILE_SYSTEM) |
| 672 | 911 | ||
| 673 | /* Three possibilities: | 912 | /* Three possibilities: |
| @@ -690,6 +929,93 @@ socket_status (socket_name) | |||
| 690 | return 0; | 929 | return 0; |
| 691 | } | 930 | } |
| 692 | 931 | ||
| 932 | |||
| 933 | /* A signal handler that passes the signal to the Emacs process. | ||
| 934 | Useful for SIGWINCH. */ | ||
| 935 | |||
| 936 | SIGTYPE | ||
| 937 | pass_signal_to_emacs (int signalnum) | ||
| 938 | { | ||
| 939 | int old_errno = errno; | ||
| 940 | |||
| 941 | if (emacs_pid) | ||
| 942 | kill (emacs_pid, signalnum); | ||
| 943 | |||
| 944 | signal (signalnum, pass_signal_to_emacs); | ||
| 945 | errno = old_errno; | ||
| 946 | } | ||
| 947 | |||
| 948 | /* Signal handler for SIGCONT; notify the Emacs process that it can | ||
| 949 | now resume our tty frame. */ | ||
| 950 | |||
| 951 | SIGTYPE | ||
| 952 | handle_sigcont (int signalnum) | ||
| 953 | { | ||
| 954 | int old_errno = errno; | ||
| 955 | |||
| 956 | if (tcgetpgrp (1) == getpgrp ()) | ||
| 957 | { | ||
| 958 | /* We are in the foreground. */ | ||
| 959 | send_to_emacs (emacs_socket, "-resume \n"); | ||
| 960 | } | ||
| 961 | else | ||
| 962 | { | ||
| 963 | /* We are in the background; cancel the continue. */ | ||
| 964 | kill (getpid (), SIGSTOP); | ||
| 965 | } | ||
| 966 | |||
| 967 | signal (signalnum, handle_sigcont); | ||
| 968 | errno = old_errno; | ||
| 969 | } | ||
| 970 | |||
| 971 | /* Signal handler for SIGTSTP; notify the Emacs process that we are | ||
| 972 | going to sleep. Normally the suspend is initiated by Emacs via | ||
| 973 | server-handle-suspend-tty, but if the server gets out of sync with | ||
| 974 | reality, we may get a SIGTSTP on C-z. Handling this signal and | ||
| 975 | notifying Emacs about it should get things under control again. */ | ||
| 976 | |||
| 977 | SIGTYPE | ||
| 978 | handle_sigtstp (int signalnum) | ||
| 979 | { | ||
| 980 | int old_errno = errno; | ||
| 981 | sigset_t set; | ||
| 982 | |||
| 983 | if (emacs_socket) | ||
| 984 | send_to_emacs (emacs_socket, "-suspend \n"); | ||
| 985 | |||
| 986 | /* Unblock this signal and call the default handler by temprarily | ||
| 987 | changing the handler and resignalling. */ | ||
| 988 | sigprocmask (SIG_BLOCK, NULL, &set); | ||
| 989 | sigdelset (&set, signalnum); | ||
| 990 | signal (signalnum, SIG_DFL); | ||
| 991 | kill (getpid (), signalnum); | ||
| 992 | sigprocmask (SIG_SETMASK, &set, NULL); /* Let's the above signal through. */ | ||
| 993 | signal (signalnum, handle_sigtstp); | ||
| 994 | |||
| 995 | errno = old_errno; | ||
| 996 | } | ||
| 997 | /* Set up signal handlers before opening a frame on the current tty. */ | ||
| 998 | |||
| 999 | void | ||
| 1000 | init_signals (void) | ||
| 1001 | { | ||
| 1002 | /* Set up signal handlers. */ | ||
| 1003 | signal (SIGWINCH, pass_signal_to_emacs); | ||
| 1004 | |||
| 1005 | /* Don't pass SIGINT and SIGQUIT to Emacs, because it has no way of | ||
| 1006 | deciding which terminal the signal came from. C-g is now a | ||
| 1007 | normal input event on secondary terminals. */ | ||
| 1008 | #if 0 | ||
| 1009 | signal (SIGINT, pass_signal_to_emacs); | ||
| 1010 | signal (SIGQUIT, pass_signal_to_emacs); | ||
| 1011 | #endif | ||
| 1012 | |||
| 1013 | signal (SIGCONT, handle_sigcont); | ||
| 1014 | signal (SIGTSTP, handle_sigtstp); | ||
| 1015 | signal (SIGTTOU, handle_sigtstp); | ||
| 1016 | } | ||
| 1017 | |||
| 1018 | |||
| 693 | HSOCKET | 1019 | HSOCKET |
| 694 | set_local_socket () | 1020 | set_local_socket () |
| 695 | { | 1021 | { |
| @@ -711,30 +1037,31 @@ set_local_socket () | |||
| 711 | { | 1037 | { |
| 712 | int sock_status = 0; | 1038 | int sock_status = 0; |
| 713 | int default_sock = !socket_name; | 1039 | int default_sock = !socket_name; |
| 714 | int saved_errno; | 1040 | int saved_errno = 0; |
| 1041 | |||
| 715 | char *server_name = "server"; | 1042 | char *server_name = "server"; |
| 716 | 1043 | ||
| 717 | if (socket_name && !index (socket_name, '/') && !index (socket_name, '\\')) | 1044 | if (socket_name && !index (socket_name, '/') && !index (socket_name, '\\')) |
| 718 | { /* socket_name is a file name component. */ | 1045 | { /* socket_name is a file name component. */ |
| 719 | server_name = socket_name; | 1046 | server_name = socket_name; |
| 720 | socket_name = NULL; | 1047 | socket_name = NULL; |
| 721 | default_sock = 1; /* Try both UIDs. */ | 1048 | default_sock = 1; /* Try both UIDs. */ |
| 722 | } | 1049 | } |
| 723 | 1050 | ||
| 724 | if (default_sock) | 1051 | if (default_sock) |
| 725 | { | 1052 | { |
| 726 | socket_name = alloca (100 + strlen (server_name)); | 1053 | socket_name = alloca (100 + strlen (server_name)); |
| 727 | sprintf (socket_name, "/tmp/emacs%d/%s", | 1054 | sprintf (socket_name, "/tmp/emacs%d/%s", |
| 728 | (int) geteuid (), server_name); | 1055 | (int) geteuid (), server_name); |
| 729 | } | 1056 | } |
| 730 | 1057 | ||
| 731 | if (strlen (socket_name) < sizeof (server.sun_path)) | 1058 | if (strlen (socket_name) < sizeof (server.sun_path)) |
| 732 | strcpy (server.sun_path, socket_name); | 1059 | strcpy (server.sun_path, socket_name); |
| 733 | else | 1060 | else |
| 734 | { | 1061 | { |
| 735 | message (TRUE, "%s: socket-name %s too long", | 1062 | message (TRUE, "%s: socket-name %s too long", |
| 736 | progname, socket_name); | 1063 | progname, socket_name); |
| 737 | exit (EXIT_FAILURE); | 1064 | fail (); |
| 738 | } | 1065 | } |
| 739 | 1066 | ||
| 740 | /* See if the socket exists, and if it's owned by us. */ | 1067 | /* See if the socket exists, and if it's owned by us. */ |
| @@ -773,7 +1100,7 @@ set_local_socket () | |||
| 773 | } | 1100 | } |
| 774 | 1101 | ||
| 775 | sock_status = socket_status (server.sun_path); | 1102 | sock_status = socket_status (server.sun_path); |
| 776 | saved_errno = errno; | 1103 | saved_errno = errno; |
| 777 | } | 1104 | } |
| 778 | else | 1105 | else |
| 779 | errno = saved_errno; | 1106 | errno = saved_errno; |
| @@ -783,26 +1110,26 @@ set_local_socket () | |||
| 783 | switch (sock_status) | 1110 | switch (sock_status) |
| 784 | { | 1111 | { |
| 785 | case 1: | 1112 | case 1: |
| 786 | /* There's a socket, but it isn't owned by us. This is OK if | 1113 | /* There's a socket, but it isn't owned by us. This is OK if |
| 787 | we are root. */ | 1114 | we are root. */ |
| 788 | if (0 != geteuid ()) | 1115 | if (0 != geteuid ()) |
| 789 | { | 1116 | { |
| 790 | message (TRUE, "%s: Invalid socket owner\n", progname); | 1117 | message (TRUE, "%s: Invalid socket owner\n", progname); |
| 791 | return INVALID_SOCKET; | 1118 | return INVALID_SOCKET; |
| 792 | } | 1119 | } |
| 793 | break; | 1120 | break; |
| 794 | 1121 | ||
| 795 | case 2: | 1122 | case 2: |
| 796 | /* `stat' failed */ | 1123 | /* `stat' failed */ |
| 797 | if (saved_errno == ENOENT) | 1124 | if (saved_errno == ENOENT) |
| 798 | message (TRUE, | 1125 | message (TRUE, |
| 799 | "%s: can't find socket; have you started the server?\n\ | 1126 | "%s: can't find socket; have you started the server?\n\ |
| 800 | To start the server in Emacs, type \"M-x server-start\".\n", | 1127 | To start the server in Emacs, type \"M-x server-start\".\n", |
| 801 | progname); | 1128 | progname); |
| 802 | else | 1129 | else |
| 803 | message (TRUE, "%s: can't stat %s: %s\n", | 1130 | message (TRUE, "%s: can't stat %s: %s\n", |
| 804 | progname, server.sun_path, strerror (saved_errno)); | 1131 | progname, server.sun_path, strerror (saved_errno)); |
| 805 | return INVALID_SOCKET; | 1132 | return INVALID_SOCKET; |
| 806 | } | 1133 | } |
| 807 | } | 1134 | } |
| 808 | 1135 | ||
| @@ -830,10 +1157,9 @@ set_socket () | |||
| 830 | { | 1157 | { |
| 831 | s = set_local_socket (); | 1158 | s = set_local_socket (); |
| 832 | if ((s != INVALID_SOCKET) || alternate_editor) | 1159 | if ((s != INVALID_SOCKET) || alternate_editor) |
| 833 | return s; | 1160 | return s; |
| 834 | |||
| 835 | message (TRUE, "%s: error accessing socket \"%s\"", | 1161 | message (TRUE, "%s: error accessing socket \"%s\"", |
| 836 | progname, socket_name); | 1162 | progname, socket_name); |
| 837 | exit (EXIT_FAILURE); | 1163 | exit (EXIT_FAILURE); |
| 838 | } | 1164 | } |
| 839 | #endif | 1165 | #endif |
| @@ -846,10 +1172,10 @@ set_socket () | |||
| 846 | { | 1172 | { |
| 847 | s = set_tcp_socket (); | 1173 | s = set_tcp_socket (); |
| 848 | if ((s != INVALID_SOCKET) || alternate_editor) | 1174 | if ((s != INVALID_SOCKET) || alternate_editor) |
| 849 | return s; | 1175 | return s; |
| 850 | 1176 | ||
| 851 | message (TRUE, "%s: error accessing server file \"%s\"", | 1177 | message (TRUE, "%s: error accessing server file \"%s\"", |
| 852 | progname, server_file); | 1178 | progname, server_file); |
| 853 | exit (EXIT_FAILURE); | 1179 | exit (EXIT_FAILURE); |
| 854 | } | 1180 | } |
| 855 | 1181 | ||
| @@ -938,129 +1264,274 @@ main (argc, argv) | |||
| 938 | int argc; | 1264 | int argc; |
| 939 | char **argv; | 1265 | char **argv; |
| 940 | { | 1266 | { |
| 941 | HSOCKET s; | ||
| 942 | int i, rl, needlf = 0; | 1267 | int i, rl, needlf = 0; |
| 943 | char *cwd; | 1268 | char *cwd, *str; |
| 944 | char string[BUFSIZ+1]; | 1269 | char string[BUFSIZ+1]; |
| 945 | 1270 | ||
| 1271 | main_argc = argc; | ||
| 1272 | main_argv = argv; | ||
| 946 | progname = argv[0]; | 1273 | progname = argv[0]; |
| 947 | 1274 | ||
| 948 | /* Process options. */ | 1275 | /* Process options. */ |
| 949 | decode_options (argc, argv); | 1276 | decode_options (argc, argv); |
| 950 | 1277 | ||
| 951 | if ((argc - optind < 1) && !eval) | 1278 | if ((argc - optind < 1) && !eval && !tty && !window_system) |
| 952 | { | 1279 | { |
| 953 | message (TRUE, "%s: file name or argument required\nTry `%s --help' for more information\n", | 1280 | message (TRUE, "%s: file name or argument required\n" |
| 954 | progname, progname); | 1281 | "Try `%s --help' for more information\n", |
| 1282 | progname, progname); | ||
| 955 | exit (EXIT_FAILURE); | 1283 | exit (EXIT_FAILURE); |
| 956 | } | 1284 | } |
| 957 | 1285 | ||
| 958 | if ((s = set_socket ()) == INVALID_SOCKET) | 1286 | if ((emacs_socket = set_socket ()) == INVALID_SOCKET) |
| 959 | fail (argc, argv); | 1287 | fail (); |
| 960 | 1288 | ||
| 961 | #ifdef HAVE_GETCWD | 1289 | |
| 962 | cwd = getcwd (string, sizeof string); | 1290 | cwd = get_current_dir_name (); |
| 963 | #else | ||
| 964 | cwd = getwd (string); | ||
| 965 | #endif | ||
| 966 | if (cwd == 0) | 1291 | if (cwd == 0) |
| 967 | { | 1292 | { |
| 968 | /* getwd puts message in STRING if it fails. */ | 1293 | /* getwd puts message in STRING if it fails. */ |
| 969 | message (TRUE, "%s: %s (%s)\n", progname, | 1294 | message (TRUE, "%s: %s\n", progname, |
| 970 | #ifdef HAVE_GETCWD | 1295 | "Cannot get current working directory"); |
| 971 | "Cannot get current working directory", | 1296 | fail (); |
| 972 | #else | ||
| 973 | string, | ||
| 974 | #endif | ||
| 975 | strerror (errno)); | ||
| 976 | fail (argc, argv); | ||
| 977 | } | 1297 | } |
| 978 | 1298 | ||
| 979 | #ifdef WINDOWSNT | 1299 | #ifdef WINDOWSNT |
| 980 | w32_give_focus (); | 1300 | w32_give_focus (); |
| 981 | #endif | 1301 | #endif |
| 982 | 1302 | ||
| 1303 | /* First of all, send our version number for verification. */ | ||
| 1304 | send_to_emacs (emacs_socket, "-version "); | ||
| 1305 | send_to_emacs (emacs_socket, VERSION); | ||
| 1306 | send_to_emacs (emacs_socket, " "); | ||
| 1307 | |||
| 1308 | /* Send over our environment. */ | ||
| 1309 | if (!current_frame) | ||
| 1310 | { | ||
| 1311 | extern char **environ; | ||
| 1312 | int i; | ||
| 1313 | for (i = 0; environ[i]; i++) | ||
| 1314 | { | ||
| 1315 | char *name = xstrdup (environ[i]); | ||
| 1316 | char *value = strchr (name, '='); | ||
| 1317 | send_to_emacs (emacs_socket, "-env "); | ||
| 1318 | quote_argument (emacs_socket, environ[i]); | ||
| 1319 | send_to_emacs (emacs_socket, " "); | ||
| 1320 | } | ||
| 1321 | } | ||
| 1322 | |||
| 1323 | /* Send over our current directory. */ | ||
| 1324 | if (!current_frame) | ||
| 1325 | { | ||
| 1326 | send_to_emacs (emacs_socket, "-dir "); | ||
| 1327 | quote_argument (emacs_socket, cwd); | ||
| 1328 | send_to_emacs (emacs_socket, "/"); | ||
| 1329 | send_to_emacs (emacs_socket, " "); | ||
| 1330 | } | ||
| 1331 | |||
| 1332 | retry: | ||
| 983 | if (nowait) | 1333 | if (nowait) |
| 984 | SEND_STRING ("-nowait "); | 1334 | send_to_emacs (emacs_socket, "-nowait "); |
| 985 | 1335 | ||
| 986 | if (eval) | 1336 | if (current_frame) |
| 987 | SEND_STRING ("-eval "); | 1337 | send_to_emacs (emacs_socket, "-current-frame "); |
| 988 | 1338 | ||
| 989 | if (display) | 1339 | if (display) |
| 990 | { | 1340 | { |
| 991 | SEND_STRING ("-display "); | 1341 | send_to_emacs (emacs_socket, "-display "); |
| 992 | SEND_QUOTED (display); | 1342 | quote_argument (emacs_socket, display); |
| 993 | SEND_STRING (" "); | 1343 | send_to_emacs (emacs_socket, " "); |
| 1344 | } | ||
| 1345 | |||
| 1346 | if (tty) | ||
| 1347 | { | ||
| 1348 | char *type = getenv ("TERM"); | ||
| 1349 | char *tty_name = NULL; | ||
| 1350 | #ifndef WINDOWSNT | ||
| 1351 | tty_name = ttyname (fileno (stdin)); | ||
| 1352 | #endif | ||
| 1353 | |||
| 1354 | if (! tty_name) | ||
| 1355 | { | ||
| 1356 | message (TRUE, "%s: could not get terminal name\n", progname); | ||
| 1357 | fail (); | ||
| 1358 | } | ||
| 1359 | |||
| 1360 | if (! type) | ||
| 1361 | { | ||
| 1362 | message (TRUE, "%s: please set the TERM variable to your terminal type\n", | ||
| 1363 | progname); | ||
| 1364 | fail (); | ||
| 1365 | } | ||
| 1366 | |||
| 1367 | if (! strcmp (type, "eterm")) | ||
| 1368 | { | ||
| 1369 | /* This causes nasty, MULTI_KBOARD-related input lockouts. */ | ||
| 1370 | message (TRUE, "%s: opening a frame in an Emacs term buffer" | ||
| 1371 | " is not supported\n", progname); | ||
| 1372 | fail (); | ||
| 1373 | } | ||
| 1374 | #if !defined (NO_SOCKETS_IN_FILE_SYSTEM) | ||
| 1375 | init_signals (); | ||
| 1376 | #endif | ||
| 1377 | |||
| 1378 | send_to_emacs (emacs_socket, "-tty "); | ||
| 1379 | quote_argument (emacs_socket, tty_name); | ||
| 1380 | send_to_emacs (emacs_socket, " "); | ||
| 1381 | quote_argument (emacs_socket, type); | ||
| 1382 | send_to_emacs (emacs_socket, " "); | ||
| 994 | } | 1383 | } |
| 995 | 1384 | ||
| 1385 | if (window_system) | ||
| 1386 | send_to_emacs (emacs_socket, "-window-system "); | ||
| 1387 | |||
| 996 | if ((argc - optind > 0)) | 1388 | if ((argc - optind > 0)) |
| 997 | { | 1389 | { |
| 998 | for (i = optind; i < argc; i++) | 1390 | for (i = optind; i < argc; i++) |
| 999 | { | 1391 | { |
| 1392 | int relative = 0; | ||
| 1393 | |||
| 1000 | if (eval) | 1394 | if (eval) |
| 1001 | ; /* Don't prepend any cwd or anything like that. */ | 1395 | { |
| 1002 | else if (*argv[i] == '+') | 1396 | /* Don't prepend cwd or anything like that. */ |
| 1003 | { | 1397 | send_to_emacs (emacs_socket, "-eval "); |
| 1398 | quote_argument (emacs_socket, argv[i]); | ||
| 1399 | send_to_emacs (emacs_socket, " "); | ||
| 1400 | continue; | ||
| 1401 | } | ||
| 1402 | |||
| 1403 | if (*argv[i] == '+') | ||
| 1404 | { | ||
| 1004 | char *p = argv[i] + 1; | 1405 | char *p = argv[i] + 1; |
| 1005 | while (isdigit ((unsigned char) *p) || *p == ':') p++; | 1406 | while (isdigit ((unsigned char) *p) || *p == ':') p++; |
| 1006 | if (*p != 0) | 1407 | if (*p == 0) |
| 1007 | { | 1408 | { |
| 1008 | SEND_QUOTED (cwd); | 1409 | send_to_emacs (emacs_socket, "-position "); |
| 1009 | SEND_STRING ("/"); | 1410 | quote_argument (emacs_socket, argv[i]); |
| 1010 | } | 1411 | send_to_emacs (emacs_socket, " "); |
| 1011 | } | 1412 | continue; |
| 1413 | } | ||
| 1414 | else | ||
| 1415 | relative = 1; | ||
| 1416 | } | ||
| 1012 | else if (! file_name_absolute_p (argv[i])) | 1417 | else if (! file_name_absolute_p (argv[i])) |
| 1013 | { | 1418 | relative = 1; |
| 1014 | SEND_QUOTED (cwd); | 1419 | |
| 1015 | SEND_STRING ("/"); | 1420 | send_to_emacs (emacs_socket, "-file "); |
| 1016 | } | 1421 | if (relative) |
| 1017 | 1422 | { | |
| 1018 | SEND_QUOTED (argv[i]); | 1423 | quote_argument (emacs_socket, cwd); |
| 1019 | SEND_STRING (" "); | 1424 | send_to_emacs (emacs_socket, "/"); |
| 1020 | } | 1425 | } |
| 1426 | quote_argument (emacs_socket, argv[i]); | ||
| 1427 | send_to_emacs (emacs_socket, " "); | ||
| 1428 | } | ||
| 1021 | } | 1429 | } |
| 1022 | else | 1430 | else |
| 1023 | { | 1431 | { |
| 1024 | while (fgets (string, BUFSIZ, stdin)) | 1432 | if (!tty && !window_system) |
| 1025 | { | 1433 | { |
| 1026 | SEND_QUOTED (string); | 1434 | while ((str = fgets (string, BUFSIZ, stdin))) |
| 1027 | } | 1435 | { |
| 1028 | SEND_STRING (" "); | 1436 | if (eval) |
| 1437 | send_to_emacs (emacs_socket, "-eval "); | ||
| 1438 | else | ||
| 1439 | send_to_emacs (emacs_socket, "-file "); | ||
| 1440 | quote_argument (emacs_socket, str); | ||
| 1441 | } | ||
| 1442 | send_to_emacs (emacs_socket, " "); | ||
| 1443 | } | ||
| 1029 | } | 1444 | } |
| 1030 | 1445 | ||
| 1031 | SEND_STRING ("\n"); | 1446 | send_to_emacs (emacs_socket, "\n"); |
| 1032 | 1447 | ||
| 1033 | /* Maybe wait for an answer. */ | 1448 | /* Wait for an answer. */ |
| 1034 | if (!nowait) | 1449 | if (!eval && !tty && !nowait) |
| 1035 | { | 1450 | { |
| 1036 | if (!eval) | 1451 | printf ("Waiting for Emacs..."); |
| 1452 | needlf = 2; | ||
| 1453 | } | ||
| 1454 | fflush (stdout); | ||
| 1455 | fsync (1); | ||
| 1456 | |||
| 1457 | /* Now, wait for an answer and print any messages. */ | ||
| 1458 | while ((rl = recv (emacs_socket, string, BUFSIZ, 0)) > 0) | ||
| 1459 | { | ||
| 1460 | char *p; | ||
| 1461 | string[rl] = '\0'; | ||
| 1462 | |||
| 1463 | p = string + strlen (string) - 1; | ||
| 1464 | while (p > string && *p == '\n') | ||
| 1465 | *p-- = 0; | ||
| 1466 | |||
| 1467 | if (strprefix ("-good-version ", string)) | ||
| 1037 | { | 1468 | { |
| 1038 | printf ("Waiting for Emacs..."); | 1469 | /* -good-version: The versions match. */ |
| 1039 | needlf = 2; | ||
| 1040 | } | 1470 | } |
| 1041 | fflush (stdout); | 1471 | else if (strprefix ("-emacs-pid ", string)) |
| 1042 | 1472 | { | |
| 1043 | /* Now, wait for an answer and print any messages. */ | 1473 | /* -emacs-pid PID: The process id of the Emacs process. */ |
| 1044 | while ((rl = recv (s, string, BUFSIZ, 0)) > 0) | 1474 | emacs_pid = strtol (string + strlen ("-emacs-pid"), NULL, 10); |
| 1475 | } | ||
| 1476 | else if (strprefix ("-window-system-unsupported ", string)) | ||
| 1045 | { | 1477 | { |
| 1046 | string[rl] = '\0'; | 1478 | /* -window-system-unsupported: Emacs was compiled without X |
| 1047 | if (needlf == 2) | 1479 | support. Try again on the terminal. */ |
| 1480 | window_system = 0; | ||
| 1481 | nowait = 0; | ||
| 1482 | tty = 1; | ||
| 1483 | goto retry; | ||
| 1484 | } | ||
| 1485 | else if (strprefix ("-print ", string)) | ||
| 1486 | { | ||
| 1487 | /* -print STRING: Print STRING on the terminal. */ | ||
| 1488 | str = unquote_argument (string + strlen ("-print ")); | ||
| 1489 | if (needlf) | ||
| 1048 | printf ("\n"); | 1490 | printf ("\n"); |
| 1049 | printf ("%s", string); | 1491 | printf ("%s", str); |
| 1050 | needlf = string[0] == '\0' ? needlf : string[strlen (string) - 1] != '\n'; | 1492 | needlf = str[0] == '\0' ? needlf : str[strlen (str) - 1] != '\n'; |
| 1493 | } | ||
| 1494 | else if (strprefix ("-error ", string)) | ||
| 1495 | { | ||
| 1496 | /* -error DESCRIPTION: Signal an error on the terminal. */ | ||
| 1497 | str = unquote_argument (string + strlen ("-error ")); | ||
| 1498 | if (needlf) | ||
| 1499 | printf ("\n"); | ||
| 1500 | fprintf (stderr, "*ERROR*: %s", str); | ||
| 1501 | needlf = str[0] == '\0' ? needlf : str[strlen (str) - 1] != '\n'; | ||
| 1502 | } | ||
| 1503 | #ifndef WINDOWSNT | ||
| 1504 | else if (strprefix ("-suspend ", string)) | ||
| 1505 | { | ||
| 1506 | /* -suspend: Suspend this terminal, i.e., stop the process. */ | ||
| 1507 | if (needlf) | ||
| 1508 | printf ("\n"); | ||
| 1509 | needlf = 0; | ||
| 1510 | kill (0, SIGSTOP); | ||
| 1511 | } | ||
| 1512 | #endif | ||
| 1513 | else | ||
| 1514 | { | ||
| 1515 | /* Unknown command. */ | ||
| 1516 | if (needlf) | ||
| 1517 | printf ("\n"); | ||
| 1518 | printf ("*ERROR*: Unknown message: %s", string); | ||
| 1519 | needlf = string[0] == '\0' ? needlf : string[strlen (string) - 1] != '\n'; | ||
| 1051 | } | 1520 | } |
| 1052 | |||
| 1053 | if (needlf) | ||
| 1054 | printf ("\n"); | ||
| 1055 | fflush (stdout); | ||
| 1056 | } | 1521 | } |
| 1057 | 1522 | ||
| 1058 | CLOSE_SOCKET (s); | 1523 | if (needlf) |
| 1524 | printf ("\n"); | ||
| 1525 | fflush (stdout); | ||
| 1526 | fsync (1); | ||
| 1527 | |||
| 1528 | CLOSE_SOCKET (emacs_socket); | ||
| 1059 | return EXIT_SUCCESS; | 1529 | return EXIT_SUCCESS; |
| 1060 | } | 1530 | } |
| 1061 | 1531 | ||
| 1062 | #endif /* HAVE_SOCKETS && HAVE_INET_SOCKETS */ | 1532 | #endif /* HAVE_SOCKETS && HAVE_INET_SOCKETS */ |
| 1063 | 1533 | ||
| 1534 | |||
| 1064 | #ifndef HAVE_STRERROR | 1535 | #ifndef HAVE_STRERROR |
| 1065 | char * | 1536 | char * |
| 1066 | strerror (errnum) | 1537 | strerror (errnum) |
diff --git a/lib-src/makefile.w32-in b/lib-src/makefile.w32-in index 3076b85dbd8..c21401154eb 100644 --- a/lib-src/makefile.w32-in +++ b/lib-src/makefile.w32-in | |||
| @@ -24,7 +24,7 @@ ALL = make-docfile hexl ctags etags movemail ebrowse sorted-doc digest-doc emacs | |||
| 24 | 24 | ||
| 25 | .PHONY: $(ALL) | 25 | .PHONY: $(ALL) |
| 26 | 26 | ||
| 27 | VERSION = 22.1.50 | 27 | VERSION = 23.0.51 |
| 28 | 28 | ||
| 29 | LOCAL_FLAGS = -DWINDOWSNT -DDOS_NT -DSTDC_HEADERS=1 -DNO_LDAV=1 \ | 29 | LOCAL_FLAGS = -DWINDOWSNT -DDOS_NT -DSTDC_HEADERS=1 -DNO_LDAV=1 \ |
| 30 | -DNO_ARCHIVES=1 -DHAVE_CONFIG_H=1 -I../nt/inc \ | 30 | -DNO_ARCHIVES=1 -DHAVE_CONFIG_H=1 -I../nt/inc \ |