0

I have a real big problem with the function initscr().

#include <ncurses.h>
#include <stdlib.h>
#include <unistd.h>

int     main(int ac, char **av)
{
 WINDOW *win;

 initscr();
 printw("lol");
 getch();
 refresh();
 endwin();
 return (0);
}

When I compile this code and I execute ./a.out it's okay, but when I did

lol=`./a.out`

the initscr didn't appear. I read in the man about the function newterm but it was the same.

Jongware
  • 22,200
  • 8
  • 54
  • 100
Oscar
  • 1,071
  • 13
  • 26
  • Why would you like `./a.out` to work correctly with your terminal if you catch its output into a shell variable? – Jean-Baptiste Yunès Dec 03 '15 at 18:20
  • First thanks to the answer. I want to use them both... – Oscar Dec 03 '15 at 18:25
  • The output of a program that uses ncurses is intended to be written to a terminal (or emulator). It's not meant to be captured in a variable or written to a file. You *can* do that if you like, but then it's not going to the screen so it won't look right. – Keith Thompson Dec 03 '15 at 19:22
  • Okay but how its possible ? thanks – Oscar Dec 03 '15 at 19:42
  • How is *what* possible? Your question doesn't describe what you're trying to do. What do want to see when you execute the command, and what do you want/expect the variable `$lol` to contain after you execute it? Your only problem description is that "the `initscr` didn't appear", but frankly that doesn't make much sense. – Keith Thompson Dec 03 '15 at 19:57

3 Answers3

1

I have found the solution. I use newterm with stderr as output filedescriptor and it works.

int         main(int ac, char **av)
{
  SCREEN    *win;

  win = newterm(NULL, stderr, stdin);
  printw("lol");
  getch();
  refresh();
  endwin();
  return (0);
}
Ronan Boiteau
  • 9,608
  • 6
  • 34
  • 56
Oscar
  • 1,071
  • 13
  • 26
1

You can capture the output of any command on the terminal using the script utility, which is often installed by default. It saves all of the output of your program to a file named typescript, and does not interfere with the program. With Linux, you might run it as follows:

script -c ./a.out

(With other systems, such as OSX, you may not have the -c option: there is no POSIX standard for script).

However, you may find the results unexpected, since they would be mixed with escape sequences. For instance, running your program with TERM set to vt100, and showing non-printing characters in printable form using unmap, I see this:

Script started on Thu 03 Dec 2015 08:09:15 PM EST
\n
\E(B
\E)0
\E[1;40r
\E[m^O
\E[?7h
\E[H
\E[Jlol\r
\E[40;1H\r
\E[?1l
\E>
\nScript done on Thu 03 Dec 2015 08:09:16 PM EST
\n

Rather than try to separate the message from the escape sequences, some programs (such as dialog) intentionally write their messages on the standard error while using the standard output for screen updates. Or (using newterm) you can reverse that, making it simple to obtain a message.

Here is a revised program using that approach:

#include <ncurses.h>
#include <stdlib.h>
#include <unistd.h>

static void
show(const char *msg)
{
    printw("%s", msg);
    if (!isatty(fileno(stdout)))
    puts(msg);
}

int
main(int ac, char **av)
{
    newterm(NULL, stderr, stdin);
    show("lol");
    getch();
    endwin();
    return (0);
}

The revised program:

  • writes its message using a function show which writes to the screen and optionally writes the message
  • it checks if the standard output is not a tty using isatty, i.e., you are redirecting the program's output. Without the check, the two (output and error) would both be written to the screen, messing it up.
  • some minor cleanup was done: removing an unused variable, and an unnecessary call to refresh (since getch already did that).

This command

lol=`./a.out`

will do the requested assignment to lol without interfering with the screen updates.

Thomas Dickey
  • 51,086
  • 7
  • 70
  • 105
0

If you want to assign the output of a.out to a shell variable AND see the output in your terminal window, use tee (Here is an example). tee (shell program) effectively lets you duplicate the output of a process and send it to two places at once (in your case, a shell variable and your terminal).

Example (based on the solution given in the above link):

exec 5>&1
lol=$(./a.out | tee > (cat - >&5))
Community
  • 1
  • 1
Erik Nyquist
  • 1,267
  • 2
  • 12
  • 26
  • Thanks for the answer too but i'm not allowed to use the fcntl.h library. I have just to use open(), close(), write(), malloc(), free(), read(), exit(), signal(), ioctl() and all ncurses' functions... ;/ – Oscar Dec 03 '15 at 18:35
  • you misunderstand- the problem (or at least, the first one I see, and the one @Jean-Baptiste Yunès pointed out) is in the shell code you use to execute `a.out`, not in the C code. I'm talking about the shell program `tee`, not the system call in `fcntl.h`. Read the link I posted in the answer. – Erik Nyquist Dec 03 '15 at 18:40
  • @ErikNyquist : There's no link in your post, and some people (not me) will downvote an answer that points to an external source, rather than summarizing the relevant info in the answer's text. – shellter Dec 03 '15 at 18:42
  • OK, fair enough- I'll summarise and add a little example. There is a link, though- click on the word "Here" :) – Erik Nyquist Dec 03 '15 at 18:45
  • The link would give you the following commands `exec 5>&1; a=\`./a.out | tee >(cat - >& 5)\`` in bash. – Jean-Baptiste Yunès Dec 03 '15 at 18:46
  • I see what you're pointing at. The fact is I need to do it with a limited set of functions and librairies. One of this means is to get in the standard output some specific informations and store them. The thing is I need to first see the virtual screen, but it does'nt come up. Whereas when I execute the ./a.out it's showing up. – Oscar Dec 03 '15 at 18:52
  • are you saying that you are limited in both the C libraries and the shell programs that you can use? or are you only limited with C libraries? – Erik Nyquist Dec 03 '15 at 18:55
  • Yes, I'll be judged only on this limited set : open(), close(), write(), malloc(), free(), read(), exit(), signal(), ioctl() and all ncurses' functions. A sole : variable=\`.a.out\` should work. – Oscar Dec 03 '15 at 19:01
  • OK, that's a list of system calls, but again, are you limited in the shell programs (not C libraries or system calls) that you can use to execute your program? – Erik Nyquist Dec 03 '15 at 19:08
  • Yes i will be corrected by a machine called "moulinette" and it will execute some specifics commands. – Oscar Dec 03 '15 at 19:13
  • OK this is getting confusing. Can you post a snippet (the smallest snippet possible to show us what's required) of the text for the assignment? – Erik Nyquist Dec 03 '15 at 19:23
  • in fact i have to realize a program who list informations past with argv and return those which are selected (thanks to ncurses). I have some news, it's about the file descriptor who changed if we put the program between backquotes... – Oscar Dec 03 '15 at 19:30
  • that doesn't tell me anything. Please post the actual text that describes this. As in, copy-and-paste. – Erik Nyquist Dec 03 '15 at 19:51
  • Thanks for all, i found the solution <3 – Oscar Dec 03 '15 at 19:55