diff options
Diffstat (limited to 'src/process.c')
| -rw-r--r-- | src/process.c | 883 |
1 files changed, 611 insertions, 272 deletions
diff --git a/src/process.c b/src/process.c index 419d108b712..1e2bcc3c2ac 100644 --- a/src/process.c +++ b/src/process.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* Asynchronous subprocess control for GNU Emacs. | 1 | /* Asynchronous subprocess control for GNU Emacs. |
| 2 | Copyright (C) 1985, 86, 87, 88, 93, 94, 95, 96, 98, 1999, | 2 | Copyright (C) 1985, 86, 87, 88, 93, 94, 95, 96, 98, 1999, |
| 3 | 2001, 2002, 2003 Free Software Foundation, Inc. | 3 | 2001, 2002, 2003, 2004 Free Software Foundation, Inc. |
| 4 | 4 | ||
| 5 | This file is part of GNU Emacs. | 5 | This file is part of GNU Emacs. |
| 6 | 6 | ||
| @@ -98,6 +98,17 @@ Boston, MA 02111-1307, USA. */ | |||
| 98 | #include <bsdtty.h> | 98 | #include <bsdtty.h> |
| 99 | #endif | 99 | #endif |
| 100 | 100 | ||
| 101 | /* Can we use SIOCGIFCONF and/or SIOCGIFADDR */ | ||
| 102 | #ifdef HAVE_SOCKETS | ||
| 103 | #if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_NET_IF_H) | ||
| 104 | /* sys/ioctl.h may have been included already */ | ||
| 105 | #ifndef SIOCGIFADDR | ||
| 106 | #include <sys/ioctl.h> | ||
| 107 | #endif | ||
| 108 | #include <net/if.h> | ||
| 109 | #endif | ||
| 110 | #endif | ||
| 111 | |||
| 101 | #ifdef IRIS | 112 | #ifdef IRIS |
| 102 | #include <sys/sysmacros.h> /* for "minor" */ | 113 | #include <sys/sysmacros.h> /* for "minor" */ |
| 103 | #endif /* not IRIS */ | 114 | #endif /* not IRIS */ |
| @@ -249,6 +260,33 @@ int update_tick; | |||
| 249 | #undef DATAGRAM_SOCKETS | 260 | #undef DATAGRAM_SOCKETS |
| 250 | #endif | 261 | #endif |
| 251 | 262 | ||
| 263 | #if !defined (ADAPTIVE_READ_BUFFERING) && !defined (NO_ADAPTIVE_READ_BUFFERING) | ||
| 264 | #ifdef EMACS_HAS_USECS | ||
| 265 | #define ADAPTIVE_READ_BUFFERING | ||
| 266 | #endif | ||
| 267 | #endif | ||
| 268 | |||
| 269 | #ifdef ADAPTIVE_READ_BUFFERING | ||
| 270 | #define READ_OUTPUT_DELAY_INCREMENT 10000 | ||
| 271 | #define READ_OUTPUT_DELAY_MAX (READ_OUTPUT_DELAY_INCREMENT * 5) | ||
| 272 | #define READ_OUTPUT_DELAY_MAX_MAX (READ_OUTPUT_DELAY_INCREMENT * 7) | ||
| 273 | |||
| 274 | /* Number of processes which might be delayed. */ | ||
| 275 | |||
| 276 | static int process_output_delay_count; | ||
| 277 | |||
| 278 | /* Non-zero if any process has non-nil process_output_skip. */ | ||
| 279 | |||
| 280 | static int process_output_skip; | ||
| 281 | |||
| 282 | /* Non-nil means to delay reading process output to improve buffering. | ||
| 283 | A value of t means that delay is reset after each send, any other | ||
| 284 | non-nil value does not reset the delay. */ | ||
| 285 | static Lisp_Object Vprocess_adaptive_read_buffering; | ||
| 286 | #else | ||
| 287 | #define process_output_delay_count 0 | ||
| 288 | #endif | ||
| 289 | |||
| 252 | 290 | ||
| 253 | #include "sysselect.h" | 291 | #include "sysselect.h" |
| 254 | 292 | ||
| @@ -562,6 +600,12 @@ make_process (name) | |||
| 562 | p->status = Qrun; | 600 | p->status = Qrun; |
| 563 | p->mark = Fmake_marker (); | 601 | p->mark = Fmake_marker (); |
| 564 | 602 | ||
| 603 | #ifdef ADAPTIVE_READ_BUFFERING | ||
| 604 | p->adaptive_read_buffering = Qnil; | ||
| 605 | XSETFASTINT (p->read_output_delay, 0); | ||
| 606 | p->read_output_skip = Qnil; | ||
| 607 | #endif | ||
| 608 | |||
| 565 | /* If name is already in use, modify it until it is unused. */ | 609 | /* If name is already in use, modify it until it is unused. */ |
| 566 | 610 | ||
| 567 | name1 = name; | 611 | name1 = name; |
| @@ -955,8 +999,14 @@ It gets two arguments: the process, and a string describing the change. */) | |||
| 955 | (process, sentinel) | 999 | (process, sentinel) |
| 956 | register Lisp_Object process, sentinel; | 1000 | register Lisp_Object process, sentinel; |
| 957 | { | 1001 | { |
| 1002 | struct Lisp_Process *p; | ||
| 1003 | |||
| 958 | CHECK_PROCESS (process); | 1004 | CHECK_PROCESS (process); |
| 959 | XPROCESS (process)->sentinel = sentinel; | 1005 | p = XPROCESS (process); |
| 1006 | |||
| 1007 | p->sentinel = sentinel; | ||
| 1008 | if (NETCONN1_P (p)) | ||
| 1009 | p->childp = Fplist_put (p->childp, QCsentinel, sentinel); | ||
| 960 | return sentinel; | 1010 | return sentinel; |
| 961 | } | 1011 | } |
| 962 | 1012 | ||
| @@ -1485,6 +1535,10 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */) | |||
| 1485 | = buffer_defaults.enable_multibyte_characters; | 1535 | = buffer_defaults.enable_multibyte_characters; |
| 1486 | XPROCESS (proc)->command = Flist (nargs - 2, args + 2); | 1536 | XPROCESS (proc)->command = Flist (nargs - 2, args + 2); |
| 1487 | 1537 | ||
| 1538 | #ifdef ADAPTIVE_READ_BUFFERING | ||
| 1539 | XPROCESS (proc)->adaptive_read_buffering = Vprocess_adaptive_read_buffering; | ||
| 1540 | #endif | ||
| 1541 | |||
| 1488 | /* Make the process marker point into the process buffer (if any). */ | 1542 | /* Make the process marker point into the process buffer (if any). */ |
| 1489 | if (!NILP (buffer)) | 1543 | if (!NILP (buffer)) |
| 1490 | set_marker_both (XPROCESS (proc)->mark, buffer, | 1544 | set_marker_both (XPROCESS (proc)->mark, buffer, |
| @@ -2298,233 +2352,172 @@ static struct socket_options { | |||
| 2298 | /* The name of this option. Should be lowercase version of option | 2352 | /* The name of this option. Should be lowercase version of option |
| 2299 | name without SO_ prefix. */ | 2353 | name without SO_ prefix. */ |
| 2300 | char *name; | 2354 | char *name; |
| 2301 | /* Length of name. */ | ||
| 2302 | int nlen; | ||
| 2303 | /* Option level SOL_... */ | 2355 | /* Option level SOL_... */ |
| 2304 | int optlevel; | 2356 | int optlevel; |
| 2305 | /* Option number SO_... */ | 2357 | /* Option number SO_... */ |
| 2306 | int optnum; | 2358 | int optnum; |
| 2307 | enum { SOPT_UNKNOWN, SOPT_BOOL, SOPT_INT, SOPT_STR, SOPT_LINGER } opttype; | 2359 | enum { SOPT_UNKNOWN, SOPT_BOOL, SOPT_INT, SOPT_IFNAME, SOPT_LINGER } opttype; |
| 2360 | enum { OPIX_NONE=0, OPIX_MISC=1, OPIX_REUSEADDR=2 } optbit; | ||
| 2308 | } socket_options[] = | 2361 | } socket_options[] = |
| 2309 | { | 2362 | { |
| 2310 | #ifdef SO_BINDTODEVICE | 2363 | #ifdef SO_BINDTODEVICE |
| 2311 | { "bindtodevice", 12, SOL_SOCKET, SO_BINDTODEVICE, SOPT_STR }, | 2364 | { ":bindtodevice", SOL_SOCKET, SO_BINDTODEVICE, SOPT_IFNAME, OPIX_MISC }, |
| 2312 | #endif | 2365 | #endif |
| 2313 | #ifdef SO_BROADCAST | 2366 | #ifdef SO_BROADCAST |
| 2314 | { "broadcast", 9, SOL_SOCKET, SO_BROADCAST, SOPT_BOOL }, | 2367 | { ":broadcast", SOL_SOCKET, SO_BROADCAST, SOPT_BOOL, OPIX_MISC }, |
| 2315 | #endif | 2368 | #endif |
| 2316 | #ifdef SO_DONTROUTE | 2369 | #ifdef SO_DONTROUTE |
| 2317 | { "dontroute", 9, SOL_SOCKET, SO_DONTROUTE, SOPT_BOOL }, | 2370 | { ":dontroute", SOL_SOCKET, SO_DONTROUTE, SOPT_BOOL, OPIX_MISC }, |
| 2318 | #endif | 2371 | #endif |
| 2319 | #ifdef SO_KEEPALIVE | 2372 | #ifdef SO_KEEPALIVE |
| 2320 | { "keepalive", 9, SOL_SOCKET, SO_KEEPALIVE, SOPT_BOOL }, | 2373 | { ":keepalive", SOL_SOCKET, SO_KEEPALIVE, SOPT_BOOL, OPIX_MISC }, |
| 2321 | #endif | 2374 | #endif |
| 2322 | #ifdef SO_LINGER | 2375 | #ifdef SO_LINGER |
| 2323 | { "linger", 6, SOL_SOCKET, SO_LINGER, SOPT_LINGER }, | 2376 | { ":linger", SOL_SOCKET, SO_LINGER, SOPT_LINGER, OPIX_MISC }, |
| 2324 | #endif | 2377 | #endif |
| 2325 | #ifdef SO_OOBINLINE | 2378 | #ifdef SO_OOBINLINE |
| 2326 | { "oobinline", 9, SOL_SOCKET, SO_OOBINLINE, SOPT_BOOL }, | 2379 | { ":oobinline", SOL_SOCKET, SO_OOBINLINE, SOPT_BOOL, OPIX_MISC }, |
| 2327 | #endif | 2380 | #endif |
| 2328 | #ifdef SO_PRIORITY | 2381 | #ifdef SO_PRIORITY |
| 2329 | { "priority", 8, SOL_SOCKET, SO_PRIORITY, SOPT_INT }, | 2382 | { ":priority", SOL_SOCKET, SO_PRIORITY, SOPT_INT, OPIX_MISC }, |
| 2330 | #endif | 2383 | #endif |
| 2331 | #ifdef SO_REUSEADDR | 2384 | #ifdef SO_REUSEADDR |
| 2332 | { "reuseaddr", 9, SOL_SOCKET, SO_REUSEADDR, SOPT_BOOL }, | 2385 | { ":reuseaddr", SOL_SOCKET, SO_REUSEADDR, SOPT_BOOL, OPIX_REUSEADDR }, |
| 2333 | #endif | 2386 | #endif |
| 2334 | { 0, 0, 0, 0, SOPT_UNKNOWN } | 2387 | { 0, 0, 0, SOPT_UNKNOWN, OPIX_NONE } |
| 2335 | }; | 2388 | }; |
| 2336 | 2389 | ||
| 2337 | /* Process list of socket options OPTS on socket S. | 2390 | /* Set option OPT to value VAL on socket S. |
| 2338 | Only check if options are supported is S < 0. | ||
| 2339 | If NO_ERROR is non-zero, continue silently if an option | ||
| 2340 | cannot be set. | ||
| 2341 | 2391 | ||
| 2342 | Each element specifies one option. An element is either a string | 2392 | Returns (1<<socket_options[OPT].optbit) if option is known, 0 otherwise. |
| 2343 | "OPTION=VALUE" or a cons (OPTION . VALUE) where OPTION is a string | 2393 | Signals an error if setting a known option fails. |
| 2344 | or a symbol. */ | 2394 | */ |
| 2345 | 2395 | ||
| 2346 | static int | 2396 | static int |
| 2347 | set_socket_options (s, opts, no_error) | 2397 | set_socket_option (s, opt, val) |
| 2348 | int s; | 2398 | int s; |
| 2349 | Lisp_Object opts; | 2399 | Lisp_Object opt, val; |
| 2350 | int no_error; | ||
| 2351 | { | 2400 | { |
| 2352 | if (!CONSP (opts)) | 2401 | char *name; |
| 2353 | opts = Fcons (opts, Qnil); | 2402 | struct socket_options *sopt; |
| 2403 | int ret = 0; | ||
| 2354 | 2404 | ||
| 2355 | while (CONSP (opts)) | 2405 | CHECK_SYMBOL (opt); |
| 2356 | { | ||
| 2357 | Lisp_Object opt; | ||
| 2358 | Lisp_Object val; | ||
| 2359 | char *name, *arg; | ||
| 2360 | struct socket_options *sopt; | ||
| 2361 | int ret = 0; | ||
| 2362 | |||
| 2363 | opt = XCAR (opts); | ||
| 2364 | opts = XCDR (opts); | ||
| 2365 | |||
| 2366 | name = 0; | ||
| 2367 | val = Qt; | ||
| 2368 | if (CONSP (opt)) | ||
| 2369 | { | ||
| 2370 | val = XCDR (opt); | ||
| 2371 | opt = XCAR (opt); | ||
| 2372 | } | ||
| 2373 | if (STRINGP (opt)) | ||
| 2374 | name = (char *) SDATA (opt); | ||
| 2375 | else if (SYMBOLP (opt)) | ||
| 2376 | name = (char *) SDATA (SYMBOL_NAME (opt)); | ||
| 2377 | else { | ||
| 2378 | error ("Mal-formed option list"); | ||
| 2379 | return 0; | ||
| 2380 | } | ||
| 2381 | 2406 | ||
| 2382 | if (strncmp (name, "no", 2) == 0) | 2407 | name = (char *) SDATA (SYMBOL_NAME (opt)); |
| 2383 | { | 2408 | for (sopt = socket_options; sopt->name; sopt++) |
| 2384 | val = Qnil; | 2409 | if (strcmp (name, sopt->name) == 0) |
| 2385 | name += 2; | 2410 | break; |
| 2386 | } | ||
| 2387 | 2411 | ||
| 2388 | arg = 0; | 2412 | switch (sopt->opttype) |
| 2389 | for (sopt = socket_options; sopt->name; sopt++) | 2413 | { |
| 2390 | if (strncmp (name, sopt->name, sopt->nlen) == 0) | 2414 | case SOPT_BOOL: |
| 2391 | { | 2415 | { |
| 2392 | if (name[sopt->nlen] == 0) | 2416 | int optval; |
| 2393 | break; | 2417 | optval = NILP (val) ? 0 : 1; |
| 2394 | if (name[sopt->nlen] == '=') | 2418 | ret = setsockopt (s, sopt->optlevel, sopt->optnum, |
| 2395 | { | 2419 | &optval, sizeof (optval)); |
| 2396 | arg = name + sopt->nlen + 1; | 2420 | break; |
| 2397 | break; | 2421 | } |
| 2398 | } | ||
| 2399 | } | ||
| 2400 | 2422 | ||
| 2401 | switch (sopt->opttype) | 2423 | case SOPT_INT: |
| 2402 | { | 2424 | { |
| 2403 | case SOPT_BOOL: | 2425 | int optval; |
| 2404 | { | 2426 | if (INTEGERP (val)) |
| 2405 | int optval; | 2427 | optval = XINT (val); |
| 2406 | if (s < 0) | 2428 | else |
| 2407 | return 1; | 2429 | error ("Bad option value for %s", name); |
| 2408 | if (arg) | 2430 | ret = setsockopt (s, sopt->optlevel, sopt->optnum, |
| 2409 | optval = (*arg == '0' || *arg == 'n') ? 0 : 1; | 2431 | &optval, sizeof (optval)); |
| 2410 | else if (INTEGERP (val)) | 2432 | break; |
| 2411 | optval = XINT (val) == 0 ? 0 : 1; | 2433 | } |
| 2412 | else | ||
| 2413 | optval = NILP (val) ? 0 : 1; | ||
| 2414 | ret = setsockopt (s, sopt->optlevel, sopt->optnum, | ||
| 2415 | &optval, sizeof (optval)); | ||
| 2416 | break; | ||
| 2417 | } | ||
| 2418 | 2434 | ||
| 2419 | case SOPT_INT: | 2435 | #ifdef SO_BINDTODEVICE |
| 2420 | { | 2436 | case SOPT_IFNAME: |
| 2421 | int optval; | 2437 | { |
| 2422 | if (arg) | 2438 | char devname[IFNAMSIZ+1]; |
| 2423 | optval = atoi(arg); | ||
| 2424 | else if (INTEGERP (val)) | ||
| 2425 | optval = XINT (val); | ||
| 2426 | else | ||
| 2427 | error ("Bad option argument for %s", name); | ||
| 2428 | if (s < 0) | ||
| 2429 | return 1; | ||
| 2430 | ret = setsockopt (s, sopt->optlevel, sopt->optnum, | ||
| 2431 | &optval, sizeof (optval)); | ||
| 2432 | break; | ||
| 2433 | } | ||
| 2434 | 2439 | ||
| 2435 | case SOPT_STR: | 2440 | /* This is broken, at least in the Linux 2.4 kernel. |
| 2441 | To unbind, the arg must be a zero integer, not the empty string. | ||
| 2442 | This should work on all systems. KFS. 2003-09-23. */ | ||
| 2443 | bzero (devname, sizeof devname); | ||
| 2444 | if (STRINGP (val)) | ||
| 2436 | { | 2445 | { |
| 2437 | if (!arg) | 2446 | char *arg = (char *) SDATA (val); |
| 2438 | { | 2447 | int len = min (strlen (arg), IFNAMSIZ); |
| 2439 | if (NILP (val)) | 2448 | bcopy (arg, devname, len); |
| 2440 | arg = ""; | ||
| 2441 | else if (STRINGP (val)) | ||
| 2442 | arg = (char *) SDATA (val); | ||
| 2443 | else if (XSYMBOL (val)) | ||
| 2444 | arg = (char *) SDATA (SYMBOL_NAME (val)); | ||
| 2445 | else | ||
| 2446 | error ("Invalid argument to %s option", name); | ||
| 2447 | } | ||
| 2448 | ret = setsockopt (s, sopt->optlevel, sopt->optnum, | ||
| 2449 | arg, strlen (arg)); | ||
| 2450 | } | 2449 | } |
| 2450 | else if (!NILP (val)) | ||
| 2451 | error ("Bad option value for %s", name); | ||
| 2452 | ret = setsockopt (s, sopt->optlevel, sopt->optnum, | ||
| 2453 | devname, IFNAMSIZ); | ||
| 2454 | break; | ||
| 2455 | } | ||
| 2456 | #endif | ||
| 2451 | 2457 | ||
| 2452 | #ifdef SO_LINGER | 2458 | #ifdef SO_LINGER |
| 2453 | case SOPT_LINGER: | 2459 | case SOPT_LINGER: |
| 2454 | { | 2460 | { |
| 2455 | struct linger linger; | 2461 | struct linger linger; |
| 2456 | |||
| 2457 | linger.l_onoff = 1; | ||
| 2458 | linger.l_linger = 0; | ||
| 2459 | |||
| 2460 | if (s < 0) | ||
| 2461 | return 1; | ||
| 2462 | 2462 | ||
| 2463 | if (arg) | 2463 | linger.l_onoff = 1; |
| 2464 | { | 2464 | linger.l_linger = 0; |
| 2465 | if (*arg == 'n' || *arg == 't' || *arg == 'y') | 2465 | if (INTEGERP (val)) |
| 2466 | linger.l_onoff = (*arg == 'n') ? 0 : 1; | 2466 | linger.l_linger = XINT (val); |
| 2467 | else | 2467 | else |
| 2468 | linger.l_linger = atoi(arg); | 2468 | linger.l_onoff = NILP (val) ? 0 : 1; |
| 2469 | } | 2469 | ret = setsockopt (s, sopt->optlevel, sopt->optnum, |
| 2470 | else if (INTEGERP (val)) | 2470 | &linger, sizeof (linger)); |
| 2471 | linger.l_linger = XINT (val); | 2471 | break; |
| 2472 | else | 2472 | } |
| 2473 | linger.l_onoff = NILP (val) ? 0 : 1; | ||
| 2474 | ret = setsockopt (s, sopt->optlevel, sopt->optnum, | ||
| 2475 | &linger, sizeof (linger)); | ||
| 2476 | break; | ||
| 2477 | } | ||
| 2478 | #endif | 2473 | #endif |
| 2479 | default: | 2474 | |
| 2480 | if (s < 0) | 2475 | default: |
| 2481 | return 0; | 2476 | return 0; |
| 2482 | if (no_error) | ||
| 2483 | continue; | ||
| 2484 | error ("Unsupported option: %s", name); | ||
| 2485 | } | ||
| 2486 | if (ret < 0 && ! no_error) | ||
| 2487 | report_file_error ("Cannot set network option: %s", opt); | ||
| 2488 | } | 2477 | } |
| 2489 | return 1; | 2478 | |
| 2479 | if (ret < 0) | ||
| 2480 | report_file_error ("Cannot set network option", | ||
| 2481 | Fcons (opt, Fcons (val, Qnil))); | ||
| 2482 | return (1 << sopt->optbit); | ||
| 2490 | } | 2483 | } |
| 2491 | 2484 | ||
| 2492 | DEFUN ("set-network-process-options", | 2485 | |
| 2493 | Fset_network_process_options, Sset_network_process_options, | 2486 | DEFUN ("set-network-process-option", |
| 2494 | 1, MANY, 0, | 2487 | Fset_network_process_option, Sset_network_process_option, |
| 2495 | doc: /* Set one or more options for network process PROCESS. | 2488 | 3, 4, 0, |
| 2496 | Each option is either a string "OPT=VALUE" or a cons (OPT . VALUE). | 2489 | doc: /* For network process PROCESS set option OPTION to value VALUE. |
| 2497 | A boolean value is false if it either zero or nil, true otherwise. | 2490 | See `make-network-process' for a list of options and values. |
| 2498 | 2491 | If optional fourth arg NO-ERROR is non-nil, don't signal an error if | |
| 2499 | The following options are known. Consult the relevant system manual | 2492 | OPTION is not a supported option, return nil instead; otherwise return t. */) |
| 2500 | pages for more information. | 2493 | (process, option, value, no_error) |
| 2501 | 2494 | Lisp_Object process, option, value; | |
| 2502 | bindtodevice=NAME -- bind to interface NAME, or remove binding if nil. | 2495 | Lisp_Object no_error; |
| 2503 | broadcast=BOOL -- Allow send and receive of datagram broadcasts. | ||
| 2504 | dontroute=BOOL -- Only send to directly connected hosts. | ||
| 2505 | keepalive=BOOL -- Send keep-alive messages on network stream. | ||
| 2506 | linger=BOOL or TIMEOUT -- Send queued messages before closing. | ||
| 2507 | oobinline=BOOL -- Place out-of-band data in receive data stream. | ||
| 2508 | priority=INT -- Set protocol defined priority for sent packets. | ||
| 2509 | reuseaddr=BOOL -- Allow reusing a recently used address. | ||
| 2510 | |||
| 2511 | usage: (set-network-process-options PROCESS &rest OPTIONS) */) | ||
| 2512 | (nargs, args) | ||
| 2513 | int nargs; | ||
| 2514 | Lisp_Object *args; | ||
| 2515 | { | 2496 | { |
| 2516 | Lisp_Object process; | 2497 | int s; |
| 2517 | Lisp_Object opts; | 2498 | struct Lisp_Process *p; |
| 2518 | 2499 | ||
| 2519 | process = args[0]; | ||
| 2520 | CHECK_PROCESS (process); | 2500 | CHECK_PROCESS (process); |
| 2521 | if (nargs > 1 && XINT (XPROCESS (process)->infd) >= 0) | 2501 | p = XPROCESS (process); |
| 2502 | if (!NETCONN1_P (p)) | ||
| 2503 | error ("Process is not a network process"); | ||
| 2504 | |||
| 2505 | s = XINT (p->infd); | ||
| 2506 | if (s < 0) | ||
| 2507 | error ("Process is not running"); | ||
| 2508 | |||
| 2509 | if (set_socket_option (s, option, value)) | ||
| 2522 | { | 2510 | { |
| 2523 | opts = Flist (nargs, args); | 2511 | p->childp = Fplist_put (p->childp, option, value); |
| 2524 | set_socket_options (XINT (XPROCESS (process)->infd), opts, 0); | 2512 | return Qt; |
| 2525 | } | 2513 | } |
| 2526 | return process; | 2514 | |
| 2515 | if (NILP (no_error)) | ||
| 2516 | error ("Unknown or unsupported option"); | ||
| 2517 | |||
| 2518 | return Qnil; | ||
| 2527 | } | 2519 | } |
| 2520 | |||
| 2528 | 2521 | ||
| 2529 | /* A version of request_sigio suitable for a record_unwind_protect. */ | 2522 | /* A version of request_sigio suitable for a record_unwind_protect. */ |
| 2530 | 2523 | ||
| @@ -2604,10 +2597,10 @@ address data with one element per address data byte. Do not rely on | |||
| 2604 | this format in portable code, as it may depend on implementation | 2597 | this format in portable code, as it may depend on implementation |
| 2605 | defined constants, data sizes, and data structure alignment. | 2598 | defined constants, data sizes, and data structure alignment. |
| 2606 | 2599 | ||
| 2607 | :coding CODING -- CODING is coding system for this process. | 2600 | :coding CODING -- If CODING is a symbol, it specifies the coding |
| 2608 | 2601 | system used for both reading and writing for this process. If CODING | |
| 2609 | :options OPTIONS -- Set the specified options for the network process. | 2602 | is a cons (DECODING . ENCODING), DECODING is used for reading, and |
| 2610 | See `set-network-process-options' for details. | 2603 | ENCODING is used for writing. |
| 2611 | 2604 | ||
| 2612 | :nowait BOOL -- If BOOL is non-nil for a stream type client process, | 2605 | :nowait BOOL -- If BOOL is non-nil for a stream type client process, |
| 2613 | return without waiting for the connection to complete; instead, the | 2606 | return without waiting for the connection to complete; instead, the |
| @@ -2641,13 +2634,33 @@ and MESSAGE is a string. | |||
| 2641 | 2634 | ||
| 2642 | :plist PLIST -- Install PLIST as the new process' initial plist. | 2635 | :plist PLIST -- Install PLIST as the new process' initial plist. |
| 2643 | 2636 | ||
| 2644 | :server BOOL -- if BOOL is non-nil, create a server process for the | 2637 | :server QLEN -- if QLEN is non-nil, create a server process for the |
| 2645 | specified FAMILY, SERVICE, and connection type (stream or datagram). | 2638 | specified FAMILY, SERVICE, and connection type (stream or datagram). |
| 2646 | Default is a client process. | 2639 | If QLEN is an integer, it is used as the max. length of the server's |
| 2640 | pending connection queue (also known as the backlog); the default | ||
| 2641 | queue length is 5. Default is to create a client process. | ||
| 2642 | |||
| 2643 | The following network options can be specified for this connection: | ||
| 2644 | |||
| 2645 | :broadcast BOOL -- Allow send and receive of datagram broadcasts. | ||
| 2646 | :dontroute BOOL -- Only send to directly connected hosts. | ||
| 2647 | :keepalive BOOL -- Send keep-alive messages on network stream. | ||
| 2648 | :linger BOOL or TIMEOUT -- Send queued messages before closing. | ||
| 2649 | :oobinline BOOL -- Place out-of-band data in receive data stream. | ||
| 2650 | :priority INT -- Set protocol defined priority for sent packets. | ||
| 2651 | :reuseaddr BOOL -- Allow reusing a recently used local address | ||
| 2652 | (this is allowed by default for a server process). | ||
| 2653 | :bindtodevice NAME -- bind to interface NAME. Using this may require | ||
| 2654 | special privileges on some systems. | ||
| 2655 | |||
| 2656 | Consult the relevant system programmer's manual pages for more | ||
| 2657 | information on using these options. | ||
| 2658 | |||
| 2659 | |||
| 2660 | A server process will listen for and accept connections from clients. | ||
| 2661 | When a client connection is accepted, a new network process is created | ||
| 2662 | for the connection with the following parameters: | ||
| 2647 | 2663 | ||
| 2648 | A server process will listen for and accept connections from | ||
| 2649 | clients. When a client connection is accepted, a new network process | ||
| 2650 | is created for the connection with the following parameters: | ||
| 2651 | - The client's process name is constructed by concatenating the server | 2664 | - The client's process name is constructed by concatenating the server |
| 2652 | process' NAME and a client identification string. | 2665 | process' NAME and a client identification string. |
| 2653 | - If the FILTER argument is non-nil, the client process will not get a | 2666 | - If the FILTER argument is non-nil, the client process will not get a |
| @@ -2708,7 +2721,7 @@ usage: (make-network-process &rest ARGS) */) | |||
| 2708 | Lisp_Object name, buffer, host, service, address; | 2721 | Lisp_Object name, buffer, host, service, address; |
| 2709 | Lisp_Object filter, sentinel; | 2722 | Lisp_Object filter, sentinel; |
| 2710 | int is_non_blocking_client = 0; | 2723 | int is_non_blocking_client = 0; |
| 2711 | int is_server = 0; | 2724 | int is_server = 0, backlog = 5; |
| 2712 | int socktype; | 2725 | int socktype; |
| 2713 | int family = -1; | 2726 | int family = -1; |
| 2714 | 2727 | ||
| @@ -2745,6 +2758,8 @@ usage: (make-network-process &rest ARGS) */) | |||
| 2745 | error ("Network servers not supported"); | 2758 | error ("Network servers not supported"); |
| 2746 | #else | 2759 | #else |
| 2747 | is_server = 1; | 2760 | is_server = 1; |
| 2761 | if (INTEGERP (tem)) | ||
| 2762 | backlog = XINT (tem); | ||
| 2748 | #endif | 2763 | #endif |
| 2749 | } | 2764 | } |
| 2750 | 2765 | ||
| @@ -2997,6 +3012,8 @@ usage: (make-network-process &rest ARGS) */) | |||
| 2997 | 3012 | ||
| 2998 | for (lres = res; lres; lres = lres->ai_next) | 3013 | for (lres = res; lres; lres = lres->ai_next) |
| 2999 | { | 3014 | { |
| 3015 | int optn, optbits; | ||
| 3016 | |||
| 3000 | s = socket (lres->ai_family, lres->ai_socktype, lres->ai_protocol); | 3017 | s = socket (lres->ai_family, lres->ai_socktype, lres->ai_protocol); |
| 3001 | if (s < 0) | 3018 | if (s < 0) |
| 3002 | { | 3019 | { |
| @@ -3030,17 +3047,27 @@ usage: (make-network-process &rest ARGS) */) | |||
| 3030 | /* Make us close S if quit. */ | 3047 | /* Make us close S if quit. */ |
| 3031 | record_unwind_protect (close_file_unwind, make_number (s)); | 3048 | record_unwind_protect (close_file_unwind, make_number (s)); |
| 3032 | 3049 | ||
| 3050 | /* Parse network options in the arg list. | ||
| 3051 | We simply ignore anything which isn't a known option (including other keywords). | ||
| 3052 | An error is signalled if setting a known option fails. */ | ||
| 3053 | for (optn = optbits = 0; optn < nargs-1; optn += 2) | ||
| 3054 | optbits |= set_socket_option (s, args[optn], args[optn+1]); | ||
| 3055 | |||
| 3033 | if (is_server) | 3056 | if (is_server) |
| 3034 | { | 3057 | { |
| 3035 | /* Configure as a server socket. */ | 3058 | /* Configure as a server socket. */ |
| 3059 | |||
| 3060 | /* SO_REUSEADDR = 1 is default for server sockets; must specify | ||
| 3061 | explicit :reuseaddr key to override this. */ | ||
| 3036 | #ifdef HAVE_LOCAL_SOCKETS | 3062 | #ifdef HAVE_LOCAL_SOCKETS |
| 3037 | if (family != AF_LOCAL) | 3063 | if (family != AF_LOCAL) |
| 3038 | #endif | 3064 | #endif |
| 3039 | { | 3065 | if (!(optbits & (1 << OPIX_REUSEADDR))) |
| 3040 | int optval = 1; | 3066 | { |
| 3041 | if (setsockopt (s, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof optval)) | 3067 | int optval = 1; |
| 3042 | report_file_error ("Cannot set reuse option on server socket.", Qnil); | 3068 | if (setsockopt (s, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof optval)) |
| 3043 | } | 3069 | report_file_error ("Cannot set reuse option on server socket", Qnil); |
| 3070 | } | ||
| 3044 | 3071 | ||
| 3045 | if (bind (s, lres->ai_addr, lres->ai_addrlen)) | 3072 | if (bind (s, lres->ai_addr, lres->ai_addrlen)) |
| 3046 | report_file_error ("Cannot bind server socket", Qnil); | 3073 | report_file_error ("Cannot bind server socket", Qnil); |
| @@ -3059,7 +3086,7 @@ usage: (make-network-process &rest ARGS) */) | |||
| 3059 | } | 3086 | } |
| 3060 | #endif | 3087 | #endif |
| 3061 | 3088 | ||
| 3062 | if (socktype == SOCK_STREAM && listen (s, 5)) | 3089 | if (socktype == SOCK_STREAM && listen (s, backlog)) |
| 3063 | report_file_error ("Cannot listen on server socket", Qnil); | 3090 | report_file_error ("Cannot listen on server socket", Qnil); |
| 3064 | 3091 | ||
| 3065 | break; | 3092 | break; |
| @@ -3195,10 +3222,6 @@ usage: (make-network-process &rest ARGS) */) | |||
| 3195 | report_file_error ("make client process failed", contact); | 3222 | report_file_error ("make client process failed", contact); |
| 3196 | } | 3223 | } |
| 3197 | 3224 | ||
| 3198 | tem = Fplist_get (contact, QCoptions); | ||
| 3199 | if (!NILP (tem)) | ||
| 3200 | set_socket_options (s, tem, 1); | ||
| 3201 | |||
| 3202 | #endif /* not TERM */ | 3225 | #endif /* not TERM */ |
| 3203 | 3226 | ||
| 3204 | inch = s; | 3227 | inch = s; |
| @@ -3280,7 +3303,11 @@ usage: (make-network-process &rest ARGS) */) | |||
| 3280 | Lisp_Object args[5], val; | 3303 | Lisp_Object args[5], val; |
| 3281 | 3304 | ||
| 3282 | if (!NILP (tem)) | 3305 | if (!NILP (tem)) |
| 3283 | val = XCAR (XCDR (tem)); | 3306 | { |
| 3307 | val = XCAR (XCDR (tem)); | ||
| 3308 | if (CONSP (val)) | ||
| 3309 | val = XCAR (val); | ||
| 3310 | } | ||
| 3284 | else if (!NILP (Vcoding_system_for_read)) | 3311 | else if (!NILP (Vcoding_system_for_read)) |
| 3285 | val = Vcoding_system_for_read; | 3312 | val = Vcoding_system_for_read; |
| 3286 | else if ((!NILP (buffer) && NILP (XBUFFER (buffer)->enable_multibyte_characters)) | 3313 | else if ((!NILP (buffer) && NILP (XBUFFER (buffer)->enable_multibyte_characters)) |
| @@ -3312,7 +3339,11 @@ usage: (make-network-process &rest ARGS) */) | |||
| 3312 | p->decode_coding_system = val; | 3339 | p->decode_coding_system = val; |
| 3313 | 3340 | ||
| 3314 | if (!NILP (tem)) | 3341 | if (!NILP (tem)) |
| 3315 | val = XCAR (XCDR (tem)); | 3342 | { |
| 3343 | val = XCAR (XCDR (tem)); | ||
| 3344 | if (CONSP (val)) | ||
| 3345 | val = XCDR (val); | ||
| 3346 | } | ||
| 3316 | else if (!NILP (Vcoding_system_for_write)) | 3347 | else if (!NILP (Vcoding_system_for_write)) |
| 3317 | val = Vcoding_system_for_write; | 3348 | val = Vcoding_system_for_write; |
| 3318 | else if (NILP (current_buffer->enable_multibyte_characters)) | 3349 | else if (NILP (current_buffer->enable_multibyte_characters)) |
| @@ -3357,6 +3388,234 @@ usage: (make-network-process &rest ARGS) */) | |||
| 3357 | } | 3388 | } |
| 3358 | #endif /* HAVE_SOCKETS */ | 3389 | #endif /* HAVE_SOCKETS */ |
| 3359 | 3390 | ||
| 3391 | |||
| 3392 | #if defined(HAVE_SOCKETS) && defined(HAVE_NET_IF_H) && defined(HAVE_SYS_IOCTL_H) | ||
| 3393 | |||
| 3394 | #ifdef SIOCGIFCONF | ||
| 3395 | DEFUN ("network-interface-list", Fnetwork_interface_list, Snetwork_interface_list, 0, 0, 0, | ||
| 3396 | doc: /* Return an alist of all network interfaces and their network address. | ||
| 3397 | Each element is a cons, the car of which is a string containing the | ||
| 3398 | interface name, and the cdr is the network address in internal | ||
| 3399 | format; see the description of ADDRESS in `make-network-process'. */) | ||
| 3400 | () | ||
| 3401 | { | ||
| 3402 | struct ifconf ifconf; | ||
| 3403 | struct ifreq *ifreqs = NULL; | ||
| 3404 | int ifaces = 0; | ||
| 3405 | int buf_size, s; | ||
| 3406 | Lisp_Object res; | ||
| 3407 | |||
| 3408 | s = socket (AF_INET, SOCK_STREAM, 0); | ||
| 3409 | if (s < 0) | ||
| 3410 | return Qnil; | ||
| 3411 | |||
| 3412 | again: | ||
| 3413 | ifaces += 25; | ||
| 3414 | buf_size = ifaces * sizeof(ifreqs[0]); | ||
| 3415 | ifreqs = (struct ifreq *)xrealloc(ifreqs, buf_size); | ||
| 3416 | if (!ifreqs) | ||
| 3417 | { | ||
| 3418 | close (s); | ||
| 3419 | return Qnil; | ||
| 3420 | } | ||
| 3421 | |||
| 3422 | ifconf.ifc_len = buf_size; | ||
| 3423 | ifconf.ifc_req = ifreqs; | ||
| 3424 | if (ioctl (s, SIOCGIFCONF, &ifconf)) | ||
| 3425 | { | ||
| 3426 | close (s); | ||
| 3427 | return Qnil; | ||
| 3428 | } | ||
| 3429 | |||
| 3430 | if (ifconf.ifc_len == buf_size) | ||
| 3431 | goto again; | ||
| 3432 | |||
| 3433 | close (s); | ||
| 3434 | ifaces = ifconf.ifc_len / sizeof (ifreqs[0]); | ||
| 3435 | |||
| 3436 | res = Qnil; | ||
| 3437 | while (--ifaces >= 0) | ||
| 3438 | { | ||
| 3439 | struct ifreq *ifq = &ifreqs[ifaces]; | ||
| 3440 | char namebuf[sizeof (ifq->ifr_name) + 1]; | ||
| 3441 | if (ifq->ifr_addr.sa_family != AF_INET) | ||
| 3442 | continue; | ||
| 3443 | bcopy (ifq->ifr_name, namebuf, sizeof (ifq->ifr_name)); | ||
| 3444 | namebuf[sizeof (ifq->ifr_name)] = 0; | ||
| 3445 | res = Fcons (Fcons (build_string (namebuf), | ||
| 3446 | conv_sockaddr_to_lisp (&ifq->ifr_addr, | ||
| 3447 | sizeof (struct sockaddr))), | ||
| 3448 | res); | ||
| 3449 | } | ||
| 3450 | |||
| 3451 | return res; | ||
| 3452 | } | ||
| 3453 | #endif /* SIOCGIFCONF */ | ||
| 3454 | |||
| 3455 | #if defined(SIOCGIFADDR) || defined(SIOCGIFHWADDR) || defined(SIOCGIFFLAGS) | ||
| 3456 | |||
| 3457 | struct ifflag_def { | ||
| 3458 | int flag_bit; | ||
| 3459 | char *flag_sym; | ||
| 3460 | }; | ||
| 3461 | |||
| 3462 | static struct ifflag_def ifflag_table[] = { | ||
| 3463 | #ifdef IFF_UP | ||
| 3464 | { IFF_UP, "up" }, | ||
| 3465 | #endif | ||
| 3466 | #ifdef IFF_BROADCAST | ||
| 3467 | { IFF_BROADCAST, "broadcast" }, | ||
| 3468 | #endif | ||
| 3469 | #ifdef IFF_DEBUG | ||
| 3470 | { IFF_DEBUG, "debug" }, | ||
| 3471 | #endif | ||
| 3472 | #ifdef IFF_LOOPBACK | ||
| 3473 | { IFF_LOOPBACK, "loopback" }, | ||
| 3474 | #endif | ||
| 3475 | #ifdef IFF_POINTOPOINT | ||
| 3476 | { IFF_POINTOPOINT, "pointopoint" }, | ||
| 3477 | #endif | ||
| 3478 | #ifdef IFF_RUNNING | ||
| 3479 | { IFF_RUNNING, "running" }, | ||
| 3480 | #endif | ||
| 3481 | #ifdef IFF_NOARP | ||
| 3482 | { IFF_NOARP, "noarp" }, | ||
| 3483 | #endif | ||
| 3484 | #ifdef IFF_PROMISC | ||
| 3485 | { IFF_PROMISC, "promisc" }, | ||
| 3486 | #endif | ||
| 3487 | #ifdef IFF_NOTRAILERS | ||
| 3488 | { IFF_NOTRAILERS, "notrailers" }, | ||
| 3489 | #endif | ||
| 3490 | #ifdef IFF_ALLMULTI | ||
| 3491 | { IFF_ALLMULTI, "allmulti" }, | ||
| 3492 | #endif | ||
| 3493 | #ifdef IFF_MASTER | ||
| 3494 | { IFF_MASTER, "master" }, | ||
| 3495 | #endif | ||
| 3496 | #ifdef IFF_SLAVE | ||
| 3497 | { IFF_SLAVE, "slave" }, | ||
| 3498 | #endif | ||
| 3499 | #ifdef IFF_MULTICAST | ||
| 3500 | { IFF_MULTICAST, "multicast" }, | ||
| 3501 | #endif | ||
| 3502 | #ifdef IFF_PORTSEL | ||
| 3503 | { IFF_PORTSEL, "portsel" }, | ||
| 3504 | #endif | ||
| 3505 | #ifdef IFF_AUTOMEDIA | ||
| 3506 | { IFF_AUTOMEDIA, "automedia" }, | ||
| 3507 | #endif | ||
| 3508 | #ifdef IFF_DYNAMIC | ||
| 3509 | { IFF_DYNAMIC, "dynamic" }, | ||
| 3510 | #endif | ||
| 3511 | { 0, 0 } | ||
| 3512 | }; | ||
| 3513 | |||
| 3514 | DEFUN ("network-interface-info", Fnetwork_interface_info, Snetwork_interface_info, 1, 1, 0, | ||
| 3515 | doc: /* Return information about network interface named IFNAME. | ||
| 3516 | The return value is a list (ADDR BCAST NETMASK HWADDR FLAGS), | ||
| 3517 | where ADDR is the layer 3 address, BCAST is the layer 3 broadcast address, | ||
| 3518 | NETMASK is the layer 3 network mask, HWADDR is the layer 2 addres, and | ||
| 3519 | FLAGS is the current flags of the interface. */) | ||
| 3520 | (ifname) | ||
| 3521 | Lisp_Object ifname; | ||
| 3522 | { | ||
| 3523 | struct ifreq rq; | ||
| 3524 | Lisp_Object res = Qnil; | ||
| 3525 | Lisp_Object elt; | ||
| 3526 | int s; | ||
| 3527 | int any = 0; | ||
| 3528 | |||
| 3529 | CHECK_STRING (ifname); | ||
| 3530 | |||
| 3531 | bzero (rq.ifr_name, sizeof rq.ifr_name); | ||
| 3532 | strncpy (rq.ifr_name, SDATA (ifname), sizeof (rq.ifr_name)); | ||
| 3533 | |||
| 3534 | s = socket (AF_INET, SOCK_STREAM, 0); | ||
| 3535 | if (s < 0) | ||
| 3536 | return Qnil; | ||
| 3537 | |||
| 3538 | elt = Qnil; | ||
| 3539 | #if defined(SIOCGIFFLAGS) && defined(HAVE_STRUCT_IFREQ_IFR_FLAGS) | ||
| 3540 | if (ioctl (s, SIOCGIFFLAGS, &rq) == 0) | ||
| 3541 | { | ||
| 3542 | int flags = rq.ifr_flags; | ||
| 3543 | struct ifflag_def *fp; | ||
| 3544 | int fnum; | ||
| 3545 | |||
| 3546 | any++; | ||
| 3547 | for (fp = ifflag_table; flags != 0 && fp; fp++) | ||
| 3548 | { | ||
| 3549 | if (flags & fp->flag_bit) | ||
| 3550 | { | ||
| 3551 | elt = Fcons (intern (fp->flag_sym), elt); | ||
| 3552 | flags -= fp->flag_bit; | ||
| 3553 | } | ||
| 3554 | } | ||
| 3555 | for (fnum = 0; flags && fnum < 32; fnum++) | ||
| 3556 | { | ||
| 3557 | if (flags & (1 << fnum)) | ||
| 3558 | { | ||
| 3559 | elt = Fcons (make_number (fnum), elt); | ||
| 3560 | } | ||
| 3561 | } | ||
| 3562 | } | ||
| 3563 | #endif | ||
| 3564 | res = Fcons (elt, res); | ||
| 3565 | |||
| 3566 | elt = Qnil; | ||
| 3567 | #if defined(SIOCGIFHWADDR) && defined(HAVE_STRUCT_IFREQ_IFR_HWADDR) | ||
| 3568 | if (ioctl (s, SIOCGIFHWADDR, &rq) == 0) | ||
| 3569 | { | ||
| 3570 | Lisp_Object hwaddr = Fmake_vector (make_number (6), Qnil); | ||
| 3571 | register struct Lisp_Vector *p = XVECTOR (hwaddr); | ||
| 3572 | int n; | ||
| 3573 | |||
| 3574 | any++; | ||
| 3575 | for (n = 0; n < 6; n++) | ||
| 3576 | p->contents[n] = make_number (((unsigned char *)&rq.ifr_hwaddr.sa_data[0])[n]); | ||
| 3577 | elt = Fcons (make_number (rq.ifr_hwaddr.sa_family), hwaddr); | ||
| 3578 | } | ||
| 3579 | #endif | ||
| 3580 | res = Fcons (elt, res); | ||
| 3581 | |||
| 3582 | elt = Qnil; | ||
| 3583 | #if defined(SIOCGIFNETMASK) && defined(ifr_netmask) | ||
| 3584 | if (ioctl (s, SIOCGIFNETMASK, &rq) == 0) | ||
| 3585 | { | ||
| 3586 | any++; | ||
| 3587 | elt = conv_sockaddr_to_lisp (&rq.ifr_netmask, sizeof (rq.ifr_netmask)); | ||
| 3588 | } | ||
| 3589 | #endif | ||
| 3590 | res = Fcons (elt, res); | ||
| 3591 | |||
| 3592 | elt = Qnil; | ||
| 3593 | #if defined(SIOCGIFBRDADDR) && defined(HAVE_STRUCT_IFREQ_IFR_BROADADDR) | ||
| 3594 | if (ioctl (s, SIOCGIFBRDADDR, &rq) == 0) | ||
| 3595 | { | ||
| 3596 | any++; | ||
| 3597 | elt = conv_sockaddr_to_lisp (&rq.ifr_broadaddr, sizeof (rq.ifr_broadaddr)); | ||
| 3598 | } | ||
| 3599 | #endif | ||
| 3600 | res = Fcons (elt, res); | ||
| 3601 | |||
| 3602 | elt = Qnil; | ||
| 3603 | #if defined(SIOCGIFADDR) && defined(HAVE_STRUCT_IFREQ_IFR_ADDR) | ||
| 3604 | if (ioctl (s, SIOCGIFADDR, &rq) == 0) | ||
| 3605 | { | ||
| 3606 | any++; | ||
| 3607 | elt = conv_sockaddr_to_lisp (&rq.ifr_addr, sizeof (rq.ifr_addr)); | ||
| 3608 | } | ||
| 3609 | #endif | ||
| 3610 | res = Fcons (elt, res); | ||
| 3611 | |||
| 3612 | close (s); | ||
| 3613 | |||
| 3614 | return any ? res : Qnil; | ||
| 3615 | } | ||
| 3616 | #endif | ||
| 3617 | #endif /* HAVE_SOCKETS */ | ||
| 3618 | |||
| 3360 | void | 3619 | void |
| 3361 | deactivate_process (proc) | 3620 | deactivate_process (proc) |
| 3362 | Lisp_Object proc; | 3621 | Lisp_Object proc; |
| @@ -3367,6 +3626,16 @@ deactivate_process (proc) | |||
| 3367 | inchannel = XINT (p->infd); | 3626 | inchannel = XINT (p->infd); |
| 3368 | outchannel = XINT (p->outfd); | 3627 | outchannel = XINT (p->outfd); |
| 3369 | 3628 | ||
| 3629 | #ifdef ADAPTIVE_READ_BUFFERING | ||
| 3630 | if (XINT (p->read_output_delay) > 0) | ||
| 3631 | { | ||
| 3632 | if (--process_output_delay_count < 0) | ||
| 3633 | process_output_delay_count = 0; | ||
| 3634 | XSETINT (p->read_output_delay, 0); | ||
| 3635 | p->read_output_skip = Qnil; | ||
| 3636 | } | ||
| 3637 | #endif | ||
| 3638 | |||
| 3370 | if (inchannel >= 0) | 3639 | if (inchannel >= 0) |
| 3371 | { | 3640 | { |
| 3372 | /* Beware SIGCHLD hereabouts. */ | 3641 | /* Beware SIGCHLD hereabouts. */ |
| @@ -3752,7 +4021,7 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display) | |||
| 3752 | register int channel, nfds; | 4021 | register int channel, nfds; |
| 3753 | static SELECT_TYPE Available; | 4022 | static SELECT_TYPE Available; |
| 3754 | static SELECT_TYPE Connecting; | 4023 | static SELECT_TYPE Connecting; |
| 3755 | int check_connect, no_avail; | 4024 | int check_connect, check_delay, no_avail; |
| 3756 | int xerrno; | 4025 | int xerrno; |
| 3757 | Lisp_Object proc; | 4026 | Lisp_Object proc; |
| 3758 | EMACS_TIME timeout, end_time; | 4027 | EMACS_TIME timeout, end_time; |
| @@ -3812,6 +4081,10 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display) | |||
| 3812 | Otherwise, do pending quit if requested. */ | 4081 | Otherwise, do pending quit if requested. */ |
| 3813 | if (XINT (read_kbd) >= 0) | 4082 | if (XINT (read_kbd) >= 0) |
| 3814 | QUIT; | 4083 | QUIT; |
| 4084 | #ifdef SYNC_INPUT | ||
| 4085 | else if (interrupt_input_pending) | ||
| 4086 | handle_async_input (); | ||
| 4087 | #endif | ||
| 3815 | 4088 | ||
| 3816 | /* Exit now if the cell we're waiting for became non-nil. */ | 4089 | /* Exit now if the cell we're waiting for became non-nil. */ |
| 3817 | if (! NILP (wait_for_cell) && ! NILP (XCAR (wait_for_cell))) | 4090 | if (! NILP (wait_for_cell) && ! NILP (XCAR (wait_for_cell))) |
| @@ -3981,7 +4254,7 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display) | |||
| 3981 | if (!NILP (wait_for_cell)) | 4254 | if (!NILP (wait_for_cell)) |
| 3982 | { | 4255 | { |
| 3983 | Available = non_process_wait_mask; | 4256 | Available = non_process_wait_mask; |
| 3984 | check_connect = 0; | 4257 | check_connect = check_delay = 0; |
| 3985 | } | 4258 | } |
| 3986 | else | 4259 | else |
| 3987 | { | 4260 | { |
| @@ -3990,6 +4263,7 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display) | |||
| 3990 | else | 4263 | else |
| 3991 | Available = input_wait_mask; | 4264 | Available = input_wait_mask; |
| 3992 | check_connect = (num_pending_connects > 0); | 4265 | check_connect = (num_pending_connects > 0); |
| 4266 | check_delay = wait_channel >= 0 ? 0 : process_output_delay_count; | ||
| 3993 | } | 4267 | } |
| 3994 | 4268 | ||
| 3995 | /* If frame size has changed or the window is newly mapped, | 4269 | /* If frame size has changed or the window is newly mapped, |
| @@ -4015,6 +4289,34 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display) | |||
| 4015 | { | 4289 | { |
| 4016 | if (check_connect) | 4290 | if (check_connect) |
| 4017 | Connecting = connect_wait_mask; | 4291 | Connecting = connect_wait_mask; |
| 4292 | |||
| 4293 | #ifdef ADAPTIVE_READ_BUFFERING | ||
| 4294 | if (process_output_skip && check_delay > 0) | ||
| 4295 | { | ||
| 4296 | int usecs = EMACS_USECS (timeout); | ||
| 4297 | if (EMACS_SECS (timeout) > 0 || usecs > READ_OUTPUT_DELAY_MAX) | ||
| 4298 | usecs = READ_OUTPUT_DELAY_MAX; | ||
| 4299 | for (channel = 0; check_delay > 0 && channel <= max_process_desc; channel++) | ||
| 4300 | { | ||
| 4301 | proc = chan_process[channel]; | ||
| 4302 | if (NILP (proc)) | ||
| 4303 | continue; | ||
| 4304 | if (XINT (XPROCESS (proc)->read_output_delay) > 0) | ||
| 4305 | { | ||
| 4306 | check_delay--; | ||
| 4307 | if (NILP (XPROCESS (proc)->read_output_skip)) | ||
| 4308 | continue; | ||
| 4309 | FD_CLR (channel, &Available); | ||
| 4310 | XPROCESS (proc)->read_output_skip = Qnil; | ||
| 4311 | if (XINT (XPROCESS (proc)->read_output_delay) < usecs) | ||
| 4312 | usecs = XINT (XPROCESS (proc)->read_output_delay); | ||
| 4313 | } | ||
| 4314 | } | ||
| 4315 | EMACS_SET_SECS_USECS (timeout, 0, usecs); | ||
| 4316 | process_output_skip = 0; | ||
| 4317 | } | ||
| 4318 | #endif | ||
| 4319 | |||
| 4018 | nfds = select (max (max_process_desc, max_keyboard_desc) + 1, | 4320 | nfds = select (max (max_process_desc, max_keyboard_desc) + 1, |
| 4019 | &Available, | 4321 | &Available, |
| 4020 | (check_connect ? &Connecting : (SELECT_TYPE *)0), | 4322 | (check_connect ? &Connecting : (SELECT_TYPE *)0), |
| @@ -4468,7 +4770,36 @@ read_process_output (proc, channel) | |||
| 4468 | else | 4770 | else |
| 4469 | #endif | 4771 | #endif |
| 4470 | if (proc_buffered_char[channel] < 0) | 4772 | if (proc_buffered_char[channel] < 0) |
| 4471 | nbytes = emacs_read (channel, chars + carryover, readmax - carryover); | 4773 | { |
| 4774 | nbytes = emacs_read (channel, chars + carryover, readmax - carryover); | ||
| 4775 | #ifdef ADAPTIVE_READ_BUFFERING | ||
| 4776 | if (!NILP (p->adaptive_read_buffering)) | ||
| 4777 | { | ||
| 4778 | int delay = XINT (p->read_output_delay); | ||
| 4779 | if (nbytes < 256) | ||
| 4780 | { | ||
| 4781 | if (delay < READ_OUTPUT_DELAY_MAX_MAX) | ||
| 4782 | { | ||
| 4783 | if (delay == 0) | ||
| 4784 | process_output_delay_count++; | ||
| 4785 | delay += READ_OUTPUT_DELAY_INCREMENT * 2; | ||
| 4786 | } | ||
| 4787 | } | ||
| 4788 | else if (delay > 0 && (nbytes == readmax - carryover)) | ||
| 4789 | { | ||
| 4790 | delay -= READ_OUTPUT_DELAY_INCREMENT; | ||
| 4791 | if (delay == 0) | ||
| 4792 | process_output_delay_count--; | ||
| 4793 | } | ||
| 4794 | XSETINT (p->read_output_delay, delay); | ||
| 4795 | if (delay) | ||
| 4796 | { | ||
| 4797 | p->read_output_skip = Qt; | ||
| 4798 | process_output_skip = 1; | ||
| 4799 | } | ||
| 4800 | } | ||
| 4801 | #endif | ||
| 4802 | } | ||
| 4472 | else | 4803 | else |
| 4473 | { | 4804 | { |
| 4474 | chars[carryover] = proc_buffered_char[channel]; | 4805 | chars[carryover] = proc_buffered_char[channel]; |
| @@ -4774,6 +5105,7 @@ send_process (proc, buf, len, object) | |||
| 4774 | volatile Lisp_Object object; | 5105 | volatile Lisp_Object object; |
| 4775 | { | 5106 | { |
| 4776 | /* Use volatile to protect variables from being clobbered by longjmp. */ | 5107 | /* Use volatile to protect variables from being clobbered by longjmp. */ |
| 5108 | struct Lisp_Process *p = XPROCESS (proc); | ||
| 4777 | int rv; | 5109 | int rv; |
| 4778 | struct coding_system *coding; | 5110 | struct coding_system *coding; |
| 4779 | struct gcpro gcpro1; | 5111 | struct gcpro gcpro1; |
| @@ -4781,20 +5113,17 @@ send_process (proc, buf, len, object) | |||
| 4781 | GCPRO1 (object); | 5113 | GCPRO1 (object); |
| 4782 | 5114 | ||
| 4783 | #ifdef VMS | 5115 | #ifdef VMS |
| 4784 | struct Lisp_Process *p = XPROCESS (proc); | ||
| 4785 | VMS_PROC_STUFF *vs, *get_vms_process_pointer(); | 5116 | VMS_PROC_STUFF *vs, *get_vms_process_pointer(); |
| 4786 | #endif /* VMS */ | 5117 | #endif /* VMS */ |
| 4787 | 5118 | ||
| 4788 | if (! NILP (XPROCESS (proc)->raw_status_low)) | 5119 | if (! NILP (p->raw_status_low)) |
| 4789 | update_status (XPROCESS (proc)); | 5120 | update_status (p); |
| 4790 | if (! EQ (XPROCESS (proc)->status, Qrun)) | 5121 | if (! EQ (p->status, Qrun)) |
| 4791 | error ("Process %s not running", | 5122 | error ("Process %s not running", SDATA (p->name)); |
| 4792 | SDATA (XPROCESS (proc)->name)); | 5123 | if (XINT (p->outfd) < 0) |
| 4793 | if (XINT (XPROCESS (proc)->outfd) < 0) | 5124 | error ("Output file descriptor of %s is closed", SDATA (p->name)); |
| 4794 | error ("Output file descriptor of %s is closed", | ||
| 4795 | SDATA (XPROCESS (proc)->name)); | ||
| 4796 | 5125 | ||
| 4797 | coding = proc_encode_coding_system[XINT (XPROCESS (proc)->outfd)]; | 5126 | coding = proc_encode_coding_system[XINT (p->outfd)]; |
| 4798 | Vlast_coding_system_used = CODING_ID_NAME (coding->id); | 5127 | Vlast_coding_system_used = CODING_ID_NAME (coding->id); |
| 4799 | 5128 | ||
| 4800 | if ((STRINGP (object) && STRING_MULTIBYTE (object)) | 5129 | if ((STRINGP (object) && STRING_MULTIBYTE (object)) |
| @@ -4802,14 +5131,12 @@ send_process (proc, buf, len, object) | |||
| 4802 | && !NILP (XBUFFER (object)->enable_multibyte_characters)) | 5131 | && !NILP (XBUFFER (object)->enable_multibyte_characters)) |
| 4803 | || EQ (object, Qt)) | 5132 | || EQ (object, Qt)) |
| 4804 | { | 5133 | { |
| 4805 | if (!EQ (Vlast_coding_system_used, | 5134 | if (!EQ (Vlast_coding_system_used, p->encode_coding_system)) |
| 4806 | XPROCESS (proc)->encode_coding_system)) | ||
| 4807 | /* The coding system for encoding was changed to raw-text | 5135 | /* The coding system for encoding was changed to raw-text |
| 4808 | because we sent a unibyte text previously. Now we are | 5136 | because we sent a unibyte text previously. Now we are |
| 4809 | sending a multibyte text, thus we must encode it by the | 5137 | sending a multibyte text, thus we must encode it by the |
| 4810 | original coding system specified for the current | 5138 | original coding system specified for the current process. */ |
| 4811 | process. */ | 5139 | setup_coding_system (p->encode_coding_system, coding); |
| 4812 | setup_coding_system (XPROCESS (proc)->encode_coding_system, coding); | ||
| 4813 | coding->src_multibyte = 1; | 5140 | coding->src_multibyte = 1; |
| 4814 | } | 5141 | } |
| 4815 | else | 5142 | else |
| @@ -4880,8 +5207,7 @@ send_process (proc, buf, len, object) | |||
| 4880 | if (pty_max_bytes == 0) | 5207 | if (pty_max_bytes == 0) |
| 4881 | { | 5208 | { |
| 4882 | #if defined (HAVE_FPATHCONF) && defined (_PC_MAX_CANON) | 5209 | #if defined (HAVE_FPATHCONF) && defined (_PC_MAX_CANON) |
| 4883 | pty_max_bytes = fpathconf (XFASTINT (XPROCESS (proc)->outfd), | 5210 | pty_max_bytes = fpathconf (XFASTINT (p->outfd), _PC_MAX_CANON); |
| 4884 | _PC_MAX_CANON); | ||
| 4885 | if (pty_max_bytes < 0) | 5211 | if (pty_max_bytes < 0) |
| 4886 | pty_max_bytes = 250; | 5212 | pty_max_bytes = 250; |
| 4887 | #else | 5213 | #else |
| @@ -4904,7 +5230,7 @@ send_process (proc, buf, len, object) | |||
| 4904 | 5230 | ||
| 4905 | /* Decide how much data we can send in one batch. | 5231 | /* Decide how much data we can send in one batch. |
| 4906 | Long lines need to be split into multiple batches. */ | 5232 | Long lines need to be split into multiple batches. */ |
| 4907 | if (!NILP (XPROCESS (proc)->pty_flag)) | 5233 | if (!NILP (p->pty_flag)) |
| 4908 | { | 5234 | { |
| 4909 | /* Starting this at zero is always correct when not the first | 5235 | /* Starting this at zero is always correct when not the first |
| 4910 | iteration because the previous iteration ended by sending C-d. | 5236 | iteration because the previous iteration ended by sending C-d. |
| @@ -4933,7 +5259,7 @@ send_process (proc, buf, len, object) | |||
| 4933 | /* Send this batch, using one or more write calls. */ | 5259 | /* Send this batch, using one or more write calls. */ |
| 4934 | while (this > 0) | 5260 | while (this > 0) |
| 4935 | { | 5261 | { |
| 4936 | int outfd = XINT (XPROCESS (proc)->outfd); | 5262 | int outfd = XINT (p->outfd); |
| 4937 | old_sigpipe = (SIGTYPE (*) ()) signal (SIGPIPE, send_process_trap); | 5263 | old_sigpipe = (SIGTYPE (*) ()) signal (SIGPIPE, send_process_trap); |
| 4938 | #ifdef DATAGRAM_SOCKETS | 5264 | #ifdef DATAGRAM_SOCKETS |
| 4939 | if (DATAGRAM_CHAN_P (outfd)) | 5265 | if (DATAGRAM_CHAN_P (outfd)) |
| @@ -4946,7 +5272,18 @@ send_process (proc, buf, len, object) | |||
| 4946 | } | 5272 | } |
| 4947 | else | 5273 | else |
| 4948 | #endif | 5274 | #endif |
| 4949 | rv = emacs_write (outfd, (char *) buf, this); | 5275 | { |
| 5276 | rv = emacs_write (outfd, (char *) buf, this); | ||
| 5277 | #ifdef ADAPTIVE_READ_BUFFERING | ||
| 5278 | if (XINT (p->read_output_delay) > 0 | ||
| 5279 | && EQ (p->adaptive_read_buffering, Qt)) | ||
| 5280 | { | ||
| 5281 | XSETFASTINT (p->read_output_delay, 0); | ||
| 5282 | process_output_delay_count--; | ||
| 5283 | p->read_output_skip = Qnil; | ||
| 5284 | } | ||
| 5285 | #endif | ||
| 5286 | } | ||
| 4950 | signal (SIGPIPE, old_sigpipe); | 5287 | signal (SIGPIPE, old_sigpipe); |
| 4951 | 5288 | ||
| 4952 | if (rv < 0) | 5289 | if (rv < 0) |
| @@ -4987,8 +5324,7 @@ send_process (proc, buf, len, object) | |||
| 4987 | if (errno == EAGAIN) | 5324 | if (errno == EAGAIN) |
| 4988 | { | 5325 | { |
| 4989 | int flags = FWRITE; | 5326 | int flags = FWRITE; |
| 4990 | ioctl (XINT (XPROCESS (proc)->outfd), TIOCFLUSH, | 5327 | ioctl (XINT (p->outfd), TIOCFLUSH, &flags); |
| 4991 | &flags); | ||
| 4992 | } | 5328 | } |
| 4993 | #endif /* BROKEN_PTY_READ_AFTER_EAGAIN */ | 5329 | #endif /* BROKEN_PTY_READ_AFTER_EAGAIN */ |
| 4994 | 5330 | ||
| @@ -5033,18 +5369,17 @@ send_process (proc, buf, len, object) | |||
| 5033 | { | 5369 | { |
| 5034 | #ifndef VMS | 5370 | #ifndef VMS |
| 5035 | proc = process_sent_to; | 5371 | proc = process_sent_to; |
| 5372 | p = XPROCESS (proc); | ||
| 5036 | #endif | 5373 | #endif |
| 5037 | XPROCESS (proc)->raw_status_low = Qnil; | 5374 | p->raw_status_low = Qnil; |
| 5038 | XPROCESS (proc)->raw_status_high = Qnil; | 5375 | p->raw_status_high = Qnil; |
| 5039 | XPROCESS (proc)->status = Fcons (Qexit, Fcons (make_number (256), Qnil)); | 5376 | p->status = Fcons (Qexit, Fcons (make_number (256), Qnil)); |
| 5040 | XSETINT (XPROCESS (proc)->tick, ++process_tick); | 5377 | XSETINT (p->tick, ++process_tick); |
| 5041 | deactivate_process (proc); | 5378 | deactivate_process (proc); |
| 5042 | #ifdef VMS | 5379 | #ifdef VMS |
| 5043 | error ("Error writing to process %s; closed it", | 5380 | error ("Error writing to process %s; closed it", SDATA (p->name)); |
| 5044 | SDATA (XPROCESS (proc)->name)); | ||
| 5045 | #else | 5381 | #else |
| 5046 | error ("SIGPIPE raised on process %s; closed it", | 5382 | error ("SIGPIPE raised on process %s; closed it", SDATA (p->name)); |
| 5047 | SDATA (XPROCESS (proc)->name)); | ||
| 5048 | #endif | 5383 | #endif |
| 5049 | } | 5384 | } |
| 5050 | 5385 | ||
| @@ -5758,7 +6093,10 @@ kill_buffer_processes (buffer) | |||
| 5758 | queued and the signal-catching function will be continually | 6093 | queued and the signal-catching function will be continually |
| 5759 | reentered until the queue is empty". Invoking signal() causes the | 6094 | reentered until the queue is empty". Invoking signal() causes the |
| 5760 | kernel to reexamine the SIGCLD queue. Fred Fish, UniSoft Systems | 6095 | kernel to reexamine the SIGCLD queue. Fred Fish, UniSoft Systems |
| 5761 | Inc. */ | 6096 | Inc. |
| 6097 | |||
| 6098 | ** Malloc WARNING: This should never call malloc either directly or | ||
| 6099 | indirectly; if it does, that is a bug */ | ||
| 5762 | 6100 | ||
| 5763 | SIGTYPE | 6101 | SIGTYPE |
| 5764 | sigchld_handler (signo) | 6102 | sigchld_handler (signo) |
| @@ -5876,18 +6214,7 @@ sigchld_handler (signo) | |||
| 5876 | if (WIFEXITED (w)) | 6214 | if (WIFEXITED (w)) |
| 5877 | synch_process_retcode = WRETCODE (w); | 6215 | synch_process_retcode = WRETCODE (w); |
| 5878 | else if (WIFSIGNALED (w)) | 6216 | else if (WIFSIGNALED (w)) |
| 5879 | { | 6217 | synch_process_termsig = WTERMSIG (w); |
| 5880 | int code = WTERMSIG (w); | ||
| 5881 | char *signame; | ||
| 5882 | |||
| 5883 | synchronize_system_messages_locale (); | ||
| 5884 | signame = strsignal (code); | ||
| 5885 | |||
| 5886 | if (signame == 0) | ||
| 5887 | signame = "unknown"; | ||
| 5888 | |||
| 5889 | synch_process_death = signame; | ||
| 5890 | } | ||
| 5891 | 6218 | ||
| 5892 | /* Tell wait_reading_process_input that it needs to wake up and | 6219 | /* Tell wait_reading_process_input that it needs to wake up and |
| 5893 | look around. */ | 6220 | look around. */ |
| @@ -6281,6 +6608,11 @@ init_process () | |||
| 6281 | FD_ZERO (&non_process_wait_mask); | 6608 | FD_ZERO (&non_process_wait_mask); |
| 6282 | max_process_desc = 0; | 6609 | max_process_desc = 0; |
| 6283 | 6610 | ||
| 6611 | #ifdef ADAPTIVE_READ_BUFFERING | ||
| 6612 | process_output_delay_count = 0; | ||
| 6613 | process_output_skip = 0; | ||
| 6614 | #endif | ||
| 6615 | |||
| 6284 | FD_SET (0, &input_wait_mask); | 6616 | FD_SET (0, &input_wait_mask); |
| 6285 | 6617 | ||
| 6286 | Vprocess_alist = Qnil; | 6618 | Vprocess_alist = Qnil; |
| @@ -6298,6 +6630,8 @@ init_process () | |||
| 6298 | #ifdef HAVE_SOCKETS | 6630 | #ifdef HAVE_SOCKETS |
| 6299 | { | 6631 | { |
| 6300 | Lisp_Object subfeatures = Qnil; | 6632 | Lisp_Object subfeatures = Qnil; |
| 6633 | struct socket_options *sopt; | ||
| 6634 | |||
| 6301 | #define ADD_SUBFEATURE(key, val) \ | 6635 | #define ADD_SUBFEATURE(key, val) \ |
| 6302 | subfeatures = Fcons (Fcons (key, Fcons (val, Qnil)), subfeatures) | 6636 | subfeatures = Fcons (Fcons (key, Fcons (val, Qnil)), subfeatures) |
| 6303 | 6637 | ||
| @@ -6316,30 +6650,10 @@ init_process () | |||
| 6316 | #if !defined(TERM) && (defined(O_NONBLOCK) || defined(O_NDELAY)) | 6650 | #if !defined(TERM) && (defined(O_NONBLOCK) || defined(O_NDELAY)) |
| 6317 | ADD_SUBFEATURE (QCserver, Qt); | 6651 | ADD_SUBFEATURE (QCserver, Qt); |
| 6318 | #endif | 6652 | #endif |
| 6319 | #ifdef SO_BINDTODEVICE | 6653 | |
| 6320 | ADD_SUBFEATURE (QCoptions, intern ("bindtodevice")); | 6654 | for (sopt = socket_options; sopt->name; sopt++) |
| 6321 | #endif | 6655 | subfeatures = Fcons (intern (sopt->name), subfeatures); |
| 6322 | #ifdef SO_BROADCAST | 6656 | |
| 6323 | ADD_SUBFEATURE (QCoptions, intern ("broadcast")); | ||
| 6324 | #endif | ||
| 6325 | #ifdef SO_DONTROUTE | ||
| 6326 | ADD_SUBFEATURE (QCoptions, intern ("dontroute")); | ||
| 6327 | #endif | ||
| 6328 | #ifdef SO_KEEPALIVE | ||
| 6329 | ADD_SUBFEATURE (QCoptions, intern ("keepalive")); | ||
| 6330 | #endif | ||
| 6331 | #ifdef SO_LINGER | ||
| 6332 | ADD_SUBFEATURE (QCoptions, intern ("linger")); | ||
| 6333 | #endif | ||
| 6334 | #ifdef SO_OOBINLINE | ||
| 6335 | ADD_SUBFEATURE (QCoptions, intern ("oobinline")); | ||
| 6336 | #endif | ||
| 6337 | #ifdef SO_PRIORITY | ||
| 6338 | ADD_SUBFEATURE (QCoptions, intern ("priority")); | ||
| 6339 | #endif | ||
| 6340 | #ifdef SO_REUSEADDR | ||
| 6341 | ADD_SUBFEATURE (QCoptions, intern ("reuseaddr")); | ||
| 6342 | #endif | ||
| 6343 | Fprovide (intern ("make-network-process"), subfeatures); | 6657 | Fprovide (intern ("make-network-process"), subfeatures); |
| 6344 | } | 6658 | } |
| 6345 | #endif /* HAVE_SOCKETS */ | 6659 | #endif /* HAVE_SOCKETS */ |
| @@ -6432,6 +6746,20 @@ then a pipe is used in any case. | |||
| 6432 | The value takes effect when `start-process' is called. */); | 6746 | The value takes effect when `start-process' is called. */); |
| 6433 | Vprocess_connection_type = Qt; | 6747 | Vprocess_connection_type = Qt; |
| 6434 | 6748 | ||
| 6749 | #ifdef ADAPTIVE_READ_BUFFERING | ||
| 6750 | DEFVAR_LISP ("process-adaptive-read-buffering", &Vprocess_adaptive_read_buffering, | ||
| 6751 | doc: /* If non-nil, improve receive buffering by delaying after short reads. | ||
| 6752 | On some systems, when emacs reads the output from a subprocess, the output data | ||
| 6753 | is read in very small blocks, potentially resulting in very poor performance. | ||
| 6754 | This behaviour can be remedied to some extent by setting this variable to a | ||
| 6755 | non-nil value, as it will automatically delay reading from such processes, to | ||
| 6756 | allowing them to produce more output before emacs tries to read it. | ||
| 6757 | If the value is t, the delay is reset after each write to the process; any other | ||
| 6758 | non-nil value means that the delay is not reset on write. | ||
| 6759 | The variable takes effect when `start-process' is called. */); | ||
| 6760 | Vprocess_adaptive_read_buffering = Qt; | ||
| 6761 | #endif | ||
| 6762 | |||
| 6435 | defsubr (&Sprocessp); | 6763 | defsubr (&Sprocessp); |
| 6436 | defsubr (&Sget_process); | 6764 | defsubr (&Sget_process); |
| 6437 | defsubr (&Sget_buffer_process); | 6765 | defsubr (&Sget_buffer_process); |
| @@ -6461,10 +6789,18 @@ The value takes effect when `start-process' is called. */); | |||
| 6461 | defsubr (&Sprocess_list); | 6789 | defsubr (&Sprocess_list); |
| 6462 | defsubr (&Sstart_process); | 6790 | defsubr (&Sstart_process); |
| 6463 | #ifdef HAVE_SOCKETS | 6791 | #ifdef HAVE_SOCKETS |
| 6464 | defsubr (&Sset_network_process_options); | 6792 | defsubr (&Sset_network_process_option); |
| 6465 | defsubr (&Smake_network_process); | 6793 | defsubr (&Smake_network_process); |
| 6466 | defsubr (&Sformat_network_address); | 6794 | defsubr (&Sformat_network_address); |
| 6467 | #endif /* HAVE_SOCKETS */ | 6795 | #endif /* HAVE_SOCKETS */ |
| 6796 | #if defined(HAVE_SOCKETS) && defined(HAVE_NET_IF_H) && defined(HAVE_SYS_IOCTL_H) | ||
| 6797 | #ifdef SIOCGIFCONF | ||
| 6798 | defsubr (&Snetwork_interface_list); | ||
| 6799 | #endif | ||
| 6800 | #if defined(SIOCGIFADDR) || defined(SIOCGIFHWADDR) || defined(SIOCGIFFLAGS) | ||
| 6801 | defsubr (&Snetwork_interface_info); | ||
| 6802 | #endif | ||
| 6803 | #endif /* HAVE_SOCKETS ... */ | ||
| 6468 | #ifdef DATAGRAM_SOCKETS | 6804 | #ifdef DATAGRAM_SOCKETS |
| 6469 | defsubr (&Sprocess_datagram_address); | 6805 | defsubr (&Sprocess_datagram_address); |
| 6470 | defsubr (&Sset_process_datagram_address); | 6806 | defsubr (&Sset_process_datagram_address); |
| @@ -6796,3 +7132,6 @@ syms_of_process () | |||
| 6796 | 7132 | ||
| 6797 | 7133 | ||
| 6798 | #endif /* not subprocesses */ | 7134 | #endif /* not subprocesses */ |
| 7135 | |||
| 7136 | /* arch-tag: 3706c011-7b9a-4117-bd4f-59e7f701a4c4 | ||
| 7137 | (do not change this comment) */ | ||