Call to fgets results in string printing to stdout - c

void deleteFile( FAT *allotable ) {
/* PRECONDITION: This function expects a FAT structure that is valid.
* POSTCONDITION: A file is flagged as removed from the disk and it will
* be possible to write over it
*/
// Local variables
unsigned char test[9] = { 0 };
// Select file to remove
// TODO: The user will select the file to remove based on the
// listing in listDir
// For testing, we are removing file at location 0 in the entry
fgets( test, NAME_SIZE, stdin );
return;
}
When I run the function and type in a string, I see the string printed back in stdout. I am sure I have an issue with a buffer, but I can't seem to figure this out.

When you run it if you see:
./program
input<CR>
input
<prompt>
Then the code you provided was not responsible for doing that. Use some debug statements or a debugger to figure out where that echo is coming from, because that isn't what fgets does.
If you are seeing:
./program
input<CR>
<prompt>
Then that is just how terminals work. They will echo back the text as you type unless you disable that feature (useful for entering passwords).

When you type characters into the console, they are echoed back to you. The characters will still be read when you read from stdin.
Alternatively you can pipe the output of a program into your own, or redirect a file to stdin. In those two cases, the characters will not be echoed:
echo Program output | ./myprog
or:
./myprog < fileinput.txt
edit - Sounds like it's a terminal problem.
You haven't stated what system you are using or how you are interfacing with it, but I can get this behaviour by connecting to a system via SSH with PuTTY.
I change the terminal settings to force on both "Local echo" and "Local line editing". Then I get the line echoed whenever I press enter. Obviously only one of those should be on. Preferably "Local echo".

A common cause of this is having echoing enabled in both your terminal (presumably an emulator these days) and in the OS terminal driver. Assuming you're using Unix, does the problem go away if you do:
stty -echo
before running your program?

Related

Reprinting input to terminal in C

i am writing a terminal chat and would like to reprint the content the user has typed in, if a new message from another user has arrived asynchronously.
if a new message arrives i print "\x1B[2K" to stdout (ANSI ESCAPE CODE for erasing the current line) to clear the current line, then i print "\r" to move the cursor to the leftmost position, then i print the received message with a newline
now i would like to reprint the characters the user has typed - i found out that there is a special character VREPRINT (http://www.gnu.org/software/libc/manual/html_node/Editing-Characters.html) that can be used and if a hit CTRL-R it actually works... but if print the character to stdout using the character placed in c_cc[VREPRINT] of a struct termios, it does not work - is it even possible to do it that way?
I do not want to use any other libraries like readline or ncurses, since this would be plain overkill... i just would like to make my solution work using ICANON terminal mode if possible
Thanks in advance!
While it is possible to write to the same tty device that you are reading from, this doesn't mean that the characters that appear will be processed as input characters.
You can test this yourself, using two separate shell sessions (using screen, tmux, or, if you are on MacOSX, iTERM.app sessions).
in Session 1, get the current tty name:
tty
Let's assume the tty name of Session 1 is /dev/ttys000.
Then enter the following, without a return or newline -- just leave it pending:
echo abc def-
In Session 2 (using the tty name from Session 1), enter the following command:
echo foo >/dev/ttys000
The string foo should appear on the pending line in Session 1, like this:
echo abc def-foo
Now, go back to Session 1, and hit an "enter" (or return), causing the input buffer to be completed and sent to the shell, which will parse the first word as the echo command, with the subsequent arguments as text to be printed.
You should see the string "abc def-" echoed -- but not the foo.
This test makes it clear that the string foo was never placed into the input buffer, even though it was sent to the same tty being used for input (and output).
You can try to see if special control characters are recognized and processed; but they won't be. These characters are only being output to the terminal, but not processed.
In order for the special characters to be processed, they have to be received via the socket connected to the input device.
To accomplish what you are trying to do, you'll have to go non-canonical (stty -icanon) and process every character in your code, in order to collect the pending input and also be able to produce asynchronous output.
Alternatively, using nurses is not hard at all, and if you are writing a terminal-based chat program, I would suggest creating at least two panels: a "chat" panel for all output, and an "input" panel for user input. This allows output from other users, as well as the completed commands from the "input" panel, to be received and written to the "chat" panel asynchronously without disturbing the current command in progress by the user in the "input" panel.

How to interrupt standard input stream for another

This problem maybe a little bit hard to state. For example, a program receive a string from stdin, but it need a interactive input from user, like this:
echo "Some text to handle later after command is specified" | a.out
And in the beginning of the program:
printf("Please input command first");
scanf("%s", &cmd);
/* Some Code Here */
/* process "Some text to handle later after command is specified" */
Is there a way to "suspend" previous input stream and wait for the scanf's ones?
The standard does not specify any way to get interactive user input besides reading from stdin. Since your stdin is occupied with a pipe, you need to tread an implementation-specific path.
For Unix-like systems that would be a special file named /dev/tty. fopen it and use normal stdio functions.
On Windows you probably need to call Console API.
Threre's no guarantee a program is attached to any interactive device, so prepare to fail.
Note that it's considered bad style to write programs this way. If there's any user input expected, a well-witten program should just use stdin. All other input streams should then be passed as filenames via command-line arguments.
When using pipes, the shell sets up the programs stdin to be from the output of the previous command. So reading should not be a problem.
The problem here is that you should not print any output if the input is from a pipe (or redirection). This can be done by checking the result of the isatty function:
if (isatty(fileno(stdin)))
{
/* Only print prompt if input is an interactive terminal */
printf(...);
}
scanf(...);
Or am I misreading you, in that you want to read both from the user, and from the pipe? Then you probably have to open a direct connection to the terminal.
For this you could use ttyname to get the name of the TTY device of stdout and open that device for input to read the user input. That won't work if the stdout is leading to a pipe (or is being redirected) as well.

Checking if a file via stdin exists (C)

I'm having difficulty writing a function in C that checks whether a user inputed file (via stdin) exists. For instance if the program is run as ./a.out <myfile.txt, I want it to return false if this file does not exist. I can do this by passing the file as an argument (i.e ./a.out myfile.txt)using fopen(), but not sure how to do this using 'stdin' (i.e ./a.out <myfile.txt)
Ok to clarify:
The larger program is supposed to take the contents of a text file and perform actions on it. The program must be run in the command line as ./a.out arg1 arg2 <myfile.txt. If user ran the program as ./a.out arg1 arg2 or ./a.out (i.e not specifying the file to perform actions on), I want to prompt the user to include a file (using stdin <, not passed as an argument).
Stdin might not be coming from a file at all. Even if it is, when the user types "< myfile.txt" at the command line, the shell swallows that part of the command, and never passes it to the program. As far as the program is concerned, it's an anonymous stream of bytes that might be from a file, a device, a terminal, a pipe, or something else. It is possible to query which of these you have, but even if you know it's a file you won't get the name of the file given on the command line, only an inode.
Since the shell is responsible for opening the file for redirection, it will refuse to execute the command if the file doesn't open.
Input redirection is something done by the shell, not your program. It simply attaches the file to standard input.
Hence, if you try to redirect input from a non-existent file, the shell should complain bitterly and not even run your program, as shown in the following transcript:
pax> echo hello >qq.in
pax> cat <qq.in
hello
pax> cat <nosuchfile.txt
bash: nosuchfile.txt: No such file or directory
In any case, your program generally doesn't know where the input is coming from, since you can do something like:
echo hello | cat
in which no file is involved.
If you want your program to detect the existence of a file, it will have to open the file itself, meaning you should probably give the filename as an argument rather than using standard input.
Or, you could detect the file existence before running your program, with something like the following bash segment:
fspec=/tmp/infile
if [[ -f ${fspec} ]] ; then
my_prog <${fspec}
else
echo What the ...
fi
The OS prevent calling your program since it can provide a valid stdin if myfile.txt does not exists. You program will not run thus there is no way you can signal the file is missing, and this diagnostics is done at the OS level.
If user ran the program as ./a.out arg1 arg2 or ./a.out (i.e not specifying the file to perform actions on), I want to prompt the user to include a file (using stdin <, not passed as an argument).
You could use OS-specific functions to check whether stdin is terminal. Checking whether it's file is a very bad idea, because it's very useful to pipe into stdin ... in fact, that's a major reason that there is such a thing as stdin in the first place. If you only want to read from a file, not a terminal or pipe, then you should take the file name as a required argument and not read from the orginal stdin (you can still read from stdin by using freopen). If you insist that you don't want to do it that way, then I will insist that you want to do it wrong.

Question about K&R - redirect input

In section 1.6 of 'The C Programming Language' (K&R) there is an example program and the authors state:
The output of this program ON ITSELF is
digits = 9 3 0 0 0 0 0 0 0 1, white space = 123, other = 345
Then there are many similar programs etc. including exercises. I understand everything about the logic of the code and can do the exercises, but how do I actually test my program on a file like the authors or many others on the web?
Edit: The question should be: How can I redirect the input of a file to the program?
The program in chapter 1.6 reads input from stdin. To make it read from a file, you can (on most operating systems) redirect stdin to be a file by running your program like this:
myprogram < somefile
Or you can pipe the content of a file to it like so:
cat somefile | myprogram
On windows, you'd use the type program instead of cat,
type somefile | myprogram
This is using re-direction. Instead of the input to the program coming from the keyboard it comes from a file.
At the DOS prompt:-
C:>myexe < filename
Get to the DOS prompt in Windows use the command shell. Or start Run.. and enter cmd
On a Mac this is called terminal (type "terminal" into Searchlight to get to it).
By default, your program will take input from stdin, which is a buffer which is filled based on input from your keyboard (by default). However, you can also tell your program to fill stdin from a text file instead.
Using a *nix based system, you can simply create a text file, and save it as whatever you'd like, "test_input" for instance. Fill it with the input that you'd like to pass to your program, save it, and then run your program like this:
./a.out < test_input
This is called redirection because you are "redirecting" (if you will) the input to come from a file, rather than the default (keyboard). It goes both ways, you can also redirect your output to a file, rather than stdout with the other angle bracket, '>'.
Using Visual Studio, and not popping open a command prompt to do something like the command above, you can use a C++ ifstream, put the text file in the local directory, and then simply use the ifstream everywhere instead of stdin:
ifstream sin("test_input.txt" , ifstream::in);
int value;
sin >> value;
You can output to a file using an ofstream.
Note that ifstreams and ofstreams are C++ objects, and can't be used in C. While you can write to files and read from files in C, it's a little trickier than simply replacing all instances of cout and cin. You actually have to think about what you are reading and writing :)

Returning the terminal cursor to start-of-line with wrapping enabled

I'm writing a filter (in a pipe destined for a terminal output) that sometimes needs to "overwrite" a line that has just occurred. It works by passing stdin to stdout character-by-character until a \n is reached, and then invoking special behaviour. My problem regards how to return to the beginning of the line.
The first thing I thought of was using a \r or the ANSI sequence \033[1G. However, if the line was long enough to have wrapped on the terminal (and hence caused it to scroll), these will only move the cursor back to the current physical line.
My second idea was to track the length of the line (number of characters passed since previous \n), and then echo \b that many times. However, that goes wrong if the line contained control characters or escape sequences (and possibly Unicode?).
Short of searching for all special sequences and using this to adjust my character count, is there a simple way to achieve this?
Even if there were a "magic sequence" that when written to a console would reliably erase the last written line, you would STILL get the line and the sequence on the output (though hidden on a console). Think what would happen if somebody wrote the output to a file, or passed it down the pipe to other filters? Would they know how to handle such input? And don't tell me you rule out the possibility of writing somewhere else than directly to a console. Sooner or later, somebody WILL want to redirect the output - maybe even you!
The Right Way to do this is to buffer each line in memory as it is processed, and then decide whether to output it or not. There's really no way around this.
$ cat >test.sh <<'EOF'
> #!/bin/sh
> tput sc
> echo 'Here is a really long multi-line string: .............................................................................................'
> tput rc
> echo 'I went back and overwrote some stuff!!!!'
> echo
> EOF
$ sh test.sh
I went back and overwrote some stuff!!!! .......................................
......................................................
Look for the save_cursor and restore_cursor string capabilities in the terminfo database.
You can query terminal dimensions with a simple ioctl:
#include <sys/types.h>
#include <sys/ioctl.h>
// ...
struct winsize ws;
ioctl(1, TIOCGWINSZ, &ws);
// ws.ws_col, ws.ws_row should now contain terminal dimensions
This way you can prevent printing anything beyond the end of line and simply use the \r method.

Resources