diff options
-rw-r--r-- | erts/emulator/sys/unix/sys_drivers.c | 26 | ||||
-rw-r--r-- | erts/emulator/test/socket_SUITE.erl | 71 | ||||
-rw-r--r-- | lib/kernel/test/interactive_shell_SUITE.erl | 60 | ||||
-rw-r--r-- | lib/kernel/test/interactive_shell_SUITE_data/.gitignore | 1 | ||||
-rw-r--r-- | lib/kernel/test/interactive_shell_SUITE_data/io_columns.erl | 6 | ||||
-rw-r--r-- | lib/kernel/test/interactive_shell_SUITE_data/io_rows.erl | 6 |
6 files changed, 134 insertions, 36 deletions
diff --git a/erts/emulator/sys/unix/sys_drivers.c b/erts/emulator/sys/unix/sys_drivers.c index 664d677ebd..92020c6f35 100644 --- a/erts/emulator/sys/unix/sys_drivers.c +++ b/erts/emulator/sys/unix/sys_drivers.c @@ -785,15 +785,15 @@ static ErlDrvSSizeT spawn_control(ErlDrvData e, unsigned int cmd, char *buf, static int fd_get_window_size(int fd, Uint32 *width, Uint32 *height) { -#ifdef TIOCGWINSZ +#ifdef TIOCGWINSZ struct winsize ws; if (ioctl(fd,TIOCGWINSZ,&ws) == 0) { *width = (Uint32) ws.ws_col; *height = (Uint32) ws.ws_row; - return 0; + return 1; } #endif - return -1; + return 0; } static ErlDrvSSizeT fd_control(ErlDrvData drv_data, @@ -801,16 +801,28 @@ static ErlDrvSSizeT fd_control(ErlDrvData drv_data, char *buf, ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen) { - int fd = (int)(long)drv_data; char resbuff[2*sizeof(Uint32)]; - + ErtsSysDriverData* dd = (ErtsSysDriverData*)drv_data; command -= ERTS_TTYSL_DRV_CONTROL_MAGIC_NUMBER; switch (command) { case FD_CTRL_OP_GET_WINSIZE: { Uint32 w,h; - if (fd_get_window_size(fd,&w,&h)) - return 0; + int success = 0; + if (dd->ofd != NULL) { + /* Try with output file descriptor */ + int out_fd = dd->ofd->fd; + success = fd_get_window_size(out_fd,&w,&h); + } + if (!success && dd->ifd != NULL) { + /* Try with input file descriptor */ + int in_fd = dd->ifd->fd; + success = fd_get_window_size(in_fd,&w,&h); + } + if (!success) { + return -1; + } + /* Succeeded */ memcpy(resbuff,&w,sizeof(Uint32)); memcpy(resbuff+sizeof(Uint32),&h,sizeof(Uint32)); } diff --git a/erts/emulator/test/socket_SUITE.erl b/erts/emulator/test/socket_SUITE.erl index be6b550891..786a6fc2fc 100644 --- a/erts/emulator/test/socket_SUITE.erl +++ b/erts/emulator/test/socket_SUITE.erl @@ -1752,13 +1752,15 @@ has_bugfree_gcc() -> %% Make sure we are on linux has_bugfree_gcc({unix, linux}) -> - has_bugfree_gcc2(os:cmd("cat /etc/issue")); + has_bugfree_gcc2(string:trim(os:cmd("cat /etc/issue"))); has_bugfree_gcc(_) -> ok. %% Make sure we are on Fedora 16 has_bugfree_gcc2("Fedora release 16 " ++ _) -> has_bugfree_gcc3(os:cmd("gcc --version")); +has_bugfree_gcc2("Welcome to SUSE Linux " ++ _) -> + has_bugfree_gcc4(os:cmd("gcc --version")); has_bugfree_gcc2(_) -> ok. @@ -1767,6 +1769,11 @@ has_bugfree_gcc3("gcc (GCC) 4.6.3 20120306 (Red Hat 4.6.3-2" ++ _) -> has_bugfree_gcc3(_) -> ok. +has_bugfree_gcc4("gcc (SUSE Linux) 4.3.2" ++ _) -> + skip("Buggy GCC"); +has_bugfree_gcc4(_) -> + ok. + api_m_debug() -> i("get initial info"), #{debug := D0} = socket:info(), @@ -1784,6 +1791,7 @@ api_m_debug() -> ok. + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% %% @@ -8605,6 +8613,7 @@ which_multicast_address(Domain) -> which_multicast_address2(Domain, WhichMAddr); Type -> + %% Actually, what is "not supported". is netstat! not_supported({multicast, Type}) end. @@ -8614,20 +8623,28 @@ which_multicast_address(Domain) -> which_multicast_address2(Domain, WhichMAddr) -> IfName = which_local_host_ifname(Domain), - try - begin - %% On some platforms the netstat barfs out some crap on stderr - %% before the actual info... - NetstatGroupsStr = os:cmd("netstat -g 2>/dev/null | grep " ++ IfName), - NetstatGroups0 = string:tokens(NetstatGroupsStr, [$\n]), - NetstatGroups = [string:tokens(G, [$ ]) || G <- NetstatGroups0], - MAddrs = [WhichMAddr(NetstatGroup) || NetstatGroup <- - NetstatGroups], - which_multicast_address3(Domain, MAddrs) - end - catch - C:E:S -> - not_supported({multicast, {C,E,S}}) + %% On some platforms the netstat barfs out some crap on stderr + %% before the actual info... + case os:cmd("netstat -g 2>/dev/null | grep " ++ IfName) of + [] -> + %% Can't figure out if we support multicast or not... + not_supported(no_netstat); + NetstatGroupsStr -> + try + begin + NetstatGroups0 = string:tokens(NetstatGroupsStr, [$\n]), + NetstatGroups = [string:tokens(G, [$ ]) || + G <- NetstatGroups0], + MAddrs = [WhichMAddr(NetstatGroup) || + NetstatGroup <- NetstatGroups], + which_multicast_address3(Domain, MAddrs) + end + catch + throw:E:_ -> + throw(E); + C:E:S -> + not_supported({multicast, {C,E,S}}) + end end. which_multicast_address3(_Domain, []) -> @@ -17821,12 +17838,12 @@ traffic_ping_pong_small_sendto_and_recvfrom_udp6(suite) -> traffic_ping_pong_small_sendto_and_recvfrom_udp6(doc) -> []; traffic_ping_pong_small_sendto_and_recvfrom_udp6(_Config) when is_list(_Config) -> - ?TT(?SECS(45)), Msg = l2b(?TPP_SMALL), Num = ?TPP_SMALL_NUM, tc_try(traffic_ping_pong_small_sendto_and_recvfrom_udp6, fun() -> has_support_ipv6() end, fun() -> + ?TT(?SECS(45)), InitState = #{domain => inet6, proto => udp, msg => Msg, @@ -17850,12 +17867,12 @@ traffic_ping_pong_small_sendto_and_recvfrom_udpL(suite) -> traffic_ping_pong_small_sendto_and_recvfrom_udpL(doc) -> []; traffic_ping_pong_small_sendto_and_recvfrom_udpL(_Config) when is_list(_Config) -> - ?TT(?SECS(45)), Msg = l2b(?TPP_SMALL), Num = ?TPP_SMALL_NUM, tc_try(traffic_ping_pong_small_sendto_and_recvfrom_udpL, fun() -> has_support_unix_domain_socket() end, fun() -> + ?TT(?SECS(45)), InitState = #{domain => local, proto => default, msg => Msg, @@ -18079,7 +18096,7 @@ traffic_ping_pong_medium_sendmsg_and_recvmsg_tcp6(_Config) when is_list(_Config) tc_try(traffic_ping_pong_medium_sendmsg_and_recvmsg_tcp6, fun() -> has_support_ipv6() end, fun() -> - ?TT(?SECS(20)), + ?TT(?SECS(30)), InitState = #{domain => inet6, proto => tcp, msg => Msg, @@ -18107,7 +18124,7 @@ traffic_ping_pong_medium_sendmsg_and_recvmsg_tcpL(_Config) when is_list(_Config) tc_try(traffic_ping_pong_medium_sendmsg_and_recvmsg_tcpL, fun() -> has_support_unix_domain_socket() end, fun() -> - ?TT(?SECS(20)), + ?TT(?SECS(30)), InitState = #{domain => local, proto => default, msg => Msg, @@ -18135,7 +18152,7 @@ traffic_ping_pong_large_sendmsg_and_recvmsg_tcp4(_Config) when is_list(_Config) tc_try(traffic_ping_pong_large_sendmsg_and_recvmsg_tcp4, fun() -> traffic_ping_pong_large_sendmsg_and_recvmsg_cond() end, fun() -> - ?TT(?SECS(30)), + ?TT(?SECS(60)), InitState = #{domain => inet, proto => tcp, msg => Msg, @@ -18176,7 +18193,7 @@ traffic_ping_pong_large_sendmsg_and_recvmsg_tcp6(_Config) when is_list(_Config) traffic_ping_pong_large_sendmsg_and_recvmsg_cond() end, fun() -> - ?TT(?SECS(30)), + ?TT(?SECS(60)), InitState = #{domain => inet6, proto => tcp, msg => Msg, @@ -18205,7 +18222,7 @@ traffic_ping_pong_large_sendmsg_and_recvmsg_tcpL(_Config) when is_list(_Config) tc_try(traffic_ping_pong_large_sendmsg_and_recvmsg_tcpL, fun() -> has_support_unix_domain_socket() end, fun() -> - ?TT(?SECS(30)), + ?TT(?SECS(60)), InitState = #{domain => local, proto => default, msg => Msg, @@ -18261,7 +18278,7 @@ traffic_ping_pong_small_sendmsg_and_recvmsg_udp6(_Config) when is_list(_Config) tc_try(traffic_ping_pong_small_sendmsg_and_recvmsg_udp6, fun() -> has_support_ipv6() end, fun() -> - ?TT(?SECS(30)), + ?TT(?SECS(60)), InitState = #{domain => inet6, proto => udp, msg => Msg, @@ -18289,7 +18306,7 @@ traffic_ping_pong_small_sendmsg_and_recvmsg_udpL(_Config) when is_list(_Config) tc_try(traffic_ping_pong_small_sendmsg_and_recvmsg_udpL, fun() -> has_support_unix_domain_socket() end, fun() -> - ?TT(?SECS(30)), + ?TT(?SECS(60)), InitState = #{domain => local, proto => default, msg => Msg, @@ -18316,7 +18333,7 @@ traffic_ping_pong_medium_sendmsg_and_recvmsg_udp4(_Config) when is_list(_Config) Num = ?TPP_MEDIUM_NUM, tc_try(traffic_ping_pong_medium_sendmsg_and_recvmsg_udp4, fun() -> - ?TT(?SECS(30)), + ?TT(?SECS(60)), InitState = #{domain => inet, proto => udp, msg => Msg, @@ -18344,7 +18361,7 @@ traffic_ping_pong_medium_sendmsg_and_recvmsg_udp6(_Config) when is_list(_Config) tc_try(traffic_ping_pong_medium_sendmsg_and_recvmsg_udp6, fun() -> has_support_ipv6() end, fun() -> - ?TT(?SECS(20)), + ?TT(?SECS(60)), InitState = #{domain => inet6, proto => udp, msg => Msg, @@ -18373,7 +18390,7 @@ traffic_ping_pong_medium_sendmsg_and_recvmsg_udpL(_Config) when is_list(_Config) tc_try(traffic_ping_pong_medium_sendmsg_and_recvmsg_udpL, fun() -> has_support_unix_domain_socket() end, fun() -> - ?TT(?SECS(20)), + ?TT(?SECS(60)), InitState = #{domain => local, proto => default, msg => Msg, diff --git a/lib/kernel/test/interactive_shell_SUITE.erl b/lib/kernel/test/interactive_shell_SUITE.erl index 298a364a91..173e25c520 100644 --- a/lib/kernel/test/interactive_shell_SUITE.erl +++ b/lib/kernel/test/interactive_shell_SUITE.erl @@ -23,7 +23,8 @@ init_per_group/2,end_per_group/2, get_columns_and_rows/1, exit_initial/1, job_control_local/1, job_control_remote/1, - job_control_remote_noshell/1,ctrl_keys/1]). + job_control_remote_noshell/1,ctrl_keys/1, + get_columns_and_rows_escript/1]). -export([init_per_testcase/2, end_per_testcase/2]). %% For spawn @@ -40,7 +41,8 @@ suite() -> {timetrap,{minutes,3}}]. all() -> - [get_columns_and_rows, exit_initial, job_control_local, + [get_columns_and_rows_escript,get_columns_and_rows, + exit_initial, job_control_local, job_control_remote, job_control_remote_noshell, ctrl_keys]. @@ -72,6 +74,60 @@ end_per_group(_GroupName, Config) -> -define(dbg(Data),noop). -endif. +string_to_term(Str) -> + {ok,Tokens,_EndLine} = erl_scan:string(Str ++ "."), + {ok,AbsForm} = erl_parse:parse_exprs(Tokens), + {value,Value,_Bs} = erl_eval:exprs(AbsForm, erl_eval:new_bindings()), + Value. + +run_unbuffer_escript(Rows, Columns, EScript, NoTermStdIn, NoTermStdOut) -> + DataDir = filename:join(filename:dirname(code:which(?MODULE)), "interactive_shell_SUITE_data"), + TmpFile = filename:join(DataDir, "tmp"), + ok = file:write_file(TmpFile, <<>>), + CommandModifier = + case {NoTermStdIn, NoTermStdOut} of + {false, false} -> ""; + {true, false} -> io_lib:format(" < ~s", [TmpFile]); + {false, true} -> io_lib:format(" > ~s ; cat ~s", [TmpFile, TmpFile]); + {true, true} -> io_lib:format(" > ~s < ~s ; cat ~s", [TmpFile, TmpFile, TmpFile]) + end, + Command = io_lib:format("unbuffer -p bash -c \"stty rows ~p; stty columns ~p; escript ~s ~s\"", + [Rows, Columns, EScript, CommandModifier]), + %% io:format("Command: ~s ~n", [Command]), + Out = os:cmd(Command), + %% io:format("Out: ~p ~n", [Out]), + string_to_term(Out). + +get_columns_and_rows_escript(Config) when is_list(Config) -> + ExpectUnbufferInstalled = + try + "79" = string:trim(os:cmd("unbuffer -p bash -c \"stty columns 79 ; tput cols\"")), + true + catch + _:_ -> false + end, + case ExpectUnbufferInstalled of + false -> + {skip, + "The unbuffer tool (https://core.tcl-lang.org/expect/index) does not seem to be installed.~n" + "On Ubuntu/Debian: \"sudo apt-get install expect\""}; + true -> + DataDir = filename:join(filename:dirname(code:which(?MODULE)), "interactive_shell_SUITE_data"), + IoColumnsErl = filename:join(DataDir, "io_columns.erl"), + IoRowsErl = filename:join(DataDir, "io_rows.erl"), + [ + begin + {ok, 42} = run_unbuffer_escript(99, 42, IoColumnsErl, NoTermStdIn, NoTermStdOut), + {ok, 99} = run_unbuffer_escript(99, 42, IoRowsErl, NoTermStdIn, NoTermStdOut) + end + || + {NoTermStdIn, NoTermStdOut} <- [{false, false}, {true, false}, {false, true}] + ], + {error,enotsup} = run_unbuffer_escript(99, 42, IoRowsErl, true, true), + {error,enotsup} = run_unbuffer_escript(99, 42, IoColumnsErl, true, true), + ok + end. + %% Test that the shell can access columns and rows. get_columns_and_rows(Config) when is_list(Config) -> case proplists:get_value(default_shell,Config) of diff --git a/lib/kernel/test/interactive_shell_SUITE_data/.gitignore b/lib/kernel/test/interactive_shell_SUITE_data/.gitignore new file mode 100644 index 0000000000..1c2f433de1 --- /dev/null +++ b/lib/kernel/test/interactive_shell_SUITE_data/.gitignore @@ -0,0 +1 @@ +tmp
\ No newline at end of file diff --git a/lib/kernel/test/interactive_shell_SUITE_data/io_columns.erl b/lib/kernel/test/interactive_shell_SUITE_data/io_columns.erl new file mode 100644 index 0000000000..32d0cf25df --- /dev/null +++ b/lib/kernel/test/interactive_shell_SUITE_data/io_columns.erl @@ -0,0 +1,6 @@ +-module(io_columns). + +-export([main/1]). + +main(_) -> + io:format("~p",[io:columns()]). diff --git a/lib/kernel/test/interactive_shell_SUITE_data/io_rows.erl b/lib/kernel/test/interactive_shell_SUITE_data/io_rows.erl new file mode 100644 index 0000000000..53ceb464b0 --- /dev/null +++ b/lib/kernel/test/interactive_shell_SUITE_data/io_rows.erl @@ -0,0 +1,6 @@ +-module(io_rows). + +-export([main/1]). + +main(_) -> + io:format("~p",[io:rows()]). |