Patch 8.2.4684
Problem: Cannot open a channel on a Unix domain socket.
Solution: Add Unix domain socket support. (closes #10062)
Files: runtime/doc/channel.txt, src/channel.c, src/testdir/check.vim,
src/testdir/shared.vim, src/testdir/test_channel.py,
src/testdir/test_channel.vim, src/testdir/test_channel_unix.py,
src/testdir/test_cmdline.vim
*** ../vim-8.2.4683/runtime/doc/channel.txt 2022-03-30 10:14:41.485657271 +0100
--- runtime/doc/channel.txt 2022-04-04 15:39:23.550236560 +0100
***************
*** 119,128 ****
Use |ch_status()| to see if the channel could be opened.
! {address} has the form "hostname:port". E.g., "localhost:8765".
!
! When using an IPv6 address, enclose it within square brackets. E.g.,
! "[2001:db8::1]:8765".
{options} is a dictionary with optional entries: *channel-open-options*
--- 119,131 ----
Use |ch_status()| to see if the channel could be opened.
! *channel-address*
! {address} can be a domain name or an IP address, followed by a port number, or
! a Unix-domain socket path prefixed by "unix:". E.g. >
!
www.example.com:80 " domain + port
!
127.0.0.1:1234 " IPv4 + port
! [2001:db8::1]:8765 " IPv6 + port
! unix:/tmp/my-socket " Unix-domain socket path
{options} is a dictionary with optional entries: *channel-open-options*
***************
*** 579,588 ****
--- 582,596 ----
When opened with ch_open():
"hostname" the hostname of the address
"port" the port of the address
+ "path" the path of the Unix-domain socket
"sock_status" "open" or "closed"
"sock_mode" "NL", "RAW", "JSON" or "JS"
"sock_io" "socket"
"sock_timeout" timeout in msec
+
+ Note that "pair" is only present for Unix-domain sockets, for
+ regular ones "hostname" and "port" are present instead.
+
When opened with job_start():
"out_status" "open", "buffered" or "closed"
"out_mode" "NL", "RAW", "JSON" or "JS"
***************
*** 641,651 ****
Open a channel to {address}. See |channel|.
Returns a Channel. Use |ch_status()| to check for failure.
! {address} is a String and has the form "hostname:port", e.g.,
! "localhost:8765".
!
! When using an IPv6 address, enclose it within square brackets.
! E.g., "[2001:db8::1]:8765".
If {options} is given it must be a |Dictionary|.
See |channel-open-options|.
--- 649,656 ----
Open a channel to {address}. See |channel|.
Returns a Channel. Use |ch_status()| to check for failure.
! {address} is a String, see |channel-address| for the possible
! accepted forms.
If {options} is given it must be a |Dictionary|.
See |channel-open-options|.
*** ../vim-8.2.4683/src/channel.c 2022-04-04 15:16:50.738014123 +0100
--- src/channel.c 2022-04-04 15:44:12.318053555 +0100
***************
*** 44,54 ****
--- 44,61 ----
# define sock_write(sd, buf, len) send((SOCKET)sd, buf, len, 0)
# define sock_read(sd, buf, len) recv((SOCKET)sd, buf, len, 0)
# define sock_close(sd) closesocket((SOCKET)sd)
+ // Support for Unix-domain sockets was added in Windows SDK 17061.
+ # define UNIX_PATH_MAX 108
+ typedef struct sockaddr_un {
+ ADDRESS_FAMILY sun_family;
+ char sun_path[UNIX_PATH_MAX];
+ } SOCKADDR_UN, *PSOCKADDR_UN;
#else
# include <netdb.h>
# include <netinet/in.h>
# include <arpa/inet.h>
# include <sys/socket.h>
+ # include <sys/un.h>
# ifdef HAVE_LIBGEN_H
# include <libgen.h>
# endif
***************
*** 929,934 ****
--- 936,1002 ----
}
/*
+ * Open a socket channel to the UNIX socket at "path".
+ * Returns the channel for success.
+ * Returns NULL for failure.
+ */
+ static channel_T *
+ channel_open_unix(
+ const char *path,
+ void (*nb_close_cb)(void))
+ {
+ channel_T *channel = NULL;
+ int sd = -1;
+ size_t path_len = STRLEN(path);
+ struct sockaddr_un server;
+ size_t server_len;
+ int waittime = -1;
+
+ if (*path == NUL || path_len >= sizeof(server.sun_path))
+ {
+ semsg(_(e_invalid_argument_str), path);
+ return NULL;
+ }
+
+ channel = add_channel();
+ if (channel == NULL)
+ {
+ ch_error(NULL, "Cannot allocate channel.");
+ return NULL;
+ }
+
+ CLEAR_FIELD(server);
+ server.sun_family = AF_UNIX;
+ STRNCPY(server.sun_path, path, sizeof(server.sun_path) - 1);
+
+ ch_log(channel, "Trying to connect to %s", path);
+
+ server_len = offsetof(struct sockaddr_un, sun_path) + path_len + 1;
+ sd = channel_connect(channel, (struct sockaddr *)&server, (int)server_len,
+ &waittime);
+
+ if (sd < 0)
+ {
+ channel_free(channel);
+ return NULL;
+ }
+
+ ch_log(channel, "Connection made");
+
+ channel->CH_SOCK_FD = (sock_T)sd;
+ channel->ch_nb_close_cb = nb_close_cb;
+ channel->ch_hostname = (char *)vim_strsave((char_u *)path);
+ channel->ch_port = 0;
+ channel->ch_to_be_closed |= (1U << PART_SOCK);
+
+ #ifdef FEAT_GUI
+ channel_gui_register_one(channel, PART_SOCK);
+ #endif
+
+ return channel;
+ }
+
+ /*
* Open a socket channel to "hostname":"port".
* "waittime" is the time in msec to wait for the connection.
* When negative wait forever.
***************
*** 1301,1308 ****
char_u *address;
char_u *p;
char *rest;
! int port;
int is_ipv6 = FALSE;
jobopt_T opt;
channel_T *channel = NULL;
--- 1369,1377 ----
char_u *address;
char_u *p;
char *rest;
! int port = 0;
int is_ipv6 = FALSE;
+ int is_unix = FALSE;
jobopt_T opt;
channel_T *channel = NULL;
***************
*** 1319,1326 ****
return NULL;
}
! // parse address
! if (*address == '[')
{
// ipv6 address
is_ipv6 = TRUE;
--- 1388,1405 ----
return NULL;
}
! if (*address == NUL)
! {
! semsg(_(e_invalid_argument_str), address);
! return NULL;
! }
!
! if (!STRNCMP(address, "unix:", 5))
! {
! is_unix = TRUE;
! address += 5;
! }
! else if (*address == '[')
{
// ipv6 address
is_ipv6 = TRUE;
***************
*** 1333,1338 ****
--- 1412,1418 ----
}
else
{
+ // ipv4 address
p = vim_strchr(address, ':');
if (p == NULL)
{
***************
*** 1340,1366 ****
return NULL;
}
}
! port = strtol((char *)(p + 1), &rest, 10);
! if (*address == NUL || port <= 0 || port >= 65536 || *rest != NUL)
! {
! semsg(_(e_invalid_argument_str), address);
! return NULL;
! }
! if (is_ipv6)
{
! // strip '[' and ']'
! ++address;
! *(p - 1) = NUL;
}
- else
- *p = NUL;
// parse options
clear_job_options(&opt);
opt.jo_mode = MODE_JSON;
opt.jo_timeout = 2000;
if (get_job_options(&argvars[1], &opt,
! JO_MODE_ALL + JO_CB_ALL + JO_WAITTIME + JO_TIMEOUT_ALL, 0) == FAIL)
goto theend;
if (opt.jo_timeout < 0)
{
--- 1420,1451 ----
return NULL;
}
}
!
! if (!is_unix)
{
! port = strtol((char *)(p + 1), &rest, 10);
! if (port <= 0 || port >= 65536 || *rest != NUL)
! {
! semsg(_(e_invalid_argument_str), address);
! return NULL;
! }
! if (is_ipv6)
! {
! // strip '[' and ']'
! ++address;
! *(p - 1) = NUL;
! }
! else
! *p = NUL;
}
// parse options
clear_job_options(&opt);
opt.jo_mode = MODE_JSON;
opt.jo_timeout = 2000;
if (get_job_options(&argvars[1], &opt,
! JO_MODE_ALL + JO_CB_ALL + JO_TIMEOUT_ALL
! + (is_unix? 0 : JO_WAITTIME), 0) == FAIL)
goto theend;
if (opt.jo_timeout < 0)
{
***************
*** 1368,1374 ****
goto theend;
}
! channel = channel_open((char *)address, port, opt.jo_waittime, NULL);
if (channel != NULL)
{
opt.jo_set = JO_ALL;
--- 1453,1462 ----
goto theend;
}
! if (is_unix)
! channel = channel_open_unix((char *)address, NULL);
! else
! channel = channel_open((char *)address, port, opt.jo_waittime, NULL);
if (channel != NULL)
{
opt.jo_set = JO_ALL;
***************
*** 3268,3275 ****
if (channel->ch_hostname != NULL)
{
! dict_add_string(dict, "hostname", (char_u *)channel->ch_hostname);
! dict_add_number(dict, "port", channel->ch_port);
channel_part_info(channel, dict, "sock", PART_SOCK);
}
else
--- 3356,3369 ----
if (channel->ch_hostname != NULL)
{
! if (channel->ch_port)
! {
! dict_add_string(dict, "hostname", (char_u *)channel->ch_hostname);
! dict_add_number(dict, "port", channel->ch_port);
! }
! else
! // Unix-domain socket.
! dict_add_string(dict, "path", (char_u *)channel->ch_hostname);
channel_part_info(channel, dict, "sock", PART_SOCK);
}
else
*** ../vim-8.2.4683/src/testdir/check.vim 2021-10-16 21:58:23.206049605 +0100
--- src/testdir/check.vim 2022-04-04 15:39:23.550236560 +0100
***************
*** 95,101 ****
endif
endfunc
! " Command to check for running on Linix
command CheckLinux call CheckLinux()
func CheckLinux()
if !has('linux')
--- 95,101 ----
endif
endfunc
! " Command to check for running on Linux
command CheckLinux call CheckLinux()
func CheckLinux()
if !has('linux')
*** ../vim-8.2.4683/src/testdir/shared.vim 2021-05-02 18:14:55.466643569 +0100
--- src/testdir/shared.vim 2022-04-04 15:39:23.550236560 +0100
***************
*** 15,24 ****
if has('unix')
" We also need the job feature or the pkill command to make sure the server
" can be stopped.
! if !(executable('python') && (has('job') || executable('pkill')))
return ''
endif
! let s:python = 'python'
elseif has('win32')
" Use Python Launcher for Windows (py.exe) if available.
" NOTE: if you get a "Python was not found" error, disable the Python
--- 15,30 ----
if has('unix')
" We also need the job feature or the pkill command to make sure the server
" can be stopped.
! if !(has('job') || executable('pkill'))
return ''
endif
! if executable('python')
! let s:python = 'python'
! elseif executable('python3')
! let s:python = 'python3'
! else
! return ''
! end
elseif has('win32')
" Use Python Launcher for Windows (py.exe) if available.
" NOTE: if you get a "Python was not found" error, disable the Python
*** ../vim-8.2.4683/src/testdir/test_channel.py 2021-07-30 20:56:07.110143138 +0100
--- src/testdir/test_channel.py 2022-04-04 15:39:23.550236560 +0100
***************
*** 22,28 ****
class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
def setup(self):
! self.request.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
def handle(self):
print("=== socket opened ===")
--- 22,29 ----
class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
def setup(self):
! if self.server.address_family != socket.AF_UNIX:
! self.request.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
def handle(self):
print("=== socket opened ===")
*** ../vim-8.2.4683/src/testdir/test_channel.vim 2022-03-30 10:14:41.489657276 +0100
--- src/testdir/test_channel.vim 2022-04-04 15:39:23.550236560 +0100
***************
*** 23,28 ****
--- 23,31 ----
if g:testfunc =~ '_ipv6()$'
let s:localhost = '[::1]:'
let s:testscript = 'test_channel_6.py'
+ elseif g:testfunc =~ '_unix()$'
+ let s:localhost = 'unix:Xtestsocket'
+ let s:testscript = 'test_channel_unix.py'
else
let s:localhost = 'localhost:'
let s:testscript = 'test_channel.py'
***************
*** 39,44 ****
--- 42,56 ----
call RunServer(s:testscript, a:testfunc, a:000)
endfunc
+ " Returns the address of the test server.
+ func s:address(port)
+ if s:localhost =~ '^unix:'
+ return s:localhost
+ else
+ return s:localhost . a:port
+ end
+ endfunc
+
" Return a list of open files.
" Can be used to make sure no resources leaked.
" Returns an empty list on systems where this is not supported.
***************
*** 65,71 ****
let s:chopt.drop = 'never'
" Also add the noblock flag to try it out.
let s:chopt.noblock = 1
! let handle = ch_open(s:localhost . a:port, s:chopt)
if ch_status(handle) == "fail"
call assert_report("Can't open channel")
return
--- 77,83 ----
let s:chopt.drop = 'never'
" Also add the noblock flag to try it out.
let s:chopt.noblock = 1
! let handle = ch_open(s:address(a:port), s:chopt)
if ch_status(handle) == "fail"
call assert_report("Can't open channel")
return
***************
*** 77,83 ****
let dict = handle->ch_info()
call assert_true(
dict.id != 0)
call assert_equal('open', dict.status)
! call assert_equal(a:port, string(dict.port))
call assert_equal('open', dict.sock_status)
call assert_equal('socket', dict.sock_io)
--- 89,98 ----
let dict = handle->ch_info()
call assert_true(
dict.id != 0)
call assert_equal('open', dict.status)
! if has_key(dict, 'port')
! " Channels using Unix sockets have no 'port' entry.
! call assert_equal(a:port, string(dict.port))
! end
call assert_equal('open', dict.sock_status)
call assert_equal('socket', dict.sock_io)
***************
*** 252,264 ****
func Test_communicate_ipv6()
CheckIPv6
call Test_communicate()
endfunc
" Test that we can open two channels.
func Ch_two_channels(port)
! let handle = ch_open(s:localhost . a:port, s:chopt)
call assert_equal(v:t_channel, type(handle))
if handle->ch_status() == "fail"
call assert_report("Can't open channel")
--- 267,285 ----
func Test_communicate_ipv6()
CheckIPv6
+ call Test_communicate()
+ endfunc
+ func Test_communicate_unix()
+ CheckUnix
call Test_communicate()
+ call delete('Xtestsocket')
endfunc
+
" Test that we can open two channels.
func Ch_two_channels(port)
! let handle = ch_open(s:address(a:port), s:chopt)
call assert_equal(v:t_channel, type(handle))
if handle->ch_status() == "fail"
call assert_report("Can't open channel")
***************
*** 267,273 ****
call assert_equal('got it', ch_evalexpr(handle, 'hello!'))
! let newhandle = ch_open(s:localhost . a:port, s:chopt)
if ch_status(newhandle) == "fail"
call assert_report("Can't open second channel")
return
--- 288,294 ----
call assert_equal('got it', ch_evalexpr(handle, 'hello!'))
! let newhandle = ch_open(s:address(a:port), s:chopt)
if ch_status(newhandle) == "fail"
call assert_report("Can't open second channel")
return
***************
*** 292,300 ****
call Test_two_channels()
endfunc
" Test that a server crash is handled gracefully.
func Ch_server_crash(port)
! let handle = ch_open(s:localhost . a:port, s:chopt)
if ch_status(handle) == "fail"
call assert_report("Can't open channel")
return
--- 313,327 ----
call Test_two_channels()
endfunc
+ func Test_two_channels_unix()
+ CheckUnix
+ call Test_two_channels()
+ call delete('Xtestsocket')
+ endfunc
+
" Test that a server crash is handled gracefully.
func Ch_server_crash(port)
! let handle = ch_open(s:address(a:port), s:chopt)
if ch_status(handle) == "fail"
call assert_report("Can't open channel")
return
***************
*** 314,319 ****
--- 341,352 ----
call Test_server_crash()
endfunc
+ func Test_server_crash_unix()
+ CheckUnix
+ call Test_server_crash()
+ call delete('Xtestsocket')
+ endfunc
+
"""""""""
func Ch_handler(chan, msg)
***************
*** 323,329 ****
endfunc
func Ch_channel_handler(port)
! let handle = ch_open(s:localhost . a:port, s:chopt)
if ch_status(handle) == "fail"
call assert_report("Can't open channel")
return
--- 356,362 ----
endfunc
func Ch_channel_handler(port)
! let handle = ch_open(s:address(a:port), s:chopt)
if ch_status(handle) == "fail"
call assert_report("Can't open channel")
return
***************
*** 352,357 ****
--- 385,396 ----
call Test_channel_handler()
endfunc
+ func Test_channel_handler_unix()
+ CheckUnix
+ call Test_channel_handler()
+ call delete('Xtestsocket')
+ endfunc
+
"""""""""
let g:Ch_reply = ''
***************
*** 367,373 ****
endfunc
func Ch_channel_zero(port)
! let handle = (s:localhost .. a:port)->ch_open(s:chopt)
if ch_status(handle) == "fail"
call assert_report("Can't open channel")
return
--- 406,412 ----
endfunc
func Ch_channel_zero(port)
! let handle = (s:address(a:port))->ch_open(s:chopt)
if ch_status(handle) == "fail"
call assert_report("Can't open channel")
return
***************
*** 415,420 ****
--- 454,466 ----
call Test_zero_reply()
endfunc
+ func Test_zero_reply_unix()
+ CheckUnix
+ call Test_zero_reply()
+ call delete('Xtestsocket')
+ endfunc
+
+
"""""""""
let g:Ch_reply1 = ""
***************
*** 436,442 ****
endfunc
func Ch_raw_one_time_callback(port)
! let handle = ch_open(s:localhost . a:port, s:chopt)
if ch_status(handle) == "fail"
call assert_report("Can't open channel")
return
--- 482,488 ----
endfunc
func Ch_raw_one_time_callback(port)
! let handle = ch_open(s:address(a:port), s:chopt)
if ch_status(handle) == "fail"
call assert_report("Can't open channel")
return
***************
*** 462,467 ****
--- 508,519 ----
call Test_raw_one_time_callback()
endfunc
+ func Test_raw_one_time_callback_unix()
+ CheckUnix
+ call Test_raw_one_time_callback()
+ call delete('Xtestsocket')
+ endfunc
+
"""""""""
" Test that trying to connect to a non-existing port fails quickly.
***************
*** 1398,1404 ****
" Test that "unlet handle" in a handler doesn't crash Vim.
func Ch_unlet_handle(port)
! let s:channelfd = ch_open(s:localhost . a:port, s:chopt)
eval s:channelfd->ch_sendexpr("test", {'callback': function('s:UnletHandler')})
call WaitForAssert({-> assert_equal('what?', g:Ch_unletResponse)})
endfunc
--- 1450,1456 ----
" Test that "unlet handle" in a handler doesn't crash Vim.
func Ch_unlet_handle(port)
! let s:channelfd = ch_open(s:address(a:port), s:chopt)
eval s:channelfd->ch_sendexpr("test", {'callback': function('s:UnletHandler')})
call WaitForAssert({-> assert_equal('what?', g:Ch_unletResponse)})
endfunc
***************
*** 1422,1428 ****
" Test that "unlet handle" in a handler doesn't crash Vim.
func Ch_close_handle(port)
! let s:channelfd = ch_open(s:localhost . a:port, s:chopt)
call ch_sendexpr(s:channelfd, "test", {'callback': function('Ch_CloseHandler')})
call WaitForAssert({-> assert_equal('what?', g:Ch_unletResponse)})
endfunc
--- 1474,1480 ----
" Test that "unlet handle" in a handler doesn't crash Vim.
func Ch_close_handle(port)
! let s:channelfd = ch_open(s:address(a:port), s:chopt)
call ch_sendexpr(s:channelfd, "test", {'callback': function('Ch_CloseHandler')})
call WaitForAssert({-> assert_equal('what?', g:Ch_unletResponse)})
endfunc
***************
*** 1439,1445 ****
""""""""""
func Ch_open_ipv6(port)
! let handle = ch_open('[::1]:' .. a:port, s:chopt)
call assert_notequal('fail', ch_status(handle))
endfunc
--- 1491,1497 ----
""""""""""
func Ch_open_ipv6(port)
! let handle = ch_open(s:address(a:port), s:chopt)
call assert_notequal('fail', ch_status(handle))
endfunc
***************
*** 1479,1485 ****
func Ch_open_delay(port)
" Wait up to a second for the port to open.
let s:chopt.waittime = 1000
! let channel = ch_open(s:localhost . a:port, s:chopt)
if ch_status(channel) == "fail"
call assert_report("Can't open channel")
return
--- 1531,1537 ----
func Ch_open_delay(port)
" Wait up to a second for the port to open.
let s:chopt.waittime = 1000
! let channel = ch_open(s:address(a:port), s:chopt)
if ch_status(channel) == "fail"
call assert_report("Can't open channel")
return
***************
*** 1505,1511 ****
endfunc
function Ch_test_call(port)
! let handle = ch_open(s:localhost . a:port, s:chopt)
if ch_status(handle) == "fail"
call assert_report("Can't open channel")
return
--- 1557,1563 ----
endfunc
function Ch_test_call(port)
! let handle = ch_open(s:address(a:port), s:chopt)
if ch_status(handle) == "fail"
call assert_report("Can't open channel")
return
***************
*** 1529,1534 ****
--- 1581,1592 ----
call Test_call()
endfunc
+ func Test_call_unix()
+ CheckUnix
+ call Test_call()
+ call delete('Xtestsocket')
+ endfunc
+
"""""""""
let g:Ch_job_exit_ret = 'not yet'
***************
*** 1605,1611 ****
endfunc
function Ch_test_close_callback(port)
! let handle = ch_open(s:localhost . a:port, s:chopt)
if ch_status(handle) == "fail"
call assert_report("Can't open channel")
return
--- 1663,1669 ----
endfunc
function Ch_test_close_callback(port)
! let handle = ch_open(s:address(a:port), s:chopt)
if ch_status(handle) == "fail"
call assert_report("Can't open channel")
return
***************
*** 1625,1632 ****
call Test_close_callback()
endfunc
function Ch_test_close_partial(port)
! let handle = ch_open(s:localhost . a:port, s:chopt)
if ch_status(handle) == "fail"
call assert_report("Can't open channel")
return
--- 1683,1696 ----
call Test_close_callback()
endfunc
+ func Test_close_callback_unix()
+ CheckUnix
+ call Test_close_callback()
+ call delete('Xtestsocket')
+ endfunc
+
function Ch_test_close_partial(port)
! let handle = ch_open(s:address(a:port), s:chopt)
if ch_status(handle) == "fail"
call assert_report("Can't open channel")
return
***************
*** 1651,1656 ****
--- 1715,1726 ----
call Test_close_partial()
endfunc
+ func Test_close_partial_unix()
+ CheckUnix
+ call Test_close_partial()
+ call delete('Xtestsocket')
+ endfunc
+
func Test_job_start_fails()
" this was leaking memory
call assert_fails("call job_start([''])", "E474:")
***************
*** 1920,1926 ****
endfunc
function Ch_test_close_lambda(port)
! let handle = ch_open(s:localhost . a:port, s:chopt)
if ch_status(handle) == "fail"
call assert_report("Can't open channel")
return
--- 1990,1996 ----
endfunc
function Ch_test_close_lambda(port)
! let handle = ch_open(s:address(a:port), s:chopt)
if ch_status(handle) == "fail"
call assert_report("Can't open channel")
return
***************
*** 1942,1947 ****
--- 2012,2023 ----
call Test_close_lambda()
endfunc
+ func Test_close_lambda_unix()
+ CheckUnix
+ call Test_close_lambda()
+ call delete('Xtestsocket')
+ endfunc
+
func s:test_list_args(cmd, out, remove_lf)
try
let g:out = ''
***************
*** 2243,2248 ****
--- 2319,2326 ----
let job = job_start("cat ", #{in_io: 'null'})
call WaitForAssert({-> assert_equal("dead", job_status(job))})
call assert_equal(0, job_info(job).exitval)
+
+ call delete('Xtestsocket')
endfunc
func Test_ch_getbufnr()
*** ../vim-8.2.4683/src/testdir/test_channel_unix.py 2022-04-04 15:45:57.774034889 +0100
--- src/testdir/test_channel_unix.py 2022-04-04 15:39:23.550236560 +0100
***************
*** 0 ****
--- 1,50 ----
+ #!/usr/bin/env python
+ #
+ # Server that will accept connections from a Vim channel.
+ # Used by test_channel.vim.
+ #
+ # This requires Python 2.6 or later.
+
+ from __future__ import print_function
+ from test_channel import ThreadedTCPServer, ThreadedTCPRequestHandler, \
+ writePortInFile
+ import socket
+ import threading
+ import os
+
+ try:
+ FileNotFoundError
+ except NameError:
+ # Python 2
+ FileNotFoundError = (IOError, OSError)
+
+ class ThreadedUnixServer(ThreadedTCPServer):
+ address_family = socket.AF_UNIX
+
+ def main(path):
+ server = ThreadedUnixServer(path, ThreadedTCPRequestHandler)
+
+ # Start a thread with the server. That thread will then start a new thread
+ # for each connection.
+ server_thread = threading.Thread(target=server.serve_forever)
+ server_thread.start()
+
+ # Signal the test harness we're ready, the port value has no meaning.
+ writePortInFile(1234)
+
+ print("Listening on {0}".format(server.server_address))
+
+ # Main thread terminates, but the server continues running
+ # until server.shutdown() is called.
+ try:
+ while server_thread.is_alive():
+ server_thread.join(1)
+ except (KeyboardInterrupt, SystemExit):
+ server.shutdown()
+
+ if __name__ == "__main__":
+ try:
+ os.remove("Xtestsocket")
+ except FileNotFoundError:
+ pass
+ main("Xtestsocket")
*** ../vim-8.2.4683/src/testdir/test_cmdline.vim 2022-03-31 12:33:56.485701120 +0100
--- src/testdir/test_cmdline.vim 2022-04-04 15:39:23.550236560 +0100
***************
*** 620,627 ****
\ ':5s': 'substitute',
\ "'<,'>s": 'substitute',
\ ":'<,'>s": 'substitute',
! \ 'CheckUni': 'CheckUnix',
! \ 'CheckUnix': 'CheckUnix',
\ }
for [in, want] in items(tests)
--- 620,627 ----
\ ':5s': 'substitute',
\ "'<,'>s": 'substitute',
\ ":'<,'>s": 'substitute',
! \ 'CheckLin': 'CheckLinux',
! \ 'CheckLinux': 'CheckLinux',
\ }
for [in, want] in items(tests)
*** ../vim-8.2.4683/src/version.c 2022-04-04 15:16:50.746014138 +0100
--- src/version.c 2022-04-04 15:40:33.482194513 +0100
***************
*** 752,753 ****
--- 752,755 ----
{ /* Add new patch number below this line */
+ /**/
+ 4684,
/**/
--
You can be stopped by the police for biking over 65 miles per hour.
You are not allowed to walk across a street on your hands.
[real standing laws in Connecticut, United States of America]
/// Bram Moolenaar -- Br...@Moolenaar.net --
http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features --
http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims --
http://ICCF-Holland.org ///