From c1b9be4a5d45869e8f3f93979782a14eab65fec3 Mon Sep 17 00:00:00 2001 From: Kjell Winblad Date: Thu, 20 Jun 2019 12:27:15 +0200 Subject: Fix io:columns() and io:rows() are not working from escripts bug The functions io:columns() and io:rows() only worked correctly inside interactive erlang shells before this fix. These functions returned {error,enotsup} before this fix even if stdout and stdin were connected to a terminal when they were invoked from an escript or a program started with e.g., `erl -noshell`. This commit fixes issue ERL-717. --- erts/emulator/sys/unix/sys_drivers.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) (limited to 'erts/emulator/sys') 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)); } -- cgit v1.2.3