diff options
| author | Lars Ingebrigtsen | 2016-01-28 23:50:47 +0100 |
|---|---|---|
| committer | Lars Ingebrigtsen | 2016-01-28 23:50:47 +0100 |
| commit | e09c0972c350e9411683b509414fc598cbf387d3 (patch) | |
| tree | 2472742ab64bf82da9c4011f0adee5d56cb57af6 /src/process.c | |
| parent | 6d25cbeaaf93615b8d7f26024ba014104eb5d4f2 (diff) | |
| download | emacs-e09c0972c350e9411683b509414fc598cbf387d3.tar.gz emacs-e09c0972c350e9411683b509414fc598cbf387d3.zip | |
Refactor make_network_process
* src/process.c (set_network_socket_coding_system)
(connect_network_socket): Refactor out of
make_network_process to allow calling connect_network_socket
asynchronously.
(Fmake_network_process): Do nothing but parsing the parameters
and name resolution, leaving the connection to
connect_network_socket.
Diffstat (limited to 'src/process.c')
| -rw-r--r-- | src/process.c | 877 |
1 files changed, 449 insertions, 428 deletions
diff --git a/src/process.c b/src/process.c index e1ebdff7430..1329d968e28 100644 --- a/src/process.c +++ b/src/process.c | |||
| @@ -2904,6 +2904,403 @@ usage: (make-serial-process &rest ARGS) */) | |||
| 2904 | return proc; | 2904 | return proc; |
| 2905 | } | 2905 | } |
| 2906 | 2906 | ||
| 2907 | void set_network_socket_coding_system (Lisp_Object proc) { | ||
| 2908 | Lisp_Object tem; | ||
| 2909 | struct Lisp_Process *p = XPROCESS (proc); | ||
| 2910 | Lisp_Object contact = p->childp; | ||
| 2911 | Lisp_Object service, host, name; | ||
| 2912 | |||
| 2913 | service = Fplist_get (contact, QCservice); | ||
| 2914 | host = Fplist_get (contact, QChost); | ||
| 2915 | name = Fplist_get (contact, QCname); | ||
| 2916 | |||
| 2917 | tem = Fplist_member (contact, QCcoding); | ||
| 2918 | if (!NILP (tem) && (!CONSP (tem) || !CONSP (XCDR (tem)))) | ||
| 2919 | tem = Qnil; /* No error message (too late!). */ | ||
| 2920 | |||
| 2921 | { | ||
| 2922 | /* Setup coding systems for communicating with the network stream. */ | ||
| 2923 | /* Qt denotes we have not yet called Ffind_operation_coding_system. */ | ||
| 2924 | Lisp_Object coding_systems = Qt; | ||
| 2925 | Lisp_Object val; | ||
| 2926 | |||
| 2927 | if (!NILP (tem)) | ||
| 2928 | { | ||
| 2929 | val = XCAR (XCDR (tem)); | ||
| 2930 | if (CONSP (val)) | ||
| 2931 | val = XCAR (val); | ||
| 2932 | } | ||
| 2933 | else if (!NILP (Vcoding_system_for_read)) | ||
| 2934 | val = Vcoding_system_for_read; | ||
| 2935 | else if ((!NILP (p->buffer) && | ||
| 2936 | NILP (BVAR (XBUFFER (p->buffer), enable_multibyte_characters))) | ||
| 2937 | || (NILP (p->buffer) && NILP (BVAR (&buffer_defaults, enable_multibyte_characters)))) | ||
| 2938 | /* We dare not decode end-of-line format by setting VAL to | ||
| 2939 | Qraw_text, because the existing Emacs Lisp libraries | ||
| 2940 | assume that they receive bare code including a sequence of | ||
| 2941 | CR LF. */ | ||
| 2942 | val = Qnil; | ||
| 2943 | else | ||
| 2944 | { | ||
| 2945 | if (NILP (host) || NILP (service)) | ||
| 2946 | coding_systems = Qnil; | ||
| 2947 | else | ||
| 2948 | coding_systems = CALLN (Ffind_operation_coding_system, | ||
| 2949 | Qopen_network_stream, name, p->buffer, | ||
| 2950 | host, service); | ||
| 2951 | if (CONSP (coding_systems)) | ||
| 2952 | val = XCAR (coding_systems); | ||
| 2953 | else if (CONSP (Vdefault_process_coding_system)) | ||
| 2954 | val = XCAR (Vdefault_process_coding_system); | ||
| 2955 | else | ||
| 2956 | val = Qnil; | ||
| 2957 | } | ||
| 2958 | pset_decode_coding_system (p, val); | ||
| 2959 | |||
| 2960 | if (!NILP (tem)) | ||
| 2961 | { | ||
| 2962 | val = XCAR (XCDR (tem)); | ||
| 2963 | if (CONSP (val)) | ||
| 2964 | val = XCDR (val); | ||
| 2965 | } | ||
| 2966 | else if (!NILP (Vcoding_system_for_write)) | ||
| 2967 | val = Vcoding_system_for_write; | ||
| 2968 | else if (NILP (BVAR (current_buffer, enable_multibyte_characters))) | ||
| 2969 | val = Qnil; | ||
| 2970 | else | ||
| 2971 | { | ||
| 2972 | if (EQ (coding_systems, Qt)) | ||
| 2973 | { | ||
| 2974 | if (NILP (host) || NILP (service)) | ||
| 2975 | coding_systems = Qnil; | ||
| 2976 | else | ||
| 2977 | coding_systems = CALLN (Ffind_operation_coding_system, | ||
| 2978 | Qopen_network_stream, name, p->buffer, | ||
| 2979 | host, service); | ||
| 2980 | } | ||
| 2981 | if (CONSP (coding_systems)) | ||
| 2982 | val = XCDR (coding_systems); | ||
| 2983 | else if (CONSP (Vdefault_process_coding_system)) | ||
| 2984 | val = XCDR (Vdefault_process_coding_system); | ||
| 2985 | else | ||
| 2986 | val = Qnil; | ||
| 2987 | } | ||
| 2988 | pset_encode_coding_system (p, val); | ||
| 2989 | } | ||
| 2990 | setup_process_coding_systems (proc); | ||
| 2991 | |||
| 2992 | pset_decoding_buf (p, empty_unibyte_string); | ||
| 2993 | p->decoding_carryover = 0; | ||
| 2994 | pset_encoding_buf (p, empty_unibyte_string); | ||
| 2995 | |||
| 2996 | p->inherit_coding_system_flag | ||
| 2997 | = !(!NILP (tem) || NILP (p->buffer) || !inherit_process_coding_system); | ||
| 2998 | } | ||
| 2999 | |||
| 3000 | void connect_network_socket (Lisp_Object proc, Lisp_Object ip_addresses) { | ||
| 3001 | ptrdiff_t count = SPECPDL_INDEX (); | ||
| 3002 | ptrdiff_t count1; | ||
| 3003 | int s = -1, outch, inch; | ||
| 3004 | int xerrno = 0; | ||
| 3005 | Lisp_Object ip_address; | ||
| 3006 | int family; | ||
| 3007 | struct sockaddr *sa; | ||
| 3008 | int ret; | ||
| 3009 | int addrlen; | ||
| 3010 | struct Lisp_Process *p = XPROCESS (proc); | ||
| 3011 | Lisp_Object contact = p->childp; | ||
| 3012 | int optbits = 0; | ||
| 3013 | |||
| 3014 | /* Do this in case we never enter the for-loop below. */ | ||
| 3015 | count1 = SPECPDL_INDEX (); | ||
| 3016 | s = -1; | ||
| 3017 | |||
| 3018 | while (!NILP (ip_addresses)) | ||
| 3019 | { | ||
| 3020 | ip_address = Fcar (ip_addresses); | ||
| 3021 | ip_addresses = Fcdr (ip_addresses); | ||
| 3022 | |||
| 3023 | #ifdef WINDOWSNT | ||
| 3024 | retry_connect: | ||
| 3025 | #endif | ||
| 3026 | |||
| 3027 | addrlen = get_lisp_to_sockaddr_size (ip_address, &family); | ||
| 3028 | sa = alloca (addrlen); | ||
| 3029 | conv_lisp_to_sockaddr (family, ip_address, sa, addrlen); | ||
| 3030 | |||
| 3031 | s = socket (family, p->socktype | SOCK_CLOEXEC, p->ai_protocol); | ||
| 3032 | if (s < 0) | ||
| 3033 | { | ||
| 3034 | xerrno = errno; | ||
| 3035 | continue; | ||
| 3036 | } | ||
| 3037 | |||
| 3038 | #ifdef DATAGRAM_SOCKETS | ||
| 3039 | if (!p->is_server && p->socktype == SOCK_DGRAM) | ||
| 3040 | break; | ||
| 3041 | #endif /* DATAGRAM_SOCKETS */ | ||
| 3042 | |||
| 3043 | #ifdef NON_BLOCKING_CONNECT | ||
| 3044 | if (p->is_non_blocking_client) | ||
| 3045 | { | ||
| 3046 | ret = fcntl (s, F_SETFL, O_NONBLOCK); | ||
| 3047 | if (ret < 0) | ||
| 3048 | { | ||
| 3049 | xerrno = errno; | ||
| 3050 | emacs_close (s); | ||
| 3051 | s = -1; | ||
| 3052 | continue; | ||
| 3053 | } | ||
| 3054 | } | ||
| 3055 | #endif | ||
| 3056 | |||
| 3057 | /* Make us close S if quit. */ | ||
| 3058 | record_unwind_protect_int (close_file_unwind, s); | ||
| 3059 | |||
| 3060 | /* Parse network options in the arg list. We simply ignore anything | ||
| 3061 | which isn't a known option (including other keywords). An error | ||
| 3062 | is signaled if setting a known option fails. */ | ||
| 3063 | { | ||
| 3064 | Lisp_Object params = contact, key, val; | ||
| 3065 | |||
| 3066 | while (!NILP (params)) { | ||
| 3067 | key = Fcar (params); | ||
| 3068 | params = Fcdr (params); | ||
| 3069 | val = Fcar (params); | ||
| 3070 | params = Fcdr (params); | ||
| 3071 | optbits |= set_socket_option (s, key, val); | ||
| 3072 | } | ||
| 3073 | } | ||
| 3074 | |||
| 3075 | if (p->is_server) | ||
| 3076 | { | ||
| 3077 | /* Configure as a server socket. */ | ||
| 3078 | |||
| 3079 | /* SO_REUSEADDR = 1 is default for server sockets; must specify | ||
| 3080 | explicit :reuseaddr key to override this. */ | ||
| 3081 | #ifdef HAVE_LOCAL_SOCKETS | ||
| 3082 | if (family != AF_LOCAL) | ||
| 3083 | #endif | ||
| 3084 | if (!(optbits & (1 << OPIX_REUSEADDR))) | ||
| 3085 | { | ||
| 3086 | int optval = 1; | ||
| 3087 | if (setsockopt (s, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof optval)) | ||
| 3088 | report_file_error ("Cannot set reuse option on server socket", Qnil); | ||
| 3089 | } | ||
| 3090 | |||
| 3091 | if (bind (s, sa, addrlen)) | ||
| 3092 | report_file_error ("Cannot bind server socket", Qnil); | ||
| 3093 | |||
| 3094 | #ifdef HAVE_GETSOCKNAME | ||
| 3095 | if (p->port == 0) | ||
| 3096 | { | ||
| 3097 | struct sockaddr_in sa1; | ||
| 3098 | socklen_t len1 = sizeof (sa1); | ||
| 3099 | if (getsockname (s, (struct sockaddr *)&sa1, &len1) == 0) | ||
| 3100 | { | ||
| 3101 | Lisp_Object service; | ||
| 3102 | service = make_number (ntohs (sa1.sin_port)); | ||
| 3103 | contact = Fplist_put (contact, QCservice, service); | ||
| 3104 | } | ||
| 3105 | } | ||
| 3106 | #endif | ||
| 3107 | |||
| 3108 | if (p->socktype != SOCK_DGRAM && listen (s, p->backlog)) | ||
| 3109 | report_file_error ("Cannot listen on server socket", Qnil); | ||
| 3110 | |||
| 3111 | break; | ||
| 3112 | } | ||
| 3113 | |||
| 3114 | immediate_quit = 1; | ||
| 3115 | QUIT; | ||
| 3116 | |||
| 3117 | ret = connect (s, sa, addrlen); | ||
| 3118 | xerrno = errno; | ||
| 3119 | |||
| 3120 | if (ret == 0 || xerrno == EISCONN) | ||
| 3121 | { | ||
| 3122 | /* The unwind-protect will be discarded afterwards. | ||
| 3123 | Likewise for immediate_quit. */ | ||
| 3124 | break; | ||
| 3125 | } | ||
| 3126 | |||
| 3127 | #ifdef NON_BLOCKING_CONNECT | ||
| 3128 | #ifdef EINPROGRESS | ||
| 3129 | if (p->is_non_blocking_client && xerrno == EINPROGRESS) | ||
| 3130 | break; | ||
| 3131 | #else | ||
| 3132 | #ifdef EWOULDBLOCK | ||
| 3133 | if (p->is_non_blocking_client && xerrno == EWOULDBLOCK) | ||
| 3134 | break; | ||
| 3135 | #endif | ||
| 3136 | #endif | ||
| 3137 | #endif | ||
| 3138 | |||
| 3139 | #ifndef WINDOWSNT | ||
| 3140 | if (xerrno == EINTR) | ||
| 3141 | { | ||
| 3142 | /* Unlike most other syscalls connect() cannot be called | ||
| 3143 | again. (That would return EALREADY.) The proper way to | ||
| 3144 | wait for completion is pselect(). */ | ||
| 3145 | int sc; | ||
| 3146 | socklen_t len; | ||
| 3147 | fd_set fdset; | ||
| 3148 | retry_select: | ||
| 3149 | FD_ZERO (&fdset); | ||
| 3150 | FD_SET (s, &fdset); | ||
| 3151 | QUIT; | ||
| 3152 | sc = pselect (s + 1, NULL, &fdset, NULL, NULL, NULL); | ||
| 3153 | if (sc == -1) | ||
| 3154 | { | ||
| 3155 | if (errno == EINTR) | ||
| 3156 | goto retry_select; | ||
| 3157 | else | ||
| 3158 | report_file_error ("Failed select", Qnil); | ||
| 3159 | } | ||
| 3160 | eassert (sc > 0); | ||
| 3161 | |||
| 3162 | len = sizeof xerrno; | ||
| 3163 | eassert (FD_ISSET (s, &fdset)); | ||
| 3164 | if (getsockopt (s, SOL_SOCKET, SO_ERROR, &xerrno, &len) < 0) | ||
| 3165 | report_file_error ("Failed getsockopt", Qnil); | ||
| 3166 | if (xerrno) | ||
| 3167 | report_file_errno ("Failed connect", Qnil, xerrno); | ||
| 3168 | break; | ||
| 3169 | } | ||
| 3170 | #endif /* !WINDOWSNT */ | ||
| 3171 | |||
| 3172 | immediate_quit = 0; | ||
| 3173 | |||
| 3174 | /* Discard the unwind protect closing S. */ | ||
| 3175 | specpdl_ptr = specpdl + count1; | ||
| 3176 | emacs_close (s); | ||
| 3177 | s = -1; | ||
| 3178 | |||
| 3179 | #ifdef WINDOWSNT | ||
| 3180 | if (xerrno == EINTR) | ||
| 3181 | goto retry_connect; | ||
| 3182 | #endif | ||
| 3183 | } | ||
| 3184 | |||
| 3185 | if (s >= 0) | ||
| 3186 | { | ||
| 3187 | #ifdef DATAGRAM_SOCKETS | ||
| 3188 | if (p->socktype == SOCK_DGRAM) | ||
| 3189 | { | ||
| 3190 | if (datagram_address[s].sa) | ||
| 3191 | emacs_abort (); | ||
| 3192 | |||
| 3193 | datagram_address[s].sa = xmalloc (addrlen); | ||
| 3194 | datagram_address[s].len = addrlen; | ||
| 3195 | if (p->is_server) | ||
| 3196 | { | ||
| 3197 | Lisp_Object remote; | ||
| 3198 | memset (datagram_address[s].sa, 0, addrlen); | ||
| 3199 | if (remote = Fplist_get (contact, QCremote), !NILP (remote)) | ||
| 3200 | { | ||
| 3201 | int rfamily, rlen; | ||
| 3202 | rlen = get_lisp_to_sockaddr_size (remote, &rfamily); | ||
| 3203 | if (rlen != 0 && rfamily == family | ||
| 3204 | && rlen == addrlen) | ||
| 3205 | conv_lisp_to_sockaddr (rfamily, remote, | ||
| 3206 | datagram_address[s].sa, rlen); | ||
| 3207 | } | ||
| 3208 | } | ||
| 3209 | else | ||
| 3210 | memcpy (datagram_address[s].sa, sa, addrlen); | ||
| 3211 | } | ||
| 3212 | #endif | ||
| 3213 | |||
| 3214 | contact = Fplist_put (contact, p->is_server? QCremote: QClocal, | ||
| 3215 | conv_sockaddr_to_lisp (sa, addrlen)); | ||
| 3216 | #ifdef HAVE_GETSOCKNAME | ||
| 3217 | if (!p->is_server) | ||
| 3218 | { | ||
| 3219 | struct sockaddr_in sa1; | ||
| 3220 | socklen_t len1 = sizeof (sa1); | ||
| 3221 | if (getsockname (s, (struct sockaddr *)&sa1, &len1) == 0) | ||
| 3222 | contact = Fplist_put (contact, QClocal, | ||
| 3223 | conv_sockaddr_to_lisp ((struct sockaddr *)&sa1, len1)); | ||
| 3224 | } | ||
| 3225 | #endif | ||
| 3226 | } | ||
| 3227 | |||
| 3228 | immediate_quit = 0; | ||
| 3229 | |||
| 3230 | if (s < 0) | ||
| 3231 | { | ||
| 3232 | /* If non-blocking got this far - and failed - assume non-blocking is | ||
| 3233 | not supported after all. This is probably a wrong assumption, but | ||
| 3234 | the normal blocking calls to open-network-stream handles this error | ||
| 3235 | better. */ | ||
| 3236 | if (p->is_non_blocking_client) | ||
| 3237 | return; | ||
| 3238 | |||
| 3239 | report_file_errno ((p->is_server | ||
| 3240 | ? "make server process failed" | ||
| 3241 | : "make client process failed"), | ||
| 3242 | contact, xerrno); | ||
| 3243 | } | ||
| 3244 | |||
| 3245 | inch = s; | ||
| 3246 | outch = s; | ||
| 3247 | |||
| 3248 | chan_process[inch] = proc; | ||
| 3249 | |||
| 3250 | fcntl (inch, F_SETFL, O_NONBLOCK); | ||
| 3251 | |||
| 3252 | p = XPROCESS (proc); | ||
| 3253 | p->open_fd[SUBPROCESS_STDIN] = inch; | ||
| 3254 | p->infd = inch; | ||
| 3255 | p->outfd = outch; | ||
| 3256 | |||
| 3257 | /* Discard the unwind protect for closing S, if any. */ | ||
| 3258 | specpdl_ptr = specpdl + count1; | ||
| 3259 | |||
| 3260 | /* Unwind bind_polling_period and request_sigio. */ | ||
| 3261 | unbind_to (count, Qnil); | ||
| 3262 | |||
| 3263 | if (p->is_server && p->socktype != SOCK_DGRAM) | ||
| 3264 | pset_status (p, Qlisten); | ||
| 3265 | |||
| 3266 | /* Make the process marker point into the process buffer (if any). */ | ||
| 3267 | if (BUFFERP (p->buffer)) | ||
| 3268 | set_marker_both (p->mark, p->buffer, | ||
| 3269 | BUF_ZV (XBUFFER (p->buffer)), | ||
| 3270 | BUF_ZV_BYTE (XBUFFER (p->buffer))); | ||
| 3271 | |||
| 3272 | #ifdef NON_BLOCKING_CONNECT | ||
| 3273 | if (p->is_non_blocking_client) | ||
| 3274 | { | ||
| 3275 | /* We may get here if connect did succeed immediately. However, | ||
| 3276 | in that case, we still need to signal this like a non-blocking | ||
| 3277 | connection. */ | ||
| 3278 | pset_status (p, Qconnect); | ||
| 3279 | if (!FD_ISSET (inch, &connect_wait_mask)) | ||
| 3280 | { | ||
| 3281 | FD_SET (inch, &connect_wait_mask); | ||
| 3282 | FD_SET (inch, &write_mask); | ||
| 3283 | num_pending_connects++; | ||
| 3284 | } | ||
| 3285 | } | ||
| 3286 | else | ||
| 3287 | #endif | ||
| 3288 | /* A server may have a client filter setting of Qt, but it must | ||
| 3289 | still listen for incoming connects unless it is stopped. */ | ||
| 3290 | if ((!EQ (p->filter, Qt) && !EQ (p->command, Qt)) | ||
| 3291 | || (EQ (p->status, Qlisten) && NILP (p->command))) | ||
| 3292 | { | ||
| 3293 | FD_SET (inch, &input_wait_mask); | ||
| 3294 | FD_SET (inch, &non_keyboard_wait_mask); | ||
| 3295 | } | ||
| 3296 | |||
| 3297 | if (inch > max_process_desc) | ||
| 3298 | max_process_desc = inch; | ||
| 3299 | |||
| 3300 | set_network_socket_coding_system (proc); | ||
| 3301 | } | ||
| 3302 | |||
| 3303 | |||
| 2907 | /* Create a network stream/datagram client/server process. Treated | 3304 | /* Create a network stream/datagram client/server process. Treated |
| 2908 | exactly like a normal process when reading and writing. Primary | 3305 | exactly like a normal process when reading and writing. Primary |
| 2909 | differences are in status display and process deletion. A network | 3306 | differences are in status display and process deletion. A network |
| @@ -3072,36 +3469,20 @@ usage: (make-network-process &rest ARGS) */) | |||
| 3072 | struct addrinfo hints; | 3469 | struct addrinfo hints; |
| 3073 | const char *portstring; | 3470 | const char *portstring; |
| 3074 | char portbuf[128]; | 3471 | char portbuf[128]; |
| 3075 | #else /* HAVE_GETADDRINFO */ | ||
| 3076 | struct _emacs_addrinfo | ||
| 3077 | { | ||
| 3078 | int ai_family; | ||
| 3079 | int ai_socktype; | ||
| 3080 | int ai_protocol; | ||
| 3081 | int ai_addrlen; | ||
| 3082 | struct sockaddr *ai_addr; | ||
| 3083 | struct _emacs_addrinfo *ai_next; | ||
| 3084 | } ai, *res, *lres; | ||
| 3085 | #endif /* HAVE_GETADDRINFO */ | 3472 | #endif /* HAVE_GETADDRINFO */ |
| 3086 | struct sockaddr_in address_in; | ||
| 3087 | #ifdef HAVE_LOCAL_SOCKETS | 3473 | #ifdef HAVE_LOCAL_SOCKETS |
| 3088 | struct sockaddr_un address_un; | 3474 | struct sockaddr_un address_un; |
| 3089 | #endif | 3475 | #endif |
| 3090 | int port; | 3476 | int port = 0; |
| 3091 | int ret = 0; | 3477 | int ret = 0; |
| 3092 | int xerrno = 0; | ||
| 3093 | int s = -1, outch, inch; | ||
| 3094 | ptrdiff_t count = SPECPDL_INDEX (); | ||
| 3095 | ptrdiff_t count1; | ||
| 3096 | Lisp_Object colon_address; /* Either QClocal or QCremote. */ | ||
| 3097 | Lisp_Object tem; | 3478 | Lisp_Object tem; |
| 3098 | Lisp_Object name, buffer, host, service, address; | 3479 | Lisp_Object name, buffer, host, service, address; |
| 3099 | Lisp_Object filter, sentinel; | 3480 | Lisp_Object filter, sentinel; |
| 3100 | bool is_non_blocking_client = 0; | 3481 | Lisp_Object ip_addresses = Qnil; |
| 3101 | bool is_server = 0; | ||
| 3102 | int backlog = 5; | ||
| 3103 | int socktype; | 3482 | int socktype; |
| 3104 | int family = -1; | 3483 | int family = -1; |
| 3484 | int ai_protocol = 0; | ||
| 3485 | ptrdiff_t count = SPECPDL_INDEX (); | ||
| 3105 | 3486 | ||
| 3106 | if (nargs == 0) | 3487 | if (nargs == 0) |
| 3107 | return Qnil; | 3488 | return Qnil; |
| @@ -3129,31 +3510,6 @@ usage: (make-network-process &rest ARGS) */) | |||
| 3129 | else | 3510 | else |
| 3130 | error ("Unsupported connection type"); | 3511 | error ("Unsupported connection type"); |
| 3131 | 3512 | ||
| 3132 | /* :server BOOL */ | ||
| 3133 | tem = Fplist_get (contact, QCserver); | ||
| 3134 | if (!NILP (tem)) | ||
| 3135 | { | ||
| 3136 | /* Don't support network sockets when non-blocking mode is | ||
| 3137 | not available, since a blocked Emacs is not useful. */ | ||
| 3138 | is_server = 1; | ||
| 3139 | if (TYPE_RANGED_INTEGERP (int, tem)) | ||
| 3140 | backlog = XINT (tem); | ||
| 3141 | } | ||
| 3142 | |||
| 3143 | /* Make colon_address an alias for :local (server) or :remote (client). */ | ||
| 3144 | colon_address = is_server ? QClocal : QCremote; | ||
| 3145 | |||
| 3146 | /* :nowait BOOL */ | ||
| 3147 | if (!is_server && socktype != SOCK_DGRAM | ||
| 3148 | && (tem = Fplist_get (contact, QCnowait), !NILP (tem))) | ||
| 3149 | { | ||
| 3150 | #ifndef NON_BLOCKING_CONNECT | ||
| 3151 | error ("Non-blocking connect not supported"); | ||
| 3152 | #else | ||
| 3153 | is_non_blocking_client = 1; | ||
| 3154 | #endif | ||
| 3155 | } | ||
| 3156 | |||
| 3157 | name = Fplist_get (contact, QCname); | 3513 | name = Fplist_get (contact, QCname); |
| 3158 | buffer = Fplist_get (contact, QCbuffer); | 3514 | buffer = Fplist_get (contact, QCbuffer); |
| 3159 | filter = Fplist_get (contact, QCfilter); | 3515 | filter = Fplist_get (contact, QCfilter); |
| @@ -3168,16 +3524,19 @@ usage: (make-network-process &rest ARGS) */) | |||
| 3168 | res = &ai; | 3524 | res = &ai; |
| 3169 | 3525 | ||
| 3170 | /* :local ADDRESS or :remote ADDRESS */ | 3526 | /* :local ADDRESS or :remote ADDRESS */ |
| 3171 | address = Fplist_get (contact, colon_address); | 3527 | tem = Fplist_get (contact, QCserver); |
| 3528 | if (!NILP (tem)) | ||
| 3529 | address = Fplist_get (contact, QCremote); | ||
| 3530 | else | ||
| 3531 | address = Fplist_get (contact, QClocal); | ||
| 3172 | if (!NILP (address)) | 3532 | if (!NILP (address)) |
| 3173 | { | 3533 | { |
| 3174 | host = service = Qnil; | 3534 | host = service = Qnil; |
| 3175 | 3535 | ||
| 3176 | if (!(ai.ai_addrlen = get_lisp_to_sockaddr_size (address, &family))) | 3536 | if (!get_lisp_to_sockaddr_size (address, &family)) |
| 3177 | error ("Malformed :address"); | 3537 | error ("Malformed :address"); |
| 3178 | ai.ai_family = family; | 3538 | |
| 3179 | ai.ai_addr = alloca (ai.ai_addrlen); | 3539 | ip_addresses = Fcons (address, Qnil); |
| 3180 | conv_lisp_to_sockaddr (family, address, ai.ai_addr, ai.ai_addrlen); | ||
| 3181 | goto open_socket; | 3540 | goto open_socket; |
| 3182 | } | 3541 | } |
| 3183 | 3542 | ||
| @@ -3206,8 +3565,6 @@ usage: (make-network-process &rest ARGS) */) | |||
| 3206 | else | 3565 | else |
| 3207 | error ("Unknown address family"); | 3566 | error ("Unknown address family"); |
| 3208 | 3567 | ||
| 3209 | ai.ai_family = family; | ||
| 3210 | |||
| 3211 | /* :service SERVICE -- string, integer (port number), or t (random port). */ | 3568 | /* :service SERVICE -- string, integer (port number), or t (random port). */ |
| 3212 | service = Fplist_get (contact, QCservice); | 3569 | service = Fplist_get (contact, QCservice); |
| 3213 | 3570 | ||
| @@ -3232,13 +3589,9 @@ usage: (make-network-process &rest ARGS) */) | |||
| 3232 | host = Qnil; | 3589 | host = Qnil; |
| 3233 | } | 3590 | } |
| 3234 | CHECK_STRING (service); | 3591 | CHECK_STRING (service); |
| 3235 | memset (&address_un, 0, sizeof address_un); | ||
| 3236 | address_un.sun_family = AF_LOCAL; | ||
| 3237 | if (sizeof address_un.sun_path <= SBYTES (service)) | 3592 | if (sizeof address_un.sun_path <= SBYTES (service)) |
| 3238 | error ("Service name too long"); | 3593 | error ("Service name too long"); |
| 3239 | lispstpcpy (address_un.sun_path, service); | 3594 | ip_addresses = Fcons (service, Qnil); |
| 3240 | ai.ai_addr = (struct sockaddr *) &address_un; | ||
| 3241 | ai.ai_addrlen = sizeof address_un; | ||
| 3242 | goto open_socket; | 3595 | goto open_socket; |
| 3243 | } | 3596 | } |
| 3244 | #endif | 3597 | #endif |
| @@ -3257,6 +3610,7 @@ usage: (make-network-process &rest ARGS) */) | |||
| 3257 | #ifdef HAVE_GETADDRINFO | 3610 | #ifdef HAVE_GETADDRINFO |
| 3258 | /* If we have a host, use getaddrinfo to resolve both host and service. | 3611 | /* If we have a host, use getaddrinfo to resolve both host and service. |
| 3259 | Otherwise, use getservbyname to lookup the service. */ | 3612 | Otherwise, use getservbyname to lookup the service. */ |
| 3613 | |||
| 3260 | if (!NILP (host)) | 3614 | if (!NILP (host)) |
| 3261 | { | 3615 | { |
| 3262 | 3616 | ||
| @@ -3296,6 +3650,15 @@ usage: (make-network-process &rest ARGS) */) | |||
| 3296 | #endif | 3650 | #endif |
| 3297 | immediate_quit = 0; | 3651 | immediate_quit = 0; |
| 3298 | 3652 | ||
| 3653 | for (lres = res; lres; lres = lres->ai_next) | ||
| 3654 | { | ||
| 3655 | ip_addresses = Fcons (conv_sockaddr_to_lisp | ||
| 3656 | (lres->ai_addr, lres->ai_addrlen), | ||
| 3657 | ip_addresses); | ||
| 3658 | ai_protocol = lres->ai_protocol; | ||
| 3659 | family = lres->ai_family; | ||
| 3660 | } | ||
| 3661 | |||
| 3299 | goto open_socket; | 3662 | goto open_socket; |
| 3300 | } | 3663 | } |
| 3301 | #endif /* HAVE_GETADDRINFO */ | 3664 | #endif /* HAVE_GETADDRINFO */ |
| @@ -3318,11 +3681,6 @@ usage: (make-network-process &rest ARGS) */) | |||
| 3318 | port = svc_info->s_port; | 3681 | port = svc_info->s_port; |
| 3319 | } | 3682 | } |
| 3320 | 3683 | ||
| 3321 | memset (&address_in, 0, sizeof address_in); | ||
| 3322 | address_in.sin_family = family; | ||
| 3323 | address_in.sin_addr.s_addr = INADDR_ANY; | ||
| 3324 | address_in.sin_port = port; | ||
| 3325 | |||
| 3326 | #ifndef HAVE_GETADDRINFO | 3684 | #ifndef HAVE_GETADDRINFO |
| 3327 | if (!NILP (host)) | 3685 | if (!NILP (host)) |
| 3328 | { | 3686 | { |
| @@ -3342,10 +3700,10 @@ usage: (make-network-process &rest ARGS) */) | |||
| 3342 | 3700 | ||
| 3343 | if (host_info_ptr) | 3701 | if (host_info_ptr) |
| 3344 | { | 3702 | { |
| 3345 | memcpy (&address_in.sin_addr, host_info_ptr->h_addr, | 3703 | ip_addresses = Ncons (make_number (host_info_ptr->h_addr, |
| 3346 | host_info_ptr->h_length); | 3704 | host_info_ptr->h_length), |
| 3705 | Qnil); | ||
| 3347 | family = host_info_ptr->h_addrtype; | 3706 | family = host_info_ptr->h_addrtype; |
| 3348 | address_in.sin_family = family; | ||
| 3349 | } | 3707 | } |
| 3350 | else | 3708 | else |
| 3351 | /* Attempt to interpret host as numeric inet address. */ | 3709 | /* Attempt to interpret host as numeric inet address. */ |
| @@ -3355,258 +3713,18 @@ usage: (make-network-process &rest ARGS) */) | |||
| 3355 | if (numeric_addr == -1) | 3713 | if (numeric_addr == -1) |
| 3356 | error ("Unknown host \"%s\"", SDATA (host)); | 3714 | error ("Unknown host \"%s\"", SDATA (host)); |
| 3357 | 3715 | ||
| 3358 | memcpy (&address_in.sin_addr, &numeric_addr, | 3716 | ip_addresses = Ncons (make_number (numeric_addr), Qnil); |
| 3359 | sizeof (address_in.sin_addr)); | ||
| 3360 | } | 3717 | } |
| 3361 | 3718 | ||
| 3362 | } | 3719 | } |
| 3363 | #endif /* not HAVE_GETADDRINFO */ | 3720 | #endif /* not HAVE_GETADDRINFO */ |
| 3364 | 3721 | ||
| 3365 | ai.ai_family = family; | ||
| 3366 | ai.ai_addr = (struct sockaddr *) &address_in; | ||
| 3367 | ai.ai_addrlen = sizeof address_in; | ||
| 3368 | |||
| 3369 | open_socket: | 3722 | open_socket: |
| 3370 | 3723 | ||
| 3371 | /* Do this in case we never enter the for-loop below. */ | ||
| 3372 | count1 = SPECPDL_INDEX (); | ||
| 3373 | s = -1; | ||
| 3374 | |||
| 3375 | for (lres = res; lres; lres = lres->ai_next) | ||
| 3376 | { | ||
| 3377 | ptrdiff_t optn; | ||
| 3378 | int optbits; | ||
| 3379 | |||
| 3380 | #ifdef WINDOWSNT | ||
| 3381 | retry_connect: | ||
| 3382 | #endif | ||
| 3383 | |||
| 3384 | s = socket (lres->ai_family, lres->ai_socktype | SOCK_CLOEXEC, | ||
| 3385 | lres->ai_protocol); | ||
| 3386 | if (s < 0) | ||
| 3387 | { | ||
| 3388 | xerrno = errno; | ||
| 3389 | continue; | ||
| 3390 | } | ||
| 3391 | |||
| 3392 | #ifdef DATAGRAM_SOCKETS | ||
| 3393 | if (!is_server && socktype == SOCK_DGRAM) | ||
| 3394 | break; | ||
| 3395 | #endif /* DATAGRAM_SOCKETS */ | ||
| 3396 | |||
| 3397 | #ifdef NON_BLOCKING_CONNECT | ||
| 3398 | if (is_non_blocking_client) | ||
| 3399 | { | ||
| 3400 | ret = fcntl (s, F_SETFL, O_NONBLOCK); | ||
| 3401 | if (ret < 0) | ||
| 3402 | { | ||
| 3403 | xerrno = errno; | ||
| 3404 | emacs_close (s); | ||
| 3405 | s = -1; | ||
| 3406 | continue; | ||
| 3407 | } | ||
| 3408 | } | ||
| 3409 | #endif | ||
| 3410 | |||
| 3411 | /* Make us close S if quit. */ | ||
| 3412 | record_unwind_protect_int (close_file_unwind, s); | ||
| 3413 | |||
| 3414 | /* Parse network options in the arg list. | ||
| 3415 | We simply ignore anything which isn't a known option (including other keywords). | ||
| 3416 | An error is signaled if setting a known option fails. */ | ||
| 3417 | for (optn = optbits = 0; optn < nargs - 1; optn += 2) | ||
| 3418 | optbits |= set_socket_option (s, args[optn], args[optn + 1]); | ||
| 3419 | |||
| 3420 | if (is_server) | ||
| 3421 | { | ||
| 3422 | /* Configure as a server socket. */ | ||
| 3423 | |||
| 3424 | /* SO_REUSEADDR = 1 is default for server sockets; must specify | ||
| 3425 | explicit :reuseaddr key to override this. */ | ||
| 3426 | #ifdef HAVE_LOCAL_SOCKETS | ||
| 3427 | if (family != AF_LOCAL) | ||
| 3428 | #endif | ||
| 3429 | if (!(optbits & (1 << OPIX_REUSEADDR))) | ||
| 3430 | { | ||
| 3431 | int optval = 1; | ||
| 3432 | if (setsockopt (s, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof optval)) | ||
| 3433 | report_file_error ("Cannot set reuse option on server socket", Qnil); | ||
| 3434 | } | ||
| 3435 | |||
| 3436 | if (bind (s, lres->ai_addr, lres->ai_addrlen)) | ||
| 3437 | report_file_error ("Cannot bind server socket", Qnil); | ||
| 3438 | |||
| 3439 | #ifdef HAVE_GETSOCKNAME | ||
| 3440 | if (EQ (service, Qt)) | ||
| 3441 | { | ||
| 3442 | struct sockaddr_in sa1; | ||
| 3443 | socklen_t len1 = sizeof (sa1); | ||
| 3444 | if (getsockname (s, (struct sockaddr *)&sa1, &len1) == 0) | ||
| 3445 | { | ||
| 3446 | ((struct sockaddr_in *)(lres->ai_addr))->sin_port = sa1.sin_port; | ||
| 3447 | service = make_number (ntohs (sa1.sin_port)); | ||
| 3448 | contact = Fplist_put (contact, QCservice, service); | ||
| 3449 | } | ||
| 3450 | } | ||
| 3451 | #endif | ||
| 3452 | |||
| 3453 | if (socktype != SOCK_DGRAM && listen (s, backlog)) | ||
| 3454 | report_file_error ("Cannot listen on server socket", Qnil); | ||
| 3455 | |||
| 3456 | break; | ||
| 3457 | } | ||
| 3458 | |||
| 3459 | immediate_quit = 1; | ||
| 3460 | QUIT; | ||
| 3461 | |||
| 3462 | ret = connect (s, lres->ai_addr, lres->ai_addrlen); | ||
| 3463 | xerrno = errno; | ||
| 3464 | |||
| 3465 | if (ret == 0 || xerrno == EISCONN) | ||
| 3466 | { | ||
| 3467 | /* The unwind-protect will be discarded afterwards. | ||
| 3468 | Likewise for immediate_quit. */ | ||
| 3469 | break; | ||
| 3470 | } | ||
| 3471 | |||
| 3472 | #ifdef NON_BLOCKING_CONNECT | ||
| 3473 | #ifdef EINPROGRESS | ||
| 3474 | if (is_non_blocking_client && xerrno == EINPROGRESS) | ||
| 3475 | break; | ||
| 3476 | #else | ||
| 3477 | #ifdef EWOULDBLOCK | ||
| 3478 | if (is_non_blocking_client && xerrno == EWOULDBLOCK) | ||
| 3479 | break; | ||
| 3480 | #endif | ||
| 3481 | #endif | ||
| 3482 | #endif | ||
| 3483 | |||
| 3484 | #ifndef WINDOWSNT | ||
| 3485 | if (xerrno == EINTR) | ||
| 3486 | { | ||
| 3487 | /* Unlike most other syscalls connect() cannot be called | ||
| 3488 | again. (That would return EALREADY.) The proper way to | ||
| 3489 | wait for completion is pselect(). */ | ||
| 3490 | int sc; | ||
| 3491 | socklen_t len; | ||
| 3492 | fd_set fdset; | ||
| 3493 | retry_select: | ||
| 3494 | FD_ZERO (&fdset); | ||
| 3495 | FD_SET (s, &fdset); | ||
| 3496 | QUIT; | ||
| 3497 | sc = pselect (s + 1, NULL, &fdset, NULL, NULL, NULL); | ||
| 3498 | if (sc == -1) | ||
| 3499 | { | ||
| 3500 | if (errno == EINTR) | ||
| 3501 | goto retry_select; | ||
| 3502 | else | ||
| 3503 | report_file_error ("Failed select", Qnil); | ||
| 3504 | } | ||
| 3505 | eassert (sc > 0); | ||
| 3506 | |||
| 3507 | len = sizeof xerrno; | ||
| 3508 | eassert (FD_ISSET (s, &fdset)); | ||
| 3509 | if (getsockopt (s, SOL_SOCKET, SO_ERROR, &xerrno, &len) < 0) | ||
| 3510 | report_file_error ("Failed getsockopt", Qnil); | ||
| 3511 | if (xerrno) | ||
| 3512 | report_file_errno ("Failed connect", Qnil, xerrno); | ||
| 3513 | break; | ||
| 3514 | } | ||
| 3515 | #endif /* !WINDOWSNT */ | ||
| 3516 | |||
| 3517 | immediate_quit = 0; | ||
| 3518 | |||
| 3519 | /* Discard the unwind protect closing S. */ | ||
| 3520 | specpdl_ptr = specpdl + count1; | ||
| 3521 | emacs_close (s); | ||
| 3522 | s = -1; | ||
| 3523 | |||
| 3524 | #ifdef WINDOWSNT | ||
| 3525 | if (xerrno == EINTR) | ||
| 3526 | goto retry_connect; | ||
| 3527 | #endif | ||
| 3528 | } | ||
| 3529 | |||
| 3530 | if (s >= 0) | ||
| 3531 | { | ||
| 3532 | #ifdef DATAGRAM_SOCKETS | ||
| 3533 | if (socktype == SOCK_DGRAM) | ||
| 3534 | { | ||
| 3535 | if (datagram_address[s].sa) | ||
| 3536 | emacs_abort (); | ||
| 3537 | datagram_address[s].sa = xmalloc (lres->ai_addrlen); | ||
| 3538 | datagram_address[s].len = lres->ai_addrlen; | ||
| 3539 | if (is_server) | ||
| 3540 | { | ||
| 3541 | Lisp_Object remote; | ||
| 3542 | memset (datagram_address[s].sa, 0, lres->ai_addrlen); | ||
| 3543 | if (remote = Fplist_get (contact, QCremote), !NILP (remote)) | ||
| 3544 | { | ||
| 3545 | int rfamily, rlen; | ||
| 3546 | rlen = get_lisp_to_sockaddr_size (remote, &rfamily); | ||
| 3547 | if (rlen != 0 && rfamily == lres->ai_family | ||
| 3548 | && rlen == lres->ai_addrlen) | ||
| 3549 | conv_lisp_to_sockaddr (rfamily, remote, | ||
| 3550 | datagram_address[s].sa, rlen); | ||
| 3551 | } | ||
| 3552 | } | ||
| 3553 | else | ||
| 3554 | memcpy (datagram_address[s].sa, lres->ai_addr, lres->ai_addrlen); | ||
| 3555 | } | ||
| 3556 | #endif | ||
| 3557 | contact = Fplist_put (contact, colon_address, | ||
| 3558 | conv_sockaddr_to_lisp (lres->ai_addr, lres->ai_addrlen)); | ||
| 3559 | #ifdef HAVE_GETSOCKNAME | ||
| 3560 | if (!is_server) | ||
| 3561 | { | ||
| 3562 | struct sockaddr_in sa1; | ||
| 3563 | socklen_t len1 = sizeof (sa1); | ||
| 3564 | if (getsockname (s, (struct sockaddr *)&sa1, &len1) == 0) | ||
| 3565 | contact = Fplist_put (contact, QClocal, | ||
| 3566 | conv_sockaddr_to_lisp ((struct sockaddr *)&sa1, len1)); | ||
| 3567 | } | ||
| 3568 | #endif | ||
| 3569 | } | ||
| 3570 | |||
| 3571 | immediate_quit = 0; | ||
| 3572 | |||
| 3573 | #ifdef HAVE_GETADDRINFO | ||
| 3574 | if (res != &ai) | ||
| 3575 | { | ||
| 3576 | block_input (); | ||
| 3577 | freeaddrinfo (res); | ||
| 3578 | unblock_input (); | ||
| 3579 | } | ||
| 3580 | #endif | ||
| 3581 | |||
| 3582 | if (s < 0) | ||
| 3583 | { | ||
| 3584 | /* If non-blocking got this far - and failed - assume non-blocking is | ||
| 3585 | not supported after all. This is probably a wrong assumption, but | ||
| 3586 | the normal blocking calls to open-network-stream handles this error | ||
| 3587 | better. */ | ||
| 3588 | if (is_non_blocking_client) | ||
| 3589 | return Qnil; | ||
| 3590 | |||
| 3591 | report_file_errno ((is_server | ||
| 3592 | ? "make server process failed" | ||
| 3593 | : "make client process failed"), | ||
| 3594 | contact, xerrno); | ||
| 3595 | } | ||
| 3596 | |||
| 3597 | inch = s; | ||
| 3598 | outch = s; | ||
| 3599 | |||
| 3600 | if (!NILP (buffer)) | 3724 | if (!NILP (buffer)) |
| 3601 | buffer = Fget_buffer_create (buffer); | 3725 | buffer = Fget_buffer_create (buffer); |
| 3602 | proc = make_process (name); | 3726 | proc = make_process (name); |
| 3603 | |||
| 3604 | chan_process[inch] = proc; | ||
| 3605 | |||
| 3606 | fcntl (inch, F_SETFL, O_NONBLOCK); | ||
| 3607 | |||
| 3608 | p = XPROCESS (proc); | 3727 | p = XPROCESS (proc); |
| 3609 | |||
| 3610 | pset_childp (p, contact); | 3728 | pset_childp (p, contact); |
| 3611 | pset_plist (p, Fcopy_sequence (Fplist_get (contact, QCplist))); | 3729 | pset_plist (p, Fcopy_sequence (Fplist_get (contact, QCplist))); |
| 3612 | pset_type (p, Qnetwork); | 3730 | pset_type (p, Qnetwork); |
| @@ -3620,135 +3738,38 @@ usage: (make-network-process &rest ARGS) */) | |||
| 3620 | if ((tem = Fplist_get (contact, QCstop), !NILP (tem))) | 3738 | if ((tem = Fplist_get (contact, QCstop), !NILP (tem))) |
| 3621 | pset_command (p, Qt); | 3739 | pset_command (p, Qt); |
| 3622 | p->pid = 0; | 3740 | p->pid = 0; |
| 3741 | p->backlog = 5; | ||
| 3742 | p->is_non_blocking_client = 0; | ||
| 3743 | p->is_server = 0; | ||
| 3744 | p->port = port; | ||
| 3745 | p->socktype = socktype; | ||
| 3746 | p->ai_protocol = ai_protocol; | ||
| 3623 | 3747 | ||
| 3624 | p->open_fd[SUBPROCESS_STDIN] = inch; | ||
| 3625 | p->infd = inch; | ||
| 3626 | p->outfd = outch; | ||
| 3627 | |||
| 3628 | /* Discard the unwind protect for closing S, if any. */ | ||
| 3629 | specpdl_ptr = specpdl + count1; | ||
| 3630 | |||
| 3631 | /* Unwind bind_polling_period and request_sigio. */ | ||
| 3632 | unbind_to (count, Qnil); | 3748 | unbind_to (count, Qnil); |
| 3633 | 3749 | ||
| 3634 | if (is_server && socktype != SOCK_DGRAM) | 3750 | /* :server BOOL */ |
| 3635 | pset_status (p, Qlisten); | 3751 | tem = Fplist_get (contact, QCserver); |
| 3636 | 3752 | if (!NILP (tem)) | |
| 3637 | /* Make the process marker point into the process buffer (if any). */ | ||
| 3638 | if (BUFFERP (buffer)) | ||
| 3639 | set_marker_both (p->mark, buffer, | ||
| 3640 | BUF_ZV (XBUFFER (buffer)), | ||
| 3641 | BUF_ZV_BYTE (XBUFFER (buffer))); | ||
| 3642 | |||
| 3643 | #ifdef NON_BLOCKING_CONNECT | ||
| 3644 | if (is_non_blocking_client) | ||
| 3645 | { | 3753 | { |
| 3646 | /* We may get here if connect did succeed immediately. However, | 3754 | /* Don't support network sockets when non-blocking mode is |
| 3647 | in that case, we still need to signal this like a non-blocking | 3755 | not available, since a blocked Emacs is not useful. */ |
| 3648 | connection. */ | 3756 | p->is_server = 1; |
| 3649 | pset_status (p, Qconnect); | 3757 | if (TYPE_RANGED_INTEGERP (int, tem)) |
| 3650 | if (!FD_ISSET (inch, &connect_wait_mask)) | 3758 | p->backlog = XINT (tem); |
| 3651 | { | ||
| 3652 | FD_SET (inch, &connect_wait_mask); | ||
| 3653 | FD_SET (inch, &write_mask); | ||
| 3654 | num_pending_connects++; | ||
| 3655 | } | ||
| 3656 | } | 3759 | } |
| 3657 | else | ||
| 3658 | #endif | ||
| 3659 | /* A server may have a client filter setting of Qt, but it must | ||
| 3660 | still listen for incoming connects unless it is stopped. */ | ||
| 3661 | if ((!EQ (p->filter, Qt) && !EQ (p->command, Qt)) | ||
| 3662 | || (EQ (p->status, Qlisten) && NILP (p->command))) | ||
| 3663 | { | ||
| 3664 | FD_SET (inch, &input_wait_mask); | ||
| 3665 | FD_SET (inch, &non_keyboard_wait_mask); | ||
| 3666 | } | ||
| 3667 | |||
| 3668 | if (inch > max_process_desc) | ||
| 3669 | max_process_desc = inch; | ||
| 3670 | |||
| 3671 | tem = Fplist_member (contact, QCcoding); | ||
| 3672 | if (!NILP (tem) && (!CONSP (tem) || !CONSP (XCDR (tem)))) | ||
| 3673 | tem = Qnil; /* No error message (too late!). */ | ||
| 3674 | |||
| 3675 | { | ||
| 3676 | /* Setup coding systems for communicating with the network stream. */ | ||
| 3677 | /* Qt denotes we have not yet called Ffind_operation_coding_system. */ | ||
| 3678 | Lisp_Object coding_systems = Qt; | ||
| 3679 | Lisp_Object val; | ||
| 3680 | |||
| 3681 | if (!NILP (tem)) | ||
| 3682 | { | ||
| 3683 | val = XCAR (XCDR (tem)); | ||
| 3684 | if (CONSP (val)) | ||
| 3685 | val = XCAR (val); | ||
| 3686 | } | ||
| 3687 | else if (!NILP (Vcoding_system_for_read)) | ||
| 3688 | val = Vcoding_system_for_read; | ||
| 3689 | else if ((!NILP (buffer) && NILP (BVAR (XBUFFER (buffer), enable_multibyte_characters))) | ||
| 3690 | || (NILP (buffer) && NILP (BVAR (&buffer_defaults, enable_multibyte_characters)))) | ||
| 3691 | /* We dare not decode end-of-line format by setting VAL to | ||
| 3692 | Qraw_text, because the existing Emacs Lisp libraries | ||
| 3693 | assume that they receive bare code including a sequence of | ||
| 3694 | CR LF. */ | ||
| 3695 | val = Qnil; | ||
| 3696 | else | ||
| 3697 | { | ||
| 3698 | if (NILP (host) || NILP (service)) | ||
| 3699 | coding_systems = Qnil; | ||
| 3700 | else | ||
| 3701 | coding_systems = CALLN (Ffind_operation_coding_system, | ||
| 3702 | Qopen_network_stream, name, buffer, | ||
| 3703 | host, service); | ||
| 3704 | if (CONSP (coding_systems)) | ||
| 3705 | val = XCAR (coding_systems); | ||
| 3706 | else if (CONSP (Vdefault_process_coding_system)) | ||
| 3707 | val = XCAR (Vdefault_process_coding_system); | ||
| 3708 | else | ||
| 3709 | val = Qnil; | ||
| 3710 | } | ||
| 3711 | pset_decode_coding_system (p, val); | ||
| 3712 | 3760 | ||
| 3713 | if (!NILP (tem)) | 3761 | /* :nowait BOOL */ |
| 3714 | { | 3762 | if (!p->is_server && socktype != SOCK_DGRAM |
| 3715 | val = XCAR (XCDR (tem)); | 3763 | && (tem = Fplist_get (contact, QCnowait), !NILP (tem))) |
| 3716 | if (CONSP (val)) | 3764 | { |
| 3717 | val = XCDR (val); | 3765 | #ifndef NON_BLOCKING_CONNECT |
| 3718 | } | 3766 | error ("Non-blocking connect not supported"); |
| 3719 | else if (!NILP (Vcoding_system_for_write)) | 3767 | #else |
| 3720 | val = Vcoding_system_for_write; | 3768 | p->is_non_blocking_client = 1; |
| 3721 | else if (NILP (BVAR (current_buffer, enable_multibyte_characters))) | 3769 | #endif |
| 3722 | val = Qnil; | 3770 | } |
| 3723 | else | ||
| 3724 | { | ||
| 3725 | if (EQ (coding_systems, Qt)) | ||
| 3726 | { | ||
| 3727 | if (NILP (host) || NILP (service)) | ||
| 3728 | coding_systems = Qnil; | ||
| 3729 | else | ||
| 3730 | coding_systems = CALLN (Ffind_operation_coding_system, | ||
| 3731 | Qopen_network_stream, name, buffer, | ||
| 3732 | host, service); | ||
| 3733 | } | ||
| 3734 | if (CONSP (coding_systems)) | ||
| 3735 | val = XCDR (coding_systems); | ||
| 3736 | else if (CONSP (Vdefault_process_coding_system)) | ||
| 3737 | val = XCDR (Vdefault_process_coding_system); | ||
| 3738 | else | ||
| 3739 | val = Qnil; | ||
| 3740 | } | ||
| 3741 | pset_encode_coding_system (p, val); | ||
| 3742 | } | ||
| 3743 | setup_process_coding_systems (proc); | ||
| 3744 | |||
| 3745 | pset_decoding_buf (p, empty_unibyte_string); | ||
| 3746 | p->decoding_carryover = 0; | ||
| 3747 | pset_encoding_buf (p, empty_unibyte_string); | ||
| 3748 | |||
| 3749 | p->inherit_coding_system_flag | ||
| 3750 | = !(!NILP (tem) || NILP (buffer) || !inherit_process_coding_system); | ||
| 3751 | 3771 | ||
| 3772 | connect_network_socket (proc, ip_addresses); | ||
| 3752 | return proc; | 3773 | return proc; |
| 3753 | } | 3774 | } |
| 3754 | 3775 | ||