2

I wrote a program that prints a message, awaits a user input and prints a message again. The simple example below illustrates that. The program is launched with 'prog | tr 'a-z' 'A-Z'. Only the last print should be handled by 'tr 'a-z' 'A-Z'.

int main ()
{
    char name[99];
    printf ("Your name: ");
    scanf ("%98s", name);
    printf ("Your name is: %s\n", name);

    return 0;
}

I 've tried a lot with pipe, dup, dup2, but nothing has worked so far. Has anyone an idea how to solve my problem?

jdarthenay
  • 3,062
  • 1
  • 15
  • 20

3 Answers3

1

If you want to launch your program with this command, the only way to do what you want would be to print messages in stderr:

fprintf (stderr, "Your name: \n");
jdarthenay
  • 3,062
  • 1
  • 15
  • 20
  • Thanks for your answer. I thought about stderr, but I hoped I can avoid the misuse of stderr. – Nick Bendner Apr 20 '16 at 17:43
  • @NickBendner Why you are trying to do "redirect the shell created pipe"? – jdarthenay Apr 20 '16 at 17:50
  • Under some circumstances my prog requests for an user input. Before that, it prints a message why it needs an input and what kind of input it expects. Everything works well unless the user starts the prog with a pipe. If the user does so, the message will not be printed, because stdout is buffered and redirected to the pipe. The user will only see a prompt, but he does not know why and what he shall do now. My idea was to suspend the pipe, print the message, get the users input and resume the pipe then. – Nick Bendner Apr 21 '16 at 17:55
  • @NickBendner Well, in that case, this is not a "misuse" of `stderr`. Showing messages to prompt the user without polluting program output is definitely a thing to done with `stderr`. – jdarthenay Apr 21 '16 at 18:03
0

After some researches, I have found how to check if stdout is directed to a terminal, and how to write to terminal even if have no handle to it.

So you could proceed as below:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>

int print_to_terminal(const char *message)
{
    FILE *termout;

    if (isatty(STDOUT_FILENO))
    {
        termout = stdout;
    }
    else
    {
        termout = fopen("/dev/tty", "w");
        if (termout == NULL)
        {
            perror("open");
            return EOF;
        }
    }

    int result = fprintf(termout, "%s\n", message);

    if (termout != stdout)
    {
        fclose(termout);
    }

    return result;
}

int main()
{
    printf("Start of program.\n");
    print_to_terminal("Don't worry, be happy.");
    printf("End of program.\n");

    return 0;
}

The message should be printed in current terminal even if both stdout and stderr are directed to a file.

Community
  • 1
  • 1
jdarthenay
  • 3,062
  • 1
  • 15
  • 20
0

Use tail: http://linux.die.net/man/1/tail

prog | tail -n 1 | tr 'a-z' 'A-Z'
  • Thanks for your answer, but the user decides how he starts the prog. The tr 'a-z' 'A-Z' was just an example in order to show that the prog does not work properly with a pipe. – Nick Bendner Apr 22 '16 at 19:18