LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Sending data to a command using C (https://www.linuxquestions.org/questions/programming-9/sending-data-to-a-command-using-c-562986/)

gregorian 06-19-2007 12:00 PM

Sending data to a command using C
 
For example, when you enter su at the terminal, you get a prompt that asks you for the password. I want to know how to 'write' the password to that prompt and 'press' enter.

I know that system("su") will start the su command and give you the prompt, but how do I actually 'type' the password using a program?

PatrickNew 06-19-2007 12:25 PM

you want popen(char*, char*). Actually, one or both of those char*'s may be const. Anyhow, it opens a pipe to the given process, and works like fopen. It would be called like so
Code:

FILE* pipe = popen("su", "w")
The second argument can be "r" for reading or "w" for writing. The first will be the command you want to execute. Be aware though, I don't think running su through a pipe will quite do what you want it to.

gregorian 06-19-2007 12:55 PM

Quote:

su: must be run from a terminal
Yes, :D

How does su distinguish b/w me and the program? Does it check if the input is from stdin?

PatrickNew 06-19-2007 01:11 PM

you can still run it from a program by using a pseudo-terminal (pty), but I don't think this is what you want. Correct me if I'm wrong, but it seems that you want to enter a password in your program that would give you the privileges of another user? By running su in a pty, you could try to run other commands as root, but not gain root status for your own program.

gregorian 06-19-2007 01:20 PM

Code:

foo@foo:/mnt/D/Programs/C$ touch a.g b.g c.g d.g e.g f.g
foo@foo:/mnt/D/Programs/C$ rm -i *.g
rm: remove regular empty file `a.g'? y
rm: remove regular empty file `b.g'? y
rm: remove regular empty file `c.g'? y
rm: remove regular empty file `d.g'? y
rm: remove regular empty file `e.g'? y
rm: remove regular empty file `f.g'? y
foo@foo:/mnt/D/Programs/C$ touch a.g b.g c.g d.g e.g f.g
foo@foo:/mnt/D/Programs/C$ cat pipe.c
#include <stdio.h>

main()
{
  FILE *pipe;
  pipe = popen("rm -i *.g","w");
 
  fputs("y",pipe);
 

  pclose(pipe);
}
foo@foo:/mnt/D/Programs/C$ ./a.out
foo@foo:/mnt/D/Programs/C$ ls *.g
ls: *.g: No such file or directory

Why does the letter 'y' go to the terminal six times? Shouldn't it have only deleted a.g ?

EDIT: I simply want to learn more C. I'm not putting this in any other program.. just curious!

PatrickNew 06-19-2007 01:28 PM

hrm... beats me

chrism01 06-20-2007 06:38 AM

I think you've basically implemented the following
echo "y"|rm *.g
which works, as in deletes all *.g files (although in bash I do get a 'bash: echo: write error: Broken pipe' error after it's finished.)

gregorian 06-20-2007 08:16 AM

No, it doesn't. It only deletes the first file as expected. To the others, it sends the Enter key( I think, because normally after entering 'y', you are required to press Enter. Since I sent only one 'y', it 'pressed' enter till the command was completed) I'm using bash.
Code:

foo@foo:~$ touch a.g b.g c.g d.g
foo@foo:~$ echo y|rm -i *.g
rm: remove regular empty file `a.g'? rm: remove regular empty file `b.g'? rm: remove regular empty file `c.g'? rm: remove regular empty file `d.g'?
foo@foo:~$ ls *.g
b.g  c.g  d.g
foo@foo:~$

EDIT: I think you want to execute: echo "y"|rm -i *.g

gregorian 06-21-2007 02:14 AM

Anyone knows why this happens?

gregorian 06-25-2007 07:17 AM

Please tell me, I've waited for a very long time. Is it something very small?

PatrickNew 06-25-2007 01:59 PM

My guess is the pclose(). Since the command exists only on the other end of that pipe, it is terminated after the first 'y' is sent. Thus, only the first file is removed. Regarding the
Code:

echo "y" | rm *.g
why not just
Code:

rm -f *.g

PatrickNew 06-25-2007 02:02 PM

Ooops, I've misunderstood the question. All of them were deleted, but only the first should have been. I still suspect the pclose though. It is generally not a good idea to close the pipe to such a program before it terminates, as you can get undefined results, like this. In fact, if you moved to a system with, for instance, the busybox rm the result may be different.

gregorian 06-26-2007 03:53 AM

Ok, is there an alternative way to code this?

P.S. It's rm -i that is to be used, not rm. Only rm will not give any confirmation, and will delete every file.

gregorian 06-26-2007 12:51 PM

I figured it out. I forgot to simulate the Enter key.

Code:

foo@foo:~/Programs/C$ touch a.g b.g c.g
foo@foo:~/Programs/C$ cat pipe.c
#include <stdio.h>

main()
{
  FILE *pipe;
  pipe = popen("rm -i *.g ","w"); /*Delete with prompting*/
 
  fputc('y',pipe);
  fputc(10,pipe); /*Ascii code for the Enter key*/
 
 
  pclose(pipe);
}
foo@foo:~/Programs/C$ gcc pipe.c
foo@foo:~/Programs/C$ ./a.out
rm: remove regular empty file `a.g'? rm: remove regular empty file `b.g'? rm: remove regular empty file `c.g'?
foo@foo:~/Programs/C$ ls *.g
b.g  c.g
foo@foo:~/Programs/C$


chrism01 06-26-2007 06:53 PM

It's the -i switch effect that I was dealing with as per gregorian's last comment.
The same technique can be used with other cmds that prompt for confirmation (install scripts for eg).


All times are GMT -5. The time now is 06:57 PM.