Thread: How to manipulate keyboard input in console

  1. #1
    Registered User
    Join Date
    Jul 2011
    Posts
    7

    How to manipulate keyboard input in console

    I'm making a C program that works as a bot on a text-mode web browser. The program navigates on web pages and reads stuff from them.

    Since making a set of pipes for both reading and writing to and from the browser which my program calls, seems a bit challenging for me, I've come to the conclusion that one handy way of making this work is to, according to desired keys to be pressed, put stuff into stdin. In other words: I want to manipulate keyboard input without actually having to press the keys on the keyboard.

    How do I do this?

    I understand this may be quite dependent on the platform. However, I don't intend to distribute my program. I'm an Ubuntu user.



    So to make the story easier, I want to have a function like the following example:

    press_key(56);

    where 56 would be either ascii or keycode. The program wouldn't know if it's me pressing a certain key on the keyboard or if I called the press_key function instead.
    Last edited by apawamajawa; 07-17-2011 at 06:09 AM. Reason: Text was messed up

  2. #2
    Unregistered User Yarin's Avatar
    Join Date
    Jul 2007
    Posts
    2,158
    The fact that the program you want to send key presses to is text based, actually makes this a lot easier...
    Write a launching program, that creates an IPC conduit, (you can use pipe(), or even a file socket), then replace your program's stdin, with the recieving descriptor of your IPC, then exec() your target application. Your target application will now be running with it's input (stdin) fully at your control.
    From there, sending input is as easy as write()ing to the sending descriptor of your IPC.

  3. #3
    Registered User
    Join Date
    Jul 2011
    Posts
    7
    Thank you for your answer! This sounds easy and makes a lot of sense Even though I've done C programming for many years, I'm really new to the pipes. I would also appreciate it, if I could get a simple example code of just a few lines, which shows how to do this.


    "then replace your program's stdin":

    Should I use freopen here or something else?



    Right now I have something like:

    Code:
    handle=popen("browser","r");
    
    //initialize key sending connection to "browser"
    //how?
    
    while(...){
    
    //send keys to "browser":
    // write(..., string_of_keys, size);
    
    while(fgets(string,100,handle)){
       // do something with the string received from "browser"
    }
    
    }
    
    pclose(handle);




    I'd also like to mention, that I've grabbed one example code from the internet, which does fork(); and execl(...); and then just uses printf(...); to send keys to the program. I've been able to freopen(...); stdout so that I can receive data from the executed program. However, this prevents me from printf()'ing to the console because it all goes to the executed program. I haven't been able to solve this problem. This is why I've figured it would be the easiest if I can popen(...); the browser in mode "r" and then somehow send the keys to it. Since this subject is new to me, I appreciate all help a lot.
    Last edited by apawamajawa; 07-17-2011 at 01:23 PM. Reason: addition

  4. #4
    Registered User
    Join Date
    Jan 2010
    Posts
    412
    Quote Originally Posted by apawamajawa View Post
    I've been able to freopen(...); stdout so that I can receive data from the executed program. However, this prevents me from printf()'ing to the console because it all goes to the executed program. I haven't been able to solve this problem.
    Have you tried fprintf'ing to stderr? I think that should work for console output.

  5. #5
    Registered User
    Join Date
    Jul 2011
    Posts
    7
    Quote Originally Posted by _Mike View Post
    Have you tried fprintf'ing to stderr? I think that should work for console output.
    Great! Thank you! The sample code I edited even does this already and I didn't get it. So now there's at least one way to do the two-way communication.

  6. #6
    Unregistered User Yarin's Avatar
    Join Date
    Jul 2007
    Posts
    2,158
    Quote Originally Posted by apawamajawa View Post
    I'm really new to the pipes. I would also appreciate it, if I could get a simple example code of just a few lines, which shows how to do this.
    Alright, there are actually a few ways of doing this. I'll just give you some pseudo-code to get you started, since I don't actually have anything that does this lying around.
    Code:
    mkfifo(pipe_name, ...);
    
    int id = fork();
    if(id)
    {
    int fd = open(pipe_name, O_RDONLY);
    close(STDIN);
    dup2(fd, STDIN);
    execv(...);
    }
    
    sleep(1); // wait for the sibling to open the FIFO
    
    int fd = open(pipe_name, O_WRONLY);
    write(fd, "Key press string here\n", ...); // this sends input to the sibling (which should now be your browser), and it doesn't know the difference
    Of course, you'll need to do some error checking, fill in the blanks, etc.. But otherwise this should get you started.
    Quote Originally Posted by apawamajawa View Post
    "then replace your program's stdin":

    Should I use freopen here or something else?
    I suppose you could. Though, I had a FIFO in mind. See my example above.
    Last edited by Yarin; 07-17-2011 at 03:16 PM.

  7. #7
    Registered User
    Join Date
    Jul 2011
    Posts
    7
    Wonderful! Thank you very much for your help!


    Another question concerning this project:

    I use execl(...); to launch the text-mode browser. Is there a way that I can tell the system what size the terminal window is? According to the output, which I have directed away from stdout, the browser thinks it works in a very small window. It is not the window size I'm running the program in.

  8. #8
    Unregistered User Yarin's Avatar
    Join Date
    Jul 2007
    Posts
    2,158
    Most likely, the browser is doing it's stuff through curses/ncurses, which probably gets that info via TIOCGWINSZ ioctl() (or something like it).
    I don't how you would (cleanly) handling ioctl()s and the likes for your descriptor - except for using a character/block device instead of a FIFO, but that's a bit harder to do than your initial question.
    Maybe someone else will know. In that case you might want to post a new thread asking this question.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. keyboard input
    By KOFI in forum C Programming
    Replies: 2
    Last Post: 04-06-2010, 12:20 PM
  2. Keyboard input
    By Darkinyuasha1 in forum Windows Programming
    Replies: 7
    Last Post: 06-19-2007, 03:21 PM
  3. Need help with Console Keyboard Input
    By pawelx2 in forum Game Programming
    Replies: 5
    Last Post: 05-30-2002, 11:03 PM
  4. FAQ Keyboard Input ? (C++)
    By Malikive in forum FAQ Board
    Replies: 6
    Last Post: 11-07-2001, 09:30 PM
  5. Keyboard input ?
    By Malikive in forum Game Programming
    Replies: 4
    Last Post: 11-06-2001, 11:14 PM