diff options
| author | Kim F. Storm | 2003-09-16 23:05:24 +0000 |
|---|---|---|
| committer | Kim F. Storm | 2003-09-16 23:05:24 +0000 |
| commit | 2ccf3102d2ebc6f60838c80cb44b5557851c2168 (patch) | |
| tree | d47f1285b7e13eb6734e464dd0f3e2b3fd277e0d /src/process.c | |
| parent | e9c50801463ba7c4efe878c82398c68e243a02a4 (diff) | |
| download | emacs-2ccf3102d2ebc6f60838c80cb44b5557851c2168.tar.gz emacs-2ccf3102d2ebc6f60838c80cb44b5557851c2168.zip | |
(Fset_process_sentinel): Add sentinel to childp plist
for network process.
(socket_options): Add `:' prefix to option names. Add optbit field.
(set_socket_option): Remove no_error arg and special handling of s < 0.
Return 1<<optbit for known option, 0 for unknown.
Do not interpret 0 as false for boolean option (only nil).
Pass failed option and value to report_file_error.
(Fset_network_process_options): Replaced by Fset_network_process_option.
(Fset_network_process_option): New function to set just one option.
(Fmake_network_process): Allow :coding arg to be a cons.
Allow :server arg to be an integer specifying backlog size.
Remove :options arg, and allow options to be specified directly
as :KEY, VALUE pairs. Parse these options before binding socket.
As before, :reuseaddr t is default for a server process, but this
can now be disabled by specifying :reuseaddr nil.
(Fnetwork_interface_info): Rename from Fget_network_interface_info.
(init_process): Availability of network options is now checked with
simpler syntax (featurep 'make-network-process :OPTION); use loop to
setup features.
(syms_of_process): Fix defsubr's for the replaced functions.
Diffstat (limited to 'src/process.c')
| -rw-r--r-- | src/process.c | 412 |
1 files changed, 181 insertions, 231 deletions
diff --git a/src/process.c b/src/process.c index fdbdaaba2f7..23ef1e9059e 100644 --- a/src/process.c +++ b/src/process.c | |||
| @@ -965,8 +965,14 @@ It gets two arguments: the process, and a string describing the change. */) | |||
| 965 | (process, sentinel) | 965 | (process, sentinel) |
| 966 | register Lisp_Object process, sentinel; | 966 | register Lisp_Object process, sentinel; |
| 967 | { | 967 | { |
| 968 | struct Lisp_Process *p; | ||
| 969 | |||
| 968 | CHECK_PROCESS (process); | 970 | CHECK_PROCESS (process); |
| 969 | XPROCESS (process)->sentinel = sentinel; | 971 | p = XPROCESS (process); |
| 972 | |||
| 973 | p->sentinel = sentinel; | ||
| 974 | if (NETCONN1_P (p)) | ||
| 975 | p->childp = Fplist_put (p->childp, QCsentinel, sentinel); | ||
| 970 | return sentinel; | 976 | return sentinel; |
| 971 | } | 977 | } |
| 972 | 978 | ||
| @@ -2308,233 +2314,158 @@ static struct socket_options { | |||
| 2308 | /* The name of this option. Should be lowercase version of option | 2314 | /* The name of this option. Should be lowercase version of option |
| 2309 | name without SO_ prefix. */ | 2315 | name without SO_ prefix. */ |
| 2310 | char *name; | 2316 | char *name; |
| 2311 | /* Length of name. */ | ||
| 2312 | int nlen; | ||
| 2313 | /* Option level SOL_... */ | 2317 | /* Option level SOL_... */ |
| 2314 | int optlevel; | 2318 | int optlevel; |
| 2315 | /* Option number SO_... */ | 2319 | /* Option number SO_... */ |
| 2316 | int optnum; | 2320 | int optnum; |
| 2317 | enum { SOPT_UNKNOWN, SOPT_BOOL, SOPT_INT, SOPT_STR, SOPT_LINGER } opttype; | 2321 | enum { SOPT_UNKNOWN, SOPT_BOOL, SOPT_INT, SOPT_STR, SOPT_LINGER } opttype; |
| 2322 | enum { OPIX_NONE=0, OPIX_MISC=1, OPIX_REUSEADDR=2 } optbit; | ||
| 2318 | } socket_options[] = | 2323 | } socket_options[] = |
| 2319 | { | 2324 | { |
| 2320 | #ifdef SO_BINDTODEVICE | 2325 | #ifdef SO_BINDTODEVICE |
| 2321 | { "bindtodevice", 12, SOL_SOCKET, SO_BINDTODEVICE, SOPT_STR }, | 2326 | { ":bindtodevice", SOL_SOCKET, SO_BINDTODEVICE, SOPT_STR, OPIX_MISC }, |
| 2322 | #endif | 2327 | #endif |
| 2323 | #ifdef SO_BROADCAST | 2328 | #ifdef SO_BROADCAST |
| 2324 | { "broadcast", 9, SOL_SOCKET, SO_BROADCAST, SOPT_BOOL }, | 2329 | { ":broadcast", SOL_SOCKET, SO_BROADCAST, SOPT_BOOL, OPIX_MISC }, |
| 2325 | #endif | 2330 | #endif |
| 2326 | #ifdef SO_DONTROUTE | 2331 | #ifdef SO_DONTROUTE |
| 2327 | { "dontroute", 9, SOL_SOCKET, SO_DONTROUTE, SOPT_BOOL }, | 2332 | { ":dontroute", SOL_SOCKET, SO_DONTROUTE, SOPT_BOOL, OPIX_MISC }, |
| 2328 | #endif | 2333 | #endif |
| 2329 | #ifdef SO_KEEPALIVE | 2334 | #ifdef SO_KEEPALIVE |
| 2330 | { "keepalive", 9, SOL_SOCKET, SO_KEEPALIVE, SOPT_BOOL }, | 2335 | { ":keepalive", SOL_SOCKET, SO_KEEPALIVE, SOPT_BOOL, OPIX_MISC }, |
| 2331 | #endif | 2336 | #endif |
| 2332 | #ifdef SO_LINGER | 2337 | #ifdef SO_LINGER |
| 2333 | { "linger", 6, SOL_SOCKET, SO_LINGER, SOPT_LINGER }, | 2338 | { ":linger", SOL_SOCKET, SO_LINGER, SOPT_LINGER, OPIX_MISC }, |
| 2334 | #endif | 2339 | #endif |
| 2335 | #ifdef SO_OOBINLINE | 2340 | #ifdef SO_OOBINLINE |
| 2336 | { "oobinline", 9, SOL_SOCKET, SO_OOBINLINE, SOPT_BOOL }, | 2341 | { ":oobinline", SOL_SOCKET, SO_OOBINLINE, SOPT_BOOL, OPIX_MISC }, |
| 2337 | #endif | 2342 | #endif |
| 2338 | #ifdef SO_PRIORITY | 2343 | #ifdef SO_PRIORITY |
| 2339 | { "priority", 8, SOL_SOCKET, SO_PRIORITY, SOPT_INT }, | 2344 | { ":priority", SOL_SOCKET, SO_PRIORITY, SOPT_INT, OPIX_MISC }, |
| 2340 | #endif | 2345 | #endif |
| 2341 | #ifdef SO_REUSEADDR | 2346 | #ifdef SO_REUSEADDR |
| 2342 | { "reuseaddr", 9, SOL_SOCKET, SO_REUSEADDR, SOPT_BOOL }, | 2347 | { ":reuseaddr", SOL_SOCKET, SO_REUSEADDR, SOPT_BOOL, OPIX_REUSEADDR }, |
| 2343 | #endif | 2348 | #endif |
| 2344 | { 0, 0, 0, 0, SOPT_UNKNOWN } | 2349 | { 0, 0, 0, SOPT_UNKNOWN, OPIX_NONE } |
| 2345 | }; | 2350 | }; |
| 2346 | 2351 | ||
| 2347 | /* Process list of socket options OPTS on socket S. | 2352 | /* Set option OPT to value VAL on socket S. |
| 2348 | Only check if options are supported is S < 0. | ||
| 2349 | If NO_ERROR is non-zero, continue silently if an option | ||
| 2350 | cannot be set. | ||
| 2351 | 2353 | ||
| 2352 | Each element specifies one option. An element is either a string | 2354 | Returns (1<<socket_options[OPT].optbit) if option is known, 0 otherwise. |
| 2353 | "OPTION=VALUE" or a cons (OPTION . VALUE) where OPTION is a string | 2355 | Signals an error if setting a known option fails. |
| 2354 | or a symbol. */ | 2356 | */ |
| 2355 | 2357 | ||
| 2356 | static int | 2358 | static int |
| 2357 | set_socket_options (s, opts, no_error) | 2359 | set_socket_option (s, opt, val) |
| 2358 | int s; | 2360 | int s; |
| 2359 | Lisp_Object opts; | 2361 | Lisp_Object opt, val; |
| 2360 | int no_error; | ||
| 2361 | { | 2362 | { |
| 2362 | if (!CONSP (opts)) | 2363 | char *name; |
| 2363 | opts = Fcons (opts, Qnil); | 2364 | struct socket_options *sopt; |
| 2365 | int ret = 0; | ||
| 2364 | 2366 | ||
| 2365 | while (CONSP (opts)) | 2367 | CHECK_SYMBOL (opt); |
| 2366 | { | ||
| 2367 | Lisp_Object opt; | ||
| 2368 | Lisp_Object val; | ||
| 2369 | char *name, *arg; | ||
| 2370 | struct socket_options *sopt; | ||
| 2371 | int ret = 0; | ||
| 2372 | |||
| 2373 | opt = XCAR (opts); | ||
| 2374 | opts = XCDR (opts); | ||
| 2375 | |||
| 2376 | name = 0; | ||
| 2377 | val = Qt; | ||
| 2378 | if (CONSP (opt)) | ||
| 2379 | { | ||
| 2380 | val = XCDR (opt); | ||
| 2381 | opt = XCAR (opt); | ||
| 2382 | } | ||
| 2383 | if (STRINGP (opt)) | ||
| 2384 | name = (char *) SDATA (opt); | ||
| 2385 | else if (SYMBOLP (opt)) | ||
| 2386 | name = (char *) SDATA (SYMBOL_NAME (opt)); | ||
| 2387 | else { | ||
| 2388 | error ("Mal-formed option list"); | ||
| 2389 | return 0; | ||
| 2390 | } | ||
| 2391 | 2368 | ||
| 2392 | if (strncmp (name, "no", 2) == 0) | 2369 | name = (char *) SDATA (SYMBOL_NAME (opt)); |
| 2393 | { | 2370 | for (sopt = socket_options; sopt->name; sopt++) |
| 2394 | val = Qnil; | 2371 | if (strcmp (name, sopt->name) == 0) |
| 2395 | name += 2; | 2372 | break; |
| 2396 | } | ||
| 2397 | |||
| 2398 | arg = 0; | ||
| 2399 | for (sopt = socket_options; sopt->name; sopt++) | ||
| 2400 | if (strncmp (name, sopt->name, sopt->nlen) == 0) | ||
| 2401 | { | ||
| 2402 | if (name[sopt->nlen] == 0) | ||
| 2403 | break; | ||
| 2404 | if (name[sopt->nlen] == '=') | ||
| 2405 | { | ||
| 2406 | arg = name + sopt->nlen + 1; | ||
| 2407 | break; | ||
| 2408 | } | ||
| 2409 | } | ||
| 2410 | 2373 | ||
| 2411 | switch (sopt->opttype) | 2374 | switch (sopt->opttype) |
| 2412 | { | 2375 | { |
| 2413 | case SOPT_BOOL: | 2376 | case SOPT_BOOL: |
| 2414 | { | 2377 | { |
| 2415 | int optval; | 2378 | int optval; |
| 2416 | if (s < 0) | 2379 | optval = NILP (val) ? 0 : 1; |
| 2417 | return 1; | 2380 | ret = setsockopt (s, sopt->optlevel, sopt->optnum, |
| 2418 | if (arg) | 2381 | &optval, sizeof (optval)); |
| 2419 | optval = (*arg == '0' || *arg == 'n') ? 0 : 1; | 2382 | break; |
| 2420 | else if (INTEGERP (val)) | 2383 | } |
| 2421 | optval = XINT (val) == 0 ? 0 : 1; | ||
| 2422 | else | ||
| 2423 | optval = NILP (val) ? 0 : 1; | ||
| 2424 | ret = setsockopt (s, sopt->optlevel, sopt->optnum, | ||
| 2425 | &optval, sizeof (optval)); | ||
| 2426 | break; | ||
| 2427 | } | ||
| 2428 | 2384 | ||
| 2429 | case SOPT_INT: | 2385 | case SOPT_INT: |
| 2430 | { | 2386 | { |
| 2431 | int optval; | 2387 | int optval; |
| 2432 | if (arg) | 2388 | if (INTEGERP (val)) |
| 2433 | optval = atoi(arg); | 2389 | optval = XINT (val); |
| 2434 | else if (INTEGERP (val)) | 2390 | else |
| 2435 | optval = XINT (val); | 2391 | error ("Bad option value for %s", name); |
| 2436 | else | 2392 | ret = setsockopt (s, sopt->optlevel, sopt->optnum, |
| 2437 | error ("Bad option argument for %s", name); | 2393 | &optval, sizeof (optval)); |
| 2438 | if (s < 0) | 2394 | break; |
| 2439 | return 1; | 2395 | } |
| 2440 | ret = setsockopt (s, sopt->optlevel, sopt->optnum, | ||
| 2441 | &optval, sizeof (optval)); | ||
| 2442 | break; | ||
| 2443 | } | ||
| 2444 | 2396 | ||
| 2445 | case SOPT_STR: | 2397 | case SOPT_STR: |
| 2446 | { | 2398 | { |
| 2447 | if (!arg) | 2399 | char *arg; |
| 2448 | { | 2400 | |
| 2449 | if (NILP (val)) | 2401 | if (NILP (val)) |
| 2450 | arg = ""; | 2402 | arg = ""; |
| 2451 | else if (STRINGP (val)) | 2403 | else if (STRINGP (val)) |
| 2452 | arg = (char *) SDATA (val); | 2404 | arg = (char *) SDATA (val); |
| 2453 | else if (XSYMBOL (val)) | 2405 | else if (XSYMBOL (val)) |
| 2454 | arg = (char *) SDATA (SYMBOL_NAME (val)); | 2406 | arg = (char *) SDATA (SYMBOL_NAME (val)); |
| 2455 | else | 2407 | else |
| 2456 | error ("Invalid argument to %s option", name); | 2408 | error ("Bad option value for %s", name); |
| 2457 | } | 2409 | ret = setsockopt (s, sopt->optlevel, sopt->optnum, |
| 2458 | ret = setsockopt (s, sopt->optlevel, sopt->optnum, | 2410 | arg, strlen (arg)); |
| 2459 | arg, strlen (arg)); | 2411 | } |
| 2460 | } | ||
| 2461 | 2412 | ||
| 2462 | #ifdef SO_LINGER | 2413 | #ifdef SO_LINGER |
| 2463 | case SOPT_LINGER: | 2414 | case SOPT_LINGER: |
| 2464 | { | 2415 | { |
| 2465 | struct linger linger; | 2416 | struct linger linger; |
| 2466 | |||
| 2467 | linger.l_onoff = 1; | ||
| 2468 | linger.l_linger = 0; | ||
| 2469 | |||
| 2470 | if (s < 0) | ||
| 2471 | return 1; | ||
| 2472 | 2417 | ||
| 2473 | if (arg) | 2418 | linger.l_onoff = 1; |
| 2474 | { | 2419 | linger.l_linger = 0; |
| 2475 | if (*arg == 'n' || *arg == 't' || *arg == 'y') | 2420 | if (INTEGERP (val)) |
| 2476 | linger.l_onoff = (*arg == 'n') ? 0 : 1; | 2421 | linger.l_linger = XINT (val); |
| 2477 | else | 2422 | else |
| 2478 | linger.l_linger = atoi(arg); | 2423 | linger.l_onoff = NILP (val) ? 0 : 1; |
| 2479 | } | 2424 | ret = setsockopt (s, sopt->optlevel, sopt->optnum, |
| 2480 | else if (INTEGERP (val)) | 2425 | &linger, sizeof (linger)); |
| 2481 | linger.l_linger = XINT (val); | 2426 | break; |
| 2482 | else | 2427 | } |
| 2483 | linger.l_onoff = NILP (val) ? 0 : 1; | ||
| 2484 | ret = setsockopt (s, sopt->optlevel, sopt->optnum, | ||
| 2485 | &linger, sizeof (linger)); | ||
| 2486 | break; | ||
| 2487 | } | ||
| 2488 | #endif | 2428 | #endif |
| 2489 | default: | 2429 | |
| 2490 | if (s < 0) | 2430 | default: |
| 2491 | return 0; | 2431 | return 0; |
| 2492 | if (no_error) | ||
| 2493 | continue; | ||
| 2494 | error ("Unsupported option: %s", name); | ||
| 2495 | } | ||
| 2496 | if (ret < 0 && ! no_error) | ||
| 2497 | report_file_error ("Cannot set network option: %s", opt); | ||
| 2498 | } | 2432 | } |
| 2499 | return 1; | 2433 | |
| 2434 | if (ret < 0) | ||
| 2435 | report_file_error ("Cannot set network option", | ||
| 2436 | Fcons (opt, Fcons (val, Qnil))); | ||
| 2437 | return (1 << sopt->optbit); | ||
| 2500 | } | 2438 | } |
| 2501 | 2439 | ||
| 2502 | DEFUN ("set-network-process-options", | 2440 | |
| 2503 | Fset_network_process_options, Sset_network_process_options, | 2441 | DEFUN ("set-network-process-option", |
| 2504 | 1, MANY, 0, | 2442 | Fset_network_process_option, Sset_network_process_option, |
| 2505 | doc: /* Set one or more options for network process PROCESS. | 2443 | 3, 4, 0, |
| 2506 | Each option is either a string "OPT=VALUE" or a cons (OPT . VALUE). | 2444 | doc: /* For network process PROCESS set option OPTION to value VALUE. |
| 2507 | A boolean value is false if it either zero or nil, true otherwise. | 2445 | See `make-network-process' for a list of options and values. |
| 2508 | 2446 | If optional fourth arg NO-ERROR is non-nil, don't signal an error if | |
| 2509 | The following options are known. Consult the relevant system manual | 2447 | OPTION is not a supported option, return nil instead; otherwise return t. */) |
| 2510 | pages for more information. | 2448 | (process, option, value, no_error) |
| 2511 | 2449 | Lisp_Object process, option, value; | |
| 2512 | bindtodevice=NAME -- bind to interface NAME, or remove binding if nil. | 2450 | Lisp_Object no_error; |
| 2513 | broadcast=BOOL -- Allow send and receive of datagram broadcasts. | ||
| 2514 | dontroute=BOOL -- Only send to directly connected hosts. | ||
| 2515 | keepalive=BOOL -- Send keep-alive messages on network stream. | ||
| 2516 | linger=BOOL or TIMEOUT -- Send queued messages before closing. | ||
| 2517 | oobinline=BOOL -- Place out-of-band data in receive data stream. | ||
| 2518 | priority=INT -- Set protocol defined priority for sent packets. | ||
| 2519 | reuseaddr=BOOL -- Allow reusing a recently used address. | ||
| 2520 | |||
| 2521 | usage: (set-network-process-options PROCESS &rest OPTIONS) */) | ||
| 2522 | (nargs, args) | ||
| 2523 | int nargs; | ||
| 2524 | Lisp_Object *args; | ||
| 2525 | { | 2451 | { |
| 2526 | Lisp_Object process; | 2452 | int s, i; |
| 2527 | Lisp_Object opts; | ||
| 2528 | 2453 | ||
| 2529 | process = args[0]; | ||
| 2530 | CHECK_PROCESS (process); | 2454 | CHECK_PROCESS (process); |
| 2531 | if (nargs > 1 && XINT (XPROCESS (process)->infd) >= 0) | 2455 | |
| 2532 | { | 2456 | s = XINT (XPROCESS (process)->infd); |
| 2533 | opts = Flist (nargs, args); | 2457 | if (s < 0) |
| 2534 | set_socket_options (XINT (XPROCESS (process)->infd), opts, 0); | 2458 | error ("Process is not running"); |
| 2535 | } | 2459 | |
| 2536 | return process; | 2460 | if (set_socket_option (s, option, value)) |
| 2461 | return Qt; | ||
| 2462 | |||
| 2463 | if (NILP (no_error)) | ||
| 2464 | error ("Unknown or unsupported option"); | ||
| 2465 | |||
| 2466 | return Qnil; | ||
| 2537 | } | 2467 | } |
| 2468 | |||
| 2538 | 2469 | ||
| 2539 | /* A version of request_sigio suitable for a record_unwind_protect. */ | 2470 | /* A version of request_sigio suitable for a record_unwind_protect. */ |
| 2540 | 2471 | ||
| @@ -2614,10 +2545,10 @@ address data with one element per address data byte. Do not rely on | |||
| 2614 | this format in portable code, as it may depend on implementation | 2545 | this format in portable code, as it may depend on implementation |
| 2615 | defined constants, data sizes, and data structure alignment. | 2546 | defined constants, data sizes, and data structure alignment. |
| 2616 | 2547 | ||
| 2617 | :coding CODING -- CODING is coding system for this process. | 2548 | :coding CODING -- If CODING is a symbol, it specifies the coding |
| 2618 | 2549 | system used for both reading and writing for this process. If CODING | |
| 2619 | :options OPTIONS -- Set the specified options for the network process. | 2550 | is a cons (DECODING . ENCODING), DECODING is used for reading, and |
| 2620 | See `set-network-process-options' for details. | 2551 | ENCODING is used for writing. |
| 2621 | 2552 | ||
| 2622 | :nowait BOOL -- If BOOL is non-nil for a stream type client process, | 2553 | :nowait BOOL -- If BOOL is non-nil for a stream type client process, |
| 2623 | return without waiting for the connection to complete; instead, the | 2554 | return without waiting for the connection to complete; instead, the |
| @@ -2651,13 +2582,32 @@ and MESSAGE is a string. | |||
| 2651 | 2582 | ||
| 2652 | :plist PLIST -- Install PLIST as the new process' initial plist. | 2583 | :plist PLIST -- Install PLIST as the new process' initial plist. |
| 2653 | 2584 | ||
| 2654 | :server BOOL -- if BOOL is non-nil, create a server process for the | 2585 | :server QLEN -- if QLEN is non-nil, create a server process for the |
| 2655 | specified FAMILY, SERVICE, and connection type (stream or datagram). | 2586 | specified FAMILY, SERVICE, and connection type (stream or datagram). |
| 2656 | Default is a client process. | 2587 | If QLEN is an integer, it is used as the max. length of the server's |
| 2588 | pending connection queue (also known as the backlog); the default | ||
| 2589 | queue length is 5. Default is to create a client process. | ||
| 2590 | |||
| 2591 | The following network options can be specified for this connection: | ||
| 2592 | |||
| 2593 | :bindtodevice NAME -- bind to interface NAME. | ||
| 2594 | :broadcast BOOL -- Allow send and receive of datagram broadcasts. | ||
| 2595 | :dontroute BOOL -- Only send to directly connected hosts. | ||
| 2596 | :keepalive BOOL -- Send keep-alive messages on network stream. | ||
| 2597 | :linger BOOL or TIMEOUT -- Send queued messages before closing. | ||
| 2598 | :oobinline BOOL -- Place out-of-band data in receive data stream. | ||
| 2599 | :priority INT -- Set protocol defined priority for sent packets. | ||
| 2600 | :reuseaddr BOOL -- Allow reusing a recently used local address | ||
| 2601 | (this is allowed by default for a server process). | ||
| 2602 | |||
| 2603 | Consult the relevant system programmer's manual pages for more | ||
| 2604 | information on using these options. | ||
| 2605 | |||
| 2606 | |||
| 2607 | A server process will listen for and accept connections from clients. | ||
| 2608 | When a client connection is accepted, a new network process is created | ||
| 2609 | for the connection with the following parameters: | ||
| 2657 | 2610 | ||
| 2658 | A server process will listen for and accept connections from | ||
| 2659 | clients. When a client connection is accepted, a new network process | ||
| 2660 | is created for the connection with the following parameters: | ||
| 2661 | - The client's process name is constructed by concatenating the server | 2611 | - The client's process name is constructed by concatenating the server |
| 2662 | process' NAME and a client identification string. | 2612 | process' NAME and a client identification string. |
| 2663 | - If the FILTER argument is non-nil, the client process will not get a | 2613 | - If the FILTER argument is non-nil, the client process will not get a |
| @@ -2718,7 +2668,7 @@ usage: (make-network-process &rest ARGS) */) | |||
| 2718 | Lisp_Object name, buffer, host, service, address; | 2668 | Lisp_Object name, buffer, host, service, address; |
| 2719 | Lisp_Object filter, sentinel; | 2669 | Lisp_Object filter, sentinel; |
| 2720 | int is_non_blocking_client = 0; | 2670 | int is_non_blocking_client = 0; |
| 2721 | int is_server = 0; | 2671 | int is_server = 0, backlog = 5; |
| 2722 | int socktype; | 2672 | int socktype; |
| 2723 | int family = -1; | 2673 | int family = -1; |
| 2724 | 2674 | ||
| @@ -2755,6 +2705,8 @@ usage: (make-network-process &rest ARGS) */) | |||
| 2755 | error ("Network servers not supported"); | 2705 | error ("Network servers not supported"); |
| 2756 | #else | 2706 | #else |
| 2757 | is_server = 1; | 2707 | is_server = 1; |
| 2708 | if (INTEGERP (tem)) | ||
| 2709 | backlog = XINT (tem); | ||
| 2758 | #endif | 2710 | #endif |
| 2759 | } | 2711 | } |
| 2760 | 2712 | ||
| @@ -3007,6 +2959,8 @@ usage: (make-network-process &rest ARGS) */) | |||
| 3007 | 2959 | ||
| 3008 | for (lres = res; lres; lres = lres->ai_next) | 2960 | for (lres = res; lres; lres = lres->ai_next) |
| 3009 | { | 2961 | { |
| 2962 | int optn, optbits; | ||
| 2963 | |||
| 3010 | s = socket (lres->ai_family, lres->ai_socktype, lres->ai_protocol); | 2964 | s = socket (lres->ai_family, lres->ai_socktype, lres->ai_protocol); |
| 3011 | if (s < 0) | 2965 | if (s < 0) |
| 3012 | { | 2966 | { |
| @@ -3040,17 +2994,27 @@ usage: (make-network-process &rest ARGS) */) | |||
| 3040 | /* Make us close S if quit. */ | 2994 | /* Make us close S if quit. */ |
| 3041 | record_unwind_protect (close_file_unwind, make_number (s)); | 2995 | record_unwind_protect (close_file_unwind, make_number (s)); |
| 3042 | 2996 | ||
| 2997 | /* Parse network options in the arg list. | ||
| 2998 | We simply ignore anything which isn't a known option (including other keywords). | ||
| 2999 | An error is signalled if setting a known option fails. */ | ||
| 3000 | for (optn = optbits = 0; optn < nargs-1; optn += 2) | ||
| 3001 | optbits |= set_socket_option (s, args[optn], args[optn+1]); | ||
| 3002 | |||
| 3043 | if (is_server) | 3003 | if (is_server) |
| 3044 | { | 3004 | { |
| 3045 | /* Configure as a server socket. */ | 3005 | /* Configure as a server socket. */ |
| 3006 | |||
| 3007 | /* SO_REUSEADDR = 1 is default for server sockets; must specify | ||
| 3008 | explicit :reuseaddr key to override this. */ | ||
| 3046 | #ifdef HAVE_LOCAL_SOCKETS | 3009 | #ifdef HAVE_LOCAL_SOCKETS |
| 3047 | if (family != AF_LOCAL) | 3010 | if (family != AF_LOCAL) |
| 3048 | #endif | 3011 | #endif |
| 3049 | { | 3012 | if (!(optbits & (1 << OPIX_REUSEADDR))) |
| 3050 | int optval = 1; | 3013 | { |
| 3051 | if (setsockopt (s, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof optval)) | 3014 | int optval = 1; |
| 3052 | report_file_error ("Cannot set reuse option on server socket.", Qnil); | 3015 | if (setsockopt (s, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof optval)) |
| 3053 | } | 3016 | report_file_error ("Cannot set reuse option on server socket.", Qnil); |
| 3017 | } | ||
| 3054 | 3018 | ||
| 3055 | if (bind (s, lres->ai_addr, lres->ai_addrlen)) | 3019 | if (bind (s, lres->ai_addr, lres->ai_addrlen)) |
| 3056 | report_file_error ("Cannot bind server socket", Qnil); | 3020 | report_file_error ("Cannot bind server socket", Qnil); |
| @@ -3069,7 +3033,7 @@ usage: (make-network-process &rest ARGS) */) | |||
| 3069 | } | 3033 | } |
| 3070 | #endif | 3034 | #endif |
| 3071 | 3035 | ||
| 3072 | if (socktype == SOCK_STREAM && listen (s, 5)) | 3036 | if (socktype == SOCK_STREAM && listen (s, backlog)) |
| 3073 | report_file_error ("Cannot listen on server socket", Qnil); | 3037 | report_file_error ("Cannot listen on server socket", Qnil); |
| 3074 | 3038 | ||
| 3075 | break; | 3039 | break; |
| @@ -3205,10 +3169,6 @@ usage: (make-network-process &rest ARGS) */) | |||
| 3205 | report_file_error ("make client process failed", contact); | 3169 | report_file_error ("make client process failed", contact); |
| 3206 | } | 3170 | } |
| 3207 | 3171 | ||
| 3208 | tem = Fplist_get (contact, QCoptions); | ||
| 3209 | if (!NILP (tem)) | ||
| 3210 | set_socket_options (s, tem, 1); | ||
| 3211 | |||
| 3212 | #endif /* not TERM */ | 3172 | #endif /* not TERM */ |
| 3213 | 3173 | ||
| 3214 | inch = s; | 3174 | inch = s; |
| @@ -3290,7 +3250,11 @@ usage: (make-network-process &rest ARGS) */) | |||
| 3290 | Lisp_Object args[5], val; | 3250 | Lisp_Object args[5], val; |
| 3291 | 3251 | ||
| 3292 | if (!NILP (tem)) | 3252 | if (!NILP (tem)) |
| 3293 | val = XCAR (XCDR (tem)); | 3253 | { |
| 3254 | val = XCAR (XCDR (tem)); | ||
| 3255 | if (CONSP (val)) | ||
| 3256 | val = XCAR (val); | ||
| 3257 | } | ||
| 3294 | else if (!NILP (Vcoding_system_for_read)) | 3258 | else if (!NILP (Vcoding_system_for_read)) |
| 3295 | val = Vcoding_system_for_read; | 3259 | val = Vcoding_system_for_read; |
| 3296 | else if ((!NILP (buffer) && NILP (XBUFFER (buffer)->enable_multibyte_characters)) | 3260 | else if ((!NILP (buffer) && NILP (XBUFFER (buffer)->enable_multibyte_characters)) |
| @@ -3322,7 +3286,11 @@ usage: (make-network-process &rest ARGS) */) | |||
| 3322 | p->decode_coding_system = val; | 3286 | p->decode_coding_system = val; |
| 3323 | 3287 | ||
| 3324 | if (!NILP (tem)) | 3288 | if (!NILP (tem)) |
| 3325 | val = XCAR (XCDR (tem)); | 3289 | { |
| 3290 | val = XCAR (XCDR (tem)); | ||
| 3291 | if (CONSP (val)) | ||
| 3292 | val = XCDR (val); | ||
| 3293 | } | ||
| 3326 | else if (!NILP (Vcoding_system_for_write)) | 3294 | else if (!NILP (Vcoding_system_for_write)) |
| 3327 | val = Vcoding_system_for_write; | 3295 | val = Vcoding_system_for_write; |
| 3328 | else if (NILP (current_buffer->enable_multibyte_characters)) | 3296 | else if (NILP (current_buffer->enable_multibyte_characters)) |
| @@ -3490,7 +3458,7 @@ static struct ifflag_def ifflag_table[] = { | |||
| 3490 | { 0, 0 } | 3458 | { 0, 0 } |
| 3491 | }; | 3459 | }; |
| 3492 | 3460 | ||
| 3493 | DEFUN ("get-network-interface-info", Fget_network_interface_info, Sget_network_interface_info, 1, 1, 0, | 3461 | DEFUN ("network-interface-info", Fnetwork_interface_info, Snetwork_interface_info, 1, 1, 0, |
| 3494 | doc: /* Return information about network interface named IFNAME. | 3462 | doc: /* Return information about network interface named IFNAME. |
| 3495 | The return value is a list (ADDR BCAST NETMASK HWADDR FLAGS), | 3463 | The return value is a list (ADDR BCAST NETMASK HWADDR FLAGS), |
| 3496 | where ADDR is the layer 3 address, BCAST is the layer 3 broadcast address, | 3464 | where ADDR is the layer 3 address, BCAST is the layer 3 broadcast address, |
| @@ -6540,6 +6508,8 @@ init_process () | |||
| 6540 | #ifdef HAVE_SOCKETS | 6508 | #ifdef HAVE_SOCKETS |
| 6541 | { | 6509 | { |
| 6542 | Lisp_Object subfeatures = Qnil; | 6510 | Lisp_Object subfeatures = Qnil; |
| 6511 | struct socket_options *sopt; | ||
| 6512 | |||
| 6543 | #define ADD_SUBFEATURE(key, val) \ | 6513 | #define ADD_SUBFEATURE(key, val) \ |
| 6544 | subfeatures = Fcons (Fcons (key, Fcons (val, Qnil)), subfeatures) | 6514 | subfeatures = Fcons (Fcons (key, Fcons (val, Qnil)), subfeatures) |
| 6545 | 6515 | ||
| @@ -6558,30 +6528,10 @@ init_process () | |||
| 6558 | #if !defined(TERM) && (defined(O_NONBLOCK) || defined(O_NDELAY)) | 6528 | #if !defined(TERM) && (defined(O_NONBLOCK) || defined(O_NDELAY)) |
| 6559 | ADD_SUBFEATURE (QCserver, Qt); | 6529 | ADD_SUBFEATURE (QCserver, Qt); |
| 6560 | #endif | 6530 | #endif |
| 6561 | #ifdef SO_BINDTODEVICE | 6531 | |
| 6562 | ADD_SUBFEATURE (QCoptions, intern ("bindtodevice")); | 6532 | for (sopt = socket_options; sopt->name; sopt++) |
| 6563 | #endif | 6533 | subfeatures = Fcons (intern (sopt->name), subfeatures); |
| 6564 | #ifdef SO_BROADCAST | 6534 | |
| 6565 | ADD_SUBFEATURE (QCoptions, intern ("broadcast")); | ||
| 6566 | #endif | ||
| 6567 | #ifdef SO_DONTROUTE | ||
| 6568 | ADD_SUBFEATURE (QCoptions, intern ("dontroute")); | ||
| 6569 | #endif | ||
| 6570 | #ifdef SO_KEEPALIVE | ||
| 6571 | ADD_SUBFEATURE (QCoptions, intern ("keepalive")); | ||
| 6572 | #endif | ||
| 6573 | #ifdef SO_LINGER | ||
| 6574 | ADD_SUBFEATURE (QCoptions, intern ("linger")); | ||
| 6575 | #endif | ||
| 6576 | #ifdef SO_OOBINLINE | ||
| 6577 | ADD_SUBFEATURE (QCoptions, intern ("oobinline")); | ||
| 6578 | #endif | ||
| 6579 | #ifdef SO_PRIORITY | ||
| 6580 | ADD_SUBFEATURE (QCoptions, intern ("priority")); | ||
| 6581 | #endif | ||
| 6582 | #ifdef SO_REUSEADDR | ||
| 6583 | ADD_SUBFEATURE (QCoptions, intern ("reuseaddr")); | ||
| 6584 | #endif | ||
| 6585 | Fprovide (intern ("make-network-process"), subfeatures); | 6535 | Fprovide (intern ("make-network-process"), subfeatures); |
| 6586 | } | 6536 | } |
| 6587 | #endif /* HAVE_SOCKETS */ | 6537 | #endif /* HAVE_SOCKETS */ |
| @@ -6703,14 +6653,14 @@ The value takes effect when `start-process' is called. */); | |||
| 6703 | defsubr (&Sprocess_list); | 6653 | defsubr (&Sprocess_list); |
| 6704 | defsubr (&Sstart_process); | 6654 | defsubr (&Sstart_process); |
| 6705 | #ifdef HAVE_SOCKETS | 6655 | #ifdef HAVE_SOCKETS |
| 6706 | defsubr (&Sset_network_process_options); | 6656 | defsubr (&Sset_network_process_option); |
| 6707 | defsubr (&Smake_network_process); | 6657 | defsubr (&Smake_network_process); |
| 6708 | defsubr (&Sformat_network_address); | 6658 | defsubr (&Sformat_network_address); |
| 6709 | #ifdef SIOCGIFCONF | 6659 | #ifdef SIOCGIFCONF |
| 6710 | defsubr (&Snetwork_interface_list); | 6660 | defsubr (&Snetwork_interface_list); |
| 6711 | #endif | 6661 | #endif |
| 6712 | #if defined(SIOCGIFADDR) || defined(SIOCGIFHWADDR) || defined(SIOCGIFFLAGS) | 6662 | #if defined(SIOCGIFADDR) || defined(SIOCGIFHWADDR) || defined(SIOCGIFFLAGS) |
| 6713 | defsubr (&Sget_network_interface_info); | 6663 | defsubr (&Snetwork_interface_info); |
| 6714 | #endif | 6664 | #endif |
| 6715 | #endif /* HAVE_SOCKETS */ | 6665 | #endif /* HAVE_SOCKETS */ |
| 6716 | #ifdef DATAGRAM_SOCKETS | 6666 | #ifdef DATAGRAM_SOCKETS |