Thread: How to shadow user input (as 'su' does for example)

  1. #1
    Registered User
    Join Date
    Dec 2006
    Posts
    15

    How to shadow user input (as 'su' does for example)

    Hi,

    I am writing a small program ( still quite new to this), and i need to hide the input that the user enters (as su does for example, you cant see what you are typing). How can i do this?

  2. #2
    Lean Mean Coding Machine KONI's Avatar
    Join Date
    Mar 2007
    Location
    Luxembourg, Europe
    Posts
    444
    You might want to have a look at this thread, it basically explains everything you want to do.

  3. #3
    Registered User
    Join Date
    Dec 2006
    Posts
    15
    Hi,

    Thanks for the reply, but its not quite working yet.

    I now have the following code:
    Code:
    #include <stdlib.h>
    #include <curses.h>
    #include <stdio.h>
    
    void passgets(char pword[], int maxlength)
    {
            int counter = 0;
            char ch;
            while( (ch = getch() ) != '\r' && counter < maxlength-1 )
            {
                    if(ch == '\b' && counter > 0)
                    {
                            printf("\b \b");
                            counter--;
                    }
                    else
                    {
                            pword[counter++] = ch;
                            putchar('*');
                    }
            }
            pword[counter] = '\0';
    }
    
    int main()
    {
            char password[20];
            passgets(password, 19);
            return 1;
    
    }
    I then compile it with

    gcc prog.c -o prog -lcurses

    When I run the program all it does is print 19 *'s and exits, doesnt take any input, etc. What could it be?

  4. #4
    Deathray Engineer MacGyver's Avatar
    Join Date
    Mar 2007
    Posts
    3,210
    LOL. Well, it does store the input, but what else do you want it to do? You told it to store the input, hide the text, and then quit.

  5. #5
    Registered User
    Join Date
    Dec 2006
    Posts
    15
    No what it is supposed to do is the following:
    every time a key is pressed, it is added to the character buffer and a * is printed. Once the user pressed enter it quits
    What it currently does is, when run, it prints 19 *'s and quits, as if my whole program consisted of printf("*******************");

  6. #6
    Deathray Engineer MacGyver's Avatar
    Join Date
    Mar 2007
    Posts
    3,210
    Try changing the '\r' to '\n'.

  7. #7
    Registered User
    Join Date
    Dec 2006
    Posts
    15
    nah same result
    btw. im running ubuntu if that matters

    edit:
    its strange... in theory it should work, but it is as if some is pressing a key on the keyboard and as soon as the program is run it fills up with crap
    Last edited by nickkrym; 05-11-2007 at 10:30 AM.

  8. #8
    Deathray Engineer MacGyver's Avatar
    Join Date
    Mar 2007
    Posts
    3,210
    I don't have the curses library so I can't play with it at the moment. Sorry.

    I wish we had a more standard way of doing these kind of things. As it stands, you have to fight with the libraries or manage it via O/S specific methods. Kind of annoying actually.

  9. #9
    Registered User
    Join Date
    Dec 2006
    Posts
    15
    I was looking at the man pages of getch and i read the following:
    The getch, wgetch, mvgetch and mvwgetch, routines read a character from
    the window. In no-delay mode, if no input is waiting, the value ERR is
    returned. In delay mode, the program waits until the system passes
    text through to the program.
    What is this no-delay mode and does it have to do with that?

  10. #10
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    The quote you gave explains what no-delay mode is.

    To expand ....

    The behaviour of getch() and related functions is affected by settings that your program can control. One of those settings is no-delay mode which is changed using the nodelay() function -- Enter "man nodelay" (I seem to recall it's "man 3 nodelay" for the library function, but may be wrong on that) for information on the function call.

    In no-delay mode, if there is no input pending, getch will return an error status. This is potentially useful if you want to poll for user input, but do something (eg count down for some period, so the program effectively only waits for a fixed time for input, but tells the user how long is remaining).

    If not in no-delay mode, if there is no input pending, getch() will sit and wait until input is available.

  11. #11
    Registered User
    Join Date
    Dec 2006
    Posts
    15
    Thanks for the reply, but I finally found something that works. It is slightly above my head but i am trying to fully understand what it does. BTW backspaces dont work here, any ideas on that?

    Code:
    #include <stdio.h>
    #include <termios.h>
    #include <unistd.h>
    #include <ctype.h>
    
    int mygetch ( void ) 
    {
      int ch;
      struct termios oldt, newt;
      
      tcgetattr ( STDIN_FILENO, &oldt );
      newt = oldt;
      newt.c_lflag &= ~( ICANON | ECHO );
      tcsetattr ( STDIN_FILENO, TCSANOW, &newt );
      ch = getchar();
      tcsetattr ( STDIN_FILENO, TCSANOW, &oldt );
      
      return ch;
    } 
    
    int main()
    {
      
      int ch;
      char pword[BUFSIZ];
      int i = 0;
      
      puts ("Enter your password");
      fflush(stdout);
      
      while ((ch = mygetch()) != EOF 
              && ch != '\n' 
              && ch != '\r' 
              && i < sizeof(pword) - 1)
      {
        if (ch == '\b' && i > 0) 
        {
          printf("\b \b");
          fflush(stdout);
          i--;
          pword[i] = '\0';
        }
        else if (isalnum(ch))
        {
          putchar('*');
          pword[i++] = (char)ch;
        }
      }
    
      pword[i] = '\0';
      
      printf ("\nYou entered >%s<", pword);
      
      return 0;
    }
    Only thing is backspace doesnt work, any ideas on that?

  12. #12
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    What do you get as output, for example?

  13. #13
    Registered User
    Join Date
    Dec 2006
    Posts
    15
    With the new code (i.e. the code I posted above), I see everything I typed. What this means is that backspaces are effectively ignored, so if i type "hi <backspace>a" (intending to type ha), it will print hia.

  14. #14
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Quote Originally Posted by KONI View Post
    You might want to have a look at this thread, it basically explains everything you want to do.
    The final version of the code has a backspace feature. If you study it, you're bound to see how it could work in your program, as well. Nevermind our silly squabbles.

    Adak

  15. #15
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    I have my reservations about what you're doing.

    First of all, please observe that <conio.h> and <ncurses.h> implement different versions of getch(). I only say this because it appears that you've been using the code from the FAQ to do what you want. This is normally a good thing, but the code you borrowed relies on <conio.h> and its implementation of getch: you cannot mix and match libraries. If you want to use the <ncurses.h> library, then develop your application in accordance with the library's documentation. (read: I think you have to call initscr() and do some other things before input functions can work the way you expect them to.)

    It's perfectly fine if you don't want to use <ncurses.h> by the way, you can always use something else, like <termios.h>. But you should realize too that you cannot mix Standard and non-Standard code. The Standard only guarantees anything while you are in accordance with its rules.

    What I mean is that getchar is the root of your problem. Check out this average, untested fetch_string function:
    Code:
    char * fetch_string ( char * s, unsigned int n ) {
       if ( s ) {
          unsigned int i;
          int ch;
          for ( i = 0; i < n - 2; i++ ) {
             ch = getchar( );
             if( ch != '\n' && ch != EOF )
                s[i] = ch;
             else
                break;
         }
         s[i] = '\0';
       }
        return s;
    }
    getchar is implemented in such a way that allows the terminal to take care of rubout. It has no knowledge of the mistakes you make and happily returns anything in the C character set. The only reason that my function works is probably due to an intelligent environment and the fact that I'm completely following the Standard, and operating directly on the C string. Because your code never encounters the backspace character, the counter cannot be adjusted and therefore you end up with mistaken passwords, prematurely cut off passwords thanks to mistakes, et cetera. I was able to diagnose this problem because you provided the output though, thanks for cooperating.

    That's not to say what you have implemented already is a step in the wrong direction, I'm just not very familiar with the library you are using now. If termios implements a character grabbing function, use that. If not, forget about it and go back to ncurses and try again.
    Last edited by whiteflags; 05-11-2007 at 07:58 PM. Reason: some rewording. sorry.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Checking array for string
    By Ayreon in forum C Programming
    Replies: 87
    Last Post: 03-09-2009, 03:25 PM
  2. About aes
    By gumit in forum C Programming
    Replies: 13
    Last Post: 10-24-2006, 03:42 PM
  3. SSH Hacker Activity!! AAHHH!!
    By Kleid-0 in forum A Brief History of Cprogramming.com
    Replies: 15
    Last Post: 03-06-2005, 03:53 PM
  4. vectors and user input
    By Chaplin27 in forum C++ Programming
    Replies: 6
    Last Post: 01-17-2005, 10:23 AM
  5. Nested Structures - User Input
    By shazg2000 in forum C Programming
    Replies: 2
    Last Post: 01-09-2005, 10:53 AM