I am testing a method to simulate a specific input to an application.
This is the application:
#include <stdio.h>
int main()
{
int num1;
char buffer[6] = {0};
scanf("%d", &num1);
read(0, buffer, 6);
printf("num1 = %d\n", num1);
for(num1=0; num1 < 6; num1++)
{
printf("%02X\n", buffer[num1]);
}
return 0;
}
I am trying to simulate the input using the following bash command:
echo -ne "1337\\x0A\\x31\\x02\\x03\\x04\\x05\\x06" | ./test
The output I get is the following:
num1 = 1337
00
00
00
00
00
00
As you can see, the buffer was not filled with values passed to the STDIN.
EDIT:
The function below is only used to illustrate an idea of input automation in mixed i/o functions, I got this function by reverse engineering a binary file, is it possible to automate the input ?
I appreciate your help.
Thanks,
You are mixing scanf() (section 3 man page) and read() (section 2 man page). The scanf() series of functions perform buffered reads and writes. The section 2 read() is unbuffered. The bytes you are trying to read with read() have already been read and put into the buffer scanf() is using.
If you comment out your scanf() line, and change your command to
echo -ne "\\x0A\\x31\\x02\\x03\\x04\\x05\\x06" | ./test
you will get
num1 = 0
0A
31
02
03
04
05
So just use the buffered functions or the unbuffered functions. Pick one.
What's happening here?
echo is making a write with exactly as many characters you put in the command line (as you use -n flag it doesn't output a final \n char).
you are using scanf() on a pipe, so it makes a full buffer read first, and then scans the buffer for an integer. It does a n = read(0, buffer, BUFSIZ); returning 11 as the number of characters read to scanf and then scanf scans the buffer, returning 1337 as the number read and leaving all the characters past it into the buffer.
then you do a read(0, buffer, 6); that returns 0 and the buffer is not initialized with data.
then you print the previous, uninitialized buffer contents to stdout.
fifos (or pipes) behave quite different than terminals on input. The terminal driver just makes a read to complete when you push the enter key, making read to get the actual number of characters read by one input line. When you do this with a fifo, the reader process is blocked until enough characters (the actual number requested by read) is fed to the process and then that number (actually the requested number of characters) is returned by read.
If you had the precaution of checking the read(2) return value, you should get the actual number of read chars (that should be 0 as the scanf(3)
has eaten the complete buffer as it is smaller than BUFSIZ constant, in the first read)
Never mix stdio functions like scanf with low level io functions like read. Stdio maintains a buffer for efficiency and if any extra data is available when you call scanf it is likely going to read it to fill the buffer.
Use fread instead of read. Also, don't forget to check the return values of these functions.
Related
#include <stdio.h>
#define MAXLEN 256
int main() {
int n;
char buf[MAXLEN];
while((n = read(0,buf,sizeof(buf))) != 0){
printf("n: %d:",n);
write(1,buf,n);
}
return 1;
}
The output of the program (where the first read and first write is typed by the user and echoed by the terminal) is:
read
read
write
write
n: 5:n: 6:
The output of printf comes after pressing Ctrl+D at the standard input and not along with the subsequent reads. Why does this happen?
Printf is buffered.
You can force printf to 'flush' its buffer using the fflush call:
#include <stdio.h>
#define MAXLEN 256
int main() {
int n;
char buf[MAXLEN];
while((n = read(0,buf,sizeof(buf))) != 0){
printf("n: %d:",n);
fflush(stdout); /* force it to go out */
write(1,buf,n);
}
return 1;
}
In general, printf() being buffered is a good thing. Unbuffered output, particularly to visible consoles that require screen updates and such, is slow. Slow enough that an application that is printf'ing a lot can be directly slowed down by it (especially on the Windows platform; Linux and unixes are typically impacted less).
However, printf() being buffered does bite you if you also fprintf(stderr,) - stderr is deliberately unbuffered. As a consequence, you may get your messages with some printf() missing; if you write to another FILE handle that is also associated with the terminal, and might be unbuffered, make sure you first explicitly fflush(stdout).
The manpage for fgets tells me:
It is not advisable to mix calls to input functions from the stdio
library with low-level calls to read(2) for the file descriptor associ‐
ated with the input stream; the results will be undefined and very
probably not what you want.
So the best solution would be not to to use write and printf on the same descriptor.
Printf is using stdio and it is buffered.
Push it out by sending a changing to "n: %d:\n"
You can use the std fflush() function to flush the std out buffer or you can make use of an additional \n at the end of the control string inside the printf. Something like this
printf("\n :%d:\n",n);
Its always better to use the write() & read() functions in C instead of printf() and scanf(). Printf and scanf have got some problems like printf stores the string parameter in stdout buffer. So a manual flush is required which is done through fflush function or by means of \n. In a small hello world printing program you will not find such a problem as the stdout buffer is flushed at the end of the program execution. Better use write() which works fine. scanf also have the problem of reading spaces and a lot of other problems related to stdin buffer.
For example in the code below:
main() { char a; int i=0,c; for(;i<2;i++) { scanf("%d",&c); scanf("%c",&a);} }
The above program as got the problem of reading \n into stdin on pressing enter. We could resolve this but not flushing the stdin buffer or making use of \n character. Always better to use the read() and write() functions.
Hope that helps....
Use fwrite (streams version) rather than write.
Note that, while is associated with file number 1, it isn't the same thing.
I have the following C program:
#include<stdio.h>
main()
{
char buf[64];
gets(buf);
printf("Your input: %s\n", buf);
gets(buf);
printf("Your input: %s\n", buf);
}
I want to send data to the program using pipes or redirection. The problem is that the program don't wait for the second gets to enter new data.
e.g
$ echo "a" | ./test
Output:
Your input: a
Your input: a
How can I send let the program wait for the user input at each gets using pipes or redirection.
P.S I don't have persmission to write to /proc/$pid/fd/0 and I don't have to change the code.
Any help would be appreciated.
If you use pipes | to input data to a command, it is disconnected from the (input portion) of your terminal. gets reads the first line "a\n" and writes this to the buf as "a\0". Then it hits the end of the pipe, or EOF (end of file).
Your second gets then does nothing (as there is nothing to read after EOF) and lets buf alone; buf still contains "a\0", which is duly printed.
Further hints:
When doing I/O, which can inherently fail at any time, you have to check for errors after each and every call, or bad things will happen. Train yourself to do this and save lots of debugging time.
Never do an I/O like gets(buf) because it will lead to buffer overflows, the bane of computing security. If you input arbitrary data, you must use a call that lets you limit the number of bytes written. The man page for gets contains the sentence "Never use this function" right at the top. You can find other, better functions, read being a baseline, and if you are in C++ there will be plenty of other standard solutions for that.
We just started the topic of low level functions in C and for a part of this assignment we have to ask for user input. Normally I would use printf() and scanf() however for this assignment we are only allowed to use read(), write(), open(), close(), and lseek().
My question is how would you read input from the keyboard after printing to the screen?
I understand that I would have to use read, the file descriptor would be STDIN_FILENO, however how would I determine the size count? Also how would I keep track of what the user inputted? Would I have to create an char array just for that?
Also if anyone could reference some good reading material or tutorials for programming with low level functions that would help a lot.
Reading char by char would be bad for performance. System calls are kind of expensive. Most usually you want some kind of buffer (malloced, static memory, on the stack).
The size (once it's past certain size) doesn't really matter that much.
If your fd 0 is a terminal in cooked mode, you will get a line on each call to read (which will usually fail to fill your entire buffer). What's important to realize is that a read request for N bytes doesn't need to return N bytes and a return of less than N bytes doesn't need to mean an IO error. If it's a disk-based file, then your read request for the size of your buffer will tend to get fullfilled fully.
Advanced Programming in the Unix Environment by Richard Stevens is a good book on this.
Then of course, the man pages for the system calls.
Continuing from my earlier comment, there is really little difference between reading and writing to stdin using read and write and using higher level functions like fgets and printf. The primary difference is you cannot rely on the format string provided by the variadic printf, and with read, you are responsible for making use of the return to know how many characters were actually read.
Below is a short example showing the basics of reading input from stdin with read and then writing that information back with write (note: there are additional checks you should add like checking that the number of characters read is less than the size of the buffer to know if more characters remain to be read, etc...) You can always put much of the prompt and read into a function to ease repetitive use.
With write, just remember, the order you write things to stdout is the format string. So simply make logical calls to write to accomplish the formatting you desire. While you are free to use the STDIN_FILENO defines, you can also simply use 0 - stdin, 1 - stdout and 2 - stderr:
#include <unistd.h>
#define MAXC 256
int main (void) {
char buf[MAXC] = {0};
ssize_t nchr = 0;
/* write the prompt to stdout requesting input */
write (1, "\n enter text : ", sizeof ("\n enter text : "));
/* read up to MAXC characters from stdin */
if ((nchr = read (0, buf, MAXC)) == -1) {
write (2, "error: read failure.\n", sizeof ("error: read failure.\n"));
return 1;
}
/* test if additional characters remain unread in stdin */
if (nchr == MAXC && buf[nchr - 1] != '\n')
write (2, "warning: additional chars remain unread.\n",
sizeof ("warning: additional chars remain unread.\n"));
/* write the contents of buf to stdout */
write (1, "\n text entered: ", sizeof ("\n text entered: "));
write (1, buf, nchr-1);
write (1, "\n\n", sizeof ("\n\n"));
return 0;
}
Compile
gcc -Wall -Wextra -o bin/read_write_stdin read_write_stdin.c
Output
$ ./bin/read_write_stdin
enter text : The quick brown fox jumps over the lazy dog!
text entered: The quick brown fox jumps over the lazy dog!
My program has to read just ONE character from the standard input, and so I use read(0, buffer, 1).
But if the user insert more than one single character, they remain in some buffer and when I call a read again they are still there.
So, how can I discard these characters?
I want that when I call a read again, the buffer is filled with the new character, not with the old ones.
An example:
I've a read(0, buffer, 1) and the user writes abcde. My buffer contains a (and it's right), but then I call read(0, buffer, 1) again and I want the next character written by the user from now, and not the b written before.
The POSIX answer is tcflush(): flush non-transmitted output data, non-read input data, or both. There is also tcdrain() which waits for output to be transmitted. They've been in POSIX since there was a POSIX standard (1988 for the trial-use version), though I don't recall ever using them directly.
Example program
Compile this code so the resulting program is called tcflush:
#include <stdio.h>
#include <unistd.h>
#include <termios.h>
int main(void)
{
char buffer[20] = "";
read(0, buffer, 1);
printf("%c\n", buffer[0]);
tcflush(0, TCIFLUSH);
read(0, buffer, 1);
printf("%c\n", buffer[0]);
tcflush(0, TCIFLUSH);
return 0;
}
Example dialog
$ ./tcflush
abc
a
def
d
$
Looks like what the doctor ordered. Without the second tcflush(), the shell complains that it can't find a command ef. You can place a tcflush() before the first read if you like. It wasn't necessary for my simple testing, but if I'd used sleep 10; ./tcflush and then typed ahead, it would make a difference.
Tested on RHEL 5 Linux on an x86/64 machine, and also on Mac OS X 10.7.4.
When your program wants to start reading characters, it must drain the buffer of existing characters and then wait to read the character.
Otherwise, it will read the last character entered, not the last character entered after right now.
Naturally, you do not need to do anything with the read characters; but, you do need to read them.
#include <stdio.h>
#define MAXLEN 256
int main() {
int n;
char buf[MAXLEN];
while((n = read(0,buf,sizeof(buf))) != 0){
printf("n: %d:",n);
write(1,buf,n);
}
return 1;
}
The output of the program (where the first read and first write is typed by the user and echoed by the terminal) is:
read
read
write
write
n: 5:n: 6:
The output of printf comes after pressing Ctrl+D at the standard input and not along with the subsequent reads. Why does this happen?
Printf is buffered.
You can force printf to 'flush' its buffer using the fflush call:
#include <stdio.h>
#define MAXLEN 256
int main() {
int n;
char buf[MAXLEN];
while((n = read(0,buf,sizeof(buf))) != 0){
printf("n: %d:",n);
fflush(stdout); /* force it to go out */
write(1,buf,n);
}
return 1;
}
In general, printf() being buffered is a good thing. Unbuffered output, particularly to visible consoles that require screen updates and such, is slow. Slow enough that an application that is printf'ing a lot can be directly slowed down by it (especially on the Windows platform; Linux and unixes are typically impacted less).
However, printf() being buffered does bite you if you also fprintf(stderr,) - stderr is deliberately unbuffered. As a consequence, you may get your messages with some printf() missing; if you write to another FILE handle that is also associated with the terminal, and might be unbuffered, make sure you first explicitly fflush(stdout).
The manpage for fgets tells me:
It is not advisable to mix calls to input functions from the stdio
library with low-level calls to read(2) for the file descriptor associ‐
ated with the input stream; the results will be undefined and very
probably not what you want.
So the best solution would be not to to use write and printf on the same descriptor.
Printf is using stdio and it is buffered.
Push it out by sending a changing to "n: %d:\n"
You can use the std fflush() function to flush the std out buffer or you can make use of an additional \n at the end of the control string inside the printf. Something like this
printf("\n :%d:\n",n);
Its always better to use the write() & read() functions in C instead of printf() and scanf(). Printf and scanf have got some problems like printf stores the string parameter in stdout buffer. So a manual flush is required which is done through fflush function or by means of \n. In a small hello world printing program you will not find such a problem as the stdout buffer is flushed at the end of the program execution. Better use write() which works fine. scanf also have the problem of reading spaces and a lot of other problems related to stdin buffer.
For example in the code below:
main() { char a; int i=0,c; for(;i<2;i++) { scanf("%d",&c); scanf("%c",&a);} }
The above program as got the problem of reading \n into stdin on pressing enter. We could resolve this but not flushing the stdin buffer or making use of \n character. Always better to use the read() and write() functions.
Hope that helps....
Use fwrite (streams version) rather than write.
Note that, while is associated with file number 1, it isn't the same thing.