2

everyone. I am still new to programming. I really need some help about the issues that I'm facing. So, the situation here is I'm trying to display a warning when the terminal size is below 80x24. For the record, my Os is Window, but I'm using a virtual machine to run Linux because all the files are in Linux. When i run the file using terminal, the warning display correctly. But the problem is when i try to run the file from Windows using PuTTY. The warning did not appear. I'm sure its because the function that I'm using can only read the Linux environment and not the Windows. Can anyone help me or point me to a direction on how to make it capable of getting the dimension of windows. The files should all remain in Linux. I am using C.

Here are just some part of the code to show about displaying warning and getting dimension.

//This is to display warning


int display_warning()
{
 CDKSCREEN *cdkscreen = 0;
 WINDOW *cursesWin    = 0;
 char *mesg[5];
 char *buttons[] = {"[ OK ]"};
 CDKDIALOG *confirm;

 cursesWin = initscr();
 cdkscreen = initCDKScreen (cursesWin);

 initCDKColor();

 mesg[0] = "</2>"The size of Window must be at least 80x24.";
 confirm = newCDKDialog(cdkscreen, CENTER, CENTER, mesg, 1, buttons, A_REVERSE, TRUE,TRUE, FALSE);
 setCDKDialogBackgroundColor(confirm, "</2>");
 injectCDKDialog(confirm,TAB);
 activateCDKDialog(confirm,0);

 if (confirm -> exitType == vNORMAL){
 destroyCDKDialog (confirm);
 destroyCDKScreen (cdkscreen);
 endCDK();
 }
 return 0;
}



//This is to get the dimension

int get_terminal_size()
{
 int cols;
 int lines;

 #ifdef TIOCGSIZE
 struct ttysize ts;
 ioctl(0,TIOCGSIZE, &ts);
 lines = ts.ts_linesl;
 cols = ts.ts_cols;

 #elif defined(TIOCGWINSZ)
 struct winsize ts;
 ioctl(0, TIOCGWINSZ, &ts);
 lines = ts.ws_row;
 cols = ts.ws_col;

 #endif

 if((lines <= 23)||(cols <= 79)){
 display_warning();
 }

 return 0;
}

//then there will be the main function that i think is not necessary to put the code here.

All comment and help are very appreciated. I am a beginner in programming, so please excuse me if there are some basic things that i dont know.

Fikrie

Mohd Fikrie
  • 197
  • 4
  • 21
  • 1
    If you are using curses to do that, I would have expected that to work. – trojanfoe Sep 13 '13 at 10:39
  • There seems to be a typo: `#ifdef TIOCFSIZE` instead of `#ifdef TIOCGSIZE`. Am I correct? Does that change anything? – firefrorefiddle Sep 13 '13 at 10:39
  • I'm sorry, that was my mistake when typing in here, the real code was TIOCGSIZE. thank you for telling me that. – Mohd Fikrie Sep 17 '13 at 01:54
  • @trojanfoe Yes. It does work when im running the file using terminal in Linux. I just doesn't work when i ran using PuTTY on Windows. – Mohd Fikrie Sep 17 '13 at 02:24
  • See also [Get size of terminal window (rows/columns)?](https://stackoverflow.com/q/23369503/15168) That question is more general than this, and the answers address both Linux (Unix) and Windows in C (or C++) code, and also in shell scripts. This question and its answers are focussed on Linux and C only. – Jonathan Leffler Jun 21 '23 at 21:59

1 Answers1

3

The issue has nothing to do with PuTTY per se, and everything to do with SSH clients and pseudoterminals in general.

To avoid this issue, configure your PuTTY to use a pseudoterminal. (In the TTY panel, there is a "Don't allocate a pseudoterminal" checkbox. Make sure it is not checked.)

With ssh, you need to use the -t option to tell ssh to use a pseudoterminal.

Here is a simple example program you can use in Linux to obtain the terminal size. It does not require curses:

#include <unistd.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <stdio.h>

static int get_size(const int fd, int *const rows, int *const cols)
{
    struct winsize sz;
    int            result;

    do {
        result = ioctl(fd, TIOCGWINSZ, &sz);
    } while (result == -1 && errno == EINTR);
    if (result == -1)
        return errno;

    if (rows)
        *rows = sz.ws_row;

    if (cols)
        *cols = sz.ws_col;

    return 0;
}

int main(void)
{
    int rows, cols;

    if (!get_size(STDIN_FILENO,  &rows, &cols) ||
        !get_size(STDOUT_FILENO, &rows, &cols) ||
        !get_size(STDERR_FILENO, &rows, &cols))
        printf("%d rows, %d columns\n", rows, cols);
    else
        fprintf(stderr, "Terminal size is unknown.\n");
    return 0;
}

The actual information is obtained using the TIOCGWINSZ TTY ioctl.

The pseudoterminal size is actually maintained by the kernel. If there is no pseudoterminal, just standard streams, there are no rows and columns; it's just a stream in that case. In particular, even tput lines and tput cols will fail then.

Many interactive command-line programs will refuse to work if there is no pseudoterminal. For example, top will report something like "TERM environment variable not set" or "top: failed tty get". Others will work, just not interactively; they'll output once only, but as if the terminal was infinitely tall and infinitely wide.

In summary, your application should recognize whether it is running in a pseudoterminal (with terminal size known, curses support possible, and so on), or in stream mode (via SSH or PuTTY, deliberately without a pseudoterminal -- or perhaps just because inputs and outputs are all directed to/from files or some such).

Nominal Animal
  • 38,216
  • 5
  • 59
  • 86
  • Hi, I have manage to solve the issue. The problem was actually from the PuTTY where i didn't do the setting properly. There are no problem with the coding. Thanks for all the guide and help. Really appreciate it!! – Mohd Fikrie Sep 17 '13 at 03:21