I am writing a program in C++ where I am supposed to receive a string from user without displaying it on screen (for example: apassword). I tried using cin and gets to accept the string. But both will echo the characters entered by user in console.
So is there any function or any other way of doing it in C++?
How to avoid that data being read via cin shows up on the console depends very much on the console; it's certainly operating system dependant.
On Windows, you can use the SetConsoleMode function to enable/disable the echo for any file handle, including the standard input handle.
Something like
void enableStdinEcho( bool b ) {
HANDLE hStdin = ::GetStdHandle( STD_INPUT_HANDLE );
DWORD mode = 0;
::GetConsoleMode( hStdin, &mode );
if ( b ) {
mode |= ENABLE_ECHO_INPUT;
} else {
mode &= ~ENABLE_ECHO_INPUT;
}
::SetConsoleMode( hStdin, mode );
}
could probably be used to toggle the echo on stdin.
The C++ standard does not define a mechanism to do this. You have to rely on a platform specific library. For example with gcc/glibc use getpass
http://www.gnu.org/software/libc/manual/html_mono/libc.html#getpass
There might be other libraries that abstract these functions and provide a platform independent wrapper.
This is not a C++, iostream etc. question at all - it's specific to the terminal you're using.
See this question for ideas, and then ask a question specific to your terminal if it isn't covered there and you can't use ncurses.
Related
I'm programming in C++ and have run into a wall.
I need to get input from the keyboard. The problem is that I also need to get input from keys like control, scroll lock, windows key, etc. I also need to be able to differentiate between the numpad and regular numbers 0-9.
I tried using _getch(). While it can get keys like arrow keys and the numpad, I can't get keys like control, shift and scroll lock.
Does anyone have any suggestions?
There is no standard way to do this because C++ does not assume the system even has all those things.
A good solution for what you are trying to do is the SDL library. Look here:
https://www.libsdl.org/
I see the word "windows key" so I'm assuming you're programming for Windows
Use WinAPI ReadConsoleInput
HANDLE hInput = GetStdHandle(STD_INPUT_HANDLE);
INPUT_RECORD ir;
DWORD read;
if (!ReadConsoleInput(hInput, &ir, 1, &read) || read == 0) {
// Something went wrong
}
if (ir.EventType == KEY_EVENT) {
// Do stuff here
}
Refer to KEY_EVENT_RECORD for more information. You can get control keys states from
ir.Event.KeyEvent.dwControlKeyState
This is an example provided by Microsoft.
I want to detect whether or not there is input waiting on stdin in Windows.
I use the following generic structure on Linux:
fd_set currentSocketSet;
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 0;
int result = 1;
while (result > 0){
FD_ZERO(¤tSocketSet);
FD_SET(STDIN, ¤tSocketSet);
result = select(STDIN+1, ¤tSocketSet, NULL, NULL, &tv);
if (result == -1){
printf("Network Error -- select errored with id=%d.\n", errno);
return;
} else if (result > 0){
//...do stuff
}
}
Note: I do not want to deal with the keyboard and keyboard functions like kbhit. I want a way to do what I asked. I do not want a third party library to do this either, I would like a native Windows library call to get the answer.
Note #2: On windows the above code fails with windows error code 10038 "An operation was attempted on something that is not a socket" which probably means that windows does not support selecting on STDIN.
As stated in the ReadConsoleInput() documentation:
A process can specify a console input buffer handle in one of the wait functions to determine when there is unread console input. When the input buffer is not empty, the state of a console input buffer handle is signaled.
To determine the number of unread input records in a console's input buffer, use the GetNumberOfConsoleInputEvents function. To read input records from a console input buffer without affecting the number of unread records, use the PeekConsoleInput function. To discard all unread records in a console's input buffer, use the FlushConsoleInputBuffer function.
You can use GetStdHandle() to get a handle to STDIN for use in the above functions.
As already pointed out, in Windows you have to use GetStdHandle() and the returned handle cannot be mixed with sockets. But luckily, the returned handle can be tested with WaitForSingleObject(), just like many other handles in Windows. Therefere, you could do something like this:
#include <stdio.h>
#include <windows.h>
BOOL key_was_pressed(void)
{
return (WaitForSingleObject(GetStdHandle(STD_INPUT_HANDLE),0)==WAIT_OBJECT_0);
}
void wait_for_key_press(void)
{
WaitForSingleObject(GetStdHandle(STD_INPUT_HANDLE),INFINITE);
}
int main()
{
if(key_was_pressed())
printf("Someone pressed a key beforehand\n");
printf("Wait until a key is pressed\n");
wait_for_key_press();
if(key_was_pressed())
printf("Someone pressed a key\n");
else
printf("That can't be happening to me\n");
return 0;
}
EDIT: Forgot to say that you need to read the characters from the handle in order to key_was_pressed() to return FALSE.
As you know, Linux != Windows, and you're not going to get the same semantics for a "select()" in both environments.
You didn't specify whether this is a Windows GUI or console-mode program, either. It makes a difference.
... HOWEVER ...
Two Win32 APIs you might want to look at:
GetAsyncKeyState
PeekConsoleInput
'Hope that helps
PS:
If this is a console-mode program, you're going to need a window handle. Call GetStdHandle(STD_INPUT_HANDLE) to get it.
When dealing with console input (stdin,std::cin) is there a portable way in C++ to manage the various actions that a user may perform like:
Backspace/Delete
List item
Left/Right arrow keys (moving cursor back/forth insert text)
For example in windows when using std::cin (eg: std::cin >> s;), it allows for arrow keys, however when using the same bit of code on linux, the arrow keys are assumed as part of the input, the cursor is not moved around.
I know of various TUI frameworks like curses and ncurses that provide such functionality however they are more than what is required.
I'm hoping there's a simple solution based on the standard libraries, or even a lightweight open source library that might have a std::getline like feature that is portable across the more popular OSes.
Things like backspace and delete are typically handled by the
system; when you read from a terminal, you only get the input
when the user presses enter.
What the system does is usually fairly limited. In particular,
I don't know of any that do things like file name completion.
If more than what the system does is desired, I would recommend
looking into the readline library, used by many GNU programs
(bash, gdb, etc.). It's available separately from the
applications which use it. (Two small warnings: I don't know
how good its support is for native Windows, and I'm not sure
which license it is under: GPL or LGPL.)
readline is a good choice for Linux, but it's GPL! I use the following code to compile on Windows and Linux:
#ifdef USE_READLINE
#include <readline/readline.h>
#include <readline/history.h>
#endif
...
void getline(char *buf)
{
#ifdef USE_READLINE
char *tmp;
tmp = readline(PROMPT);
if(strncmp(tmp, buf, MAXLENGTH)) add_history(tmp); // only add new content
strncpy(buf, tmp, MAXLENGTH);
buf[MAXLENGTH]='\0';
free(tmp);
#else
std::cout<<PROMPT;
std::cin.get(buf,MAXLENGTH);
std::cin.ignore(); // delete CR
#endif
}
This question already has answers here:
What is the simplest way to write to stdout in binary mode?
(2 answers)
Closed 7 years ago.
I would like to know if it is possible that an utility yields binary data (i.e. graphical images) and outputs them through IO console, while another application, instructed about the nature of those data and informed of the number of the incoming bytes, is able to read it from IO console.
Yes, it is possible. While it's true that often stdin/stdout are meant to be text there are many programs that are designed to get binary input or write binary output from standard I/O channels.
The only thing you should pay attention is that normally stdout/stdin are opened in text mode under Windows, so you should switch them to binary mode to avoid character translation.
To set binary mode on stdin/stdout on Windows you need to use the _setmode call:
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
int main( void )
{
int result;
// Set "stdin" to have binary mode:
result = _setmode( _fileno( stdin ), _O_BINARY );
if( result == -1 )
perror( "Cannot set mode" );
else
printf( "'stdin' successfully changed to binary mode\n" );
}
Note also to pay attention to file buffering. Often programs will flush the buffer on newlines ONLY when the output is to an interactive console and not when it's another process. So if you need synchronizaton remember to call fflush after writing a message because otherwise the other process will not be able to get the data.
You can use traditional socket or lighter named pipe for this kind of thing.
You could Base 64-Encode/Decode the data. This will avoid the need to send pure "bits" over the standard input/output stream.
If the process is to be hosted within another process that will capture your stdout from the process that writes binary data then there is no need to encode it. In that case you can write the raw binary data to the output and be done with it. This is for example how the image writing dot tool from graphviz works, it doesn't encode it's input by default. These kinds of tools are also pretty easy to pipe to a file by the use of > in the command shell.
Only if the output from the data is going to be seen on the console are you going to need to encode it. It's not a very good idea to print the contents of say an image file.
You can do it if you choose an appropriate encoding, as the console is a text stream. Use for example Base64 encoding for your binary data and it will work fine. Another alternative is the "Quoted-printable" format. You end up of course with more bytes than the original binary data, but IMHO the only way to do it safely using the console.
I know, that there's the is_open() function in C++, but I want one program to check if a file hasn't been opened by another application. Is there any way to do it using standard library?
EDIT - Clarified in the answers that this is for a Linux application.
Not only the standard library does not have this funcionality, it's not even possible in general. You could (on linux) check /proc/*/fd — but it is possible that your program does not have permission to do it on processes from other users (this is the default in Ubuntu, for instance).
No, the standard library has no such functionality.
If you control the other process (have source code), the best plan is to use advisory locks in both processes. This locking is defined in POSIX, and will be portable across operating systems.
In Linux, you can use the utility lsof to see what files are opened by other processes.
This is limited to what you have permissions for - you have to do the check as a privileged user, or you'll only get results for files opened by the same user as the one doing the check.
I only know of the command line utility, not of any system call you can use directly from C code.
In Linux, it's also possible to turn on mandatory locking for a given filesystem (mount -o mand), and set special flags on the file (chmod g-x,g+s). Then when your process attempts to acquire a write lock, it will fail if another process has the file open. This is hardly ever used, but if you completely control the system in question, it may be an option.
The following code may work.
int main(int argc, char ** argv)
{
int fd = open(argv[1], O_RDONLY);
if (fd < 0) {
perror("open");
return 1;
}
if (fcntl(fd, F_SETLEASE, F_WRLCK) && EAGAIN == errno) {
puts("file has been opened");
}
else {
fcntl(fd, F_SETLEASE, F_UNLCK);
puts("file has not been opened");
}
close(fd);
return 0;
}
Perhaps you could just try and get a full write lock? It'll fail if anyone else has it open for reading or writing.
fopen("myfile.txt", "r+")
If it's not cross platform and is Win32, then you can request even more fine-grained set of locks.
See here
and look at dwShareMode, value of 0, as well as the other parameters.
Nope. Unless other application uses advisory locks.
See http://docs.sun.com/app/docs/doc/816-0213/6m6ne37v5?a=view
Non-natively, you could call out to Sysinternals' handle.exe as a last resort...
As #Neil Butterworth says, the standard library doesnt.
In unix you can use fcntl to use file locks.
You could write a wrapper for your open function, that checks for a lock (and locks if none exists) a file if its open by no one else. You shold write a wrapper for close as well, that releases that lock on file close.
Seeing you have tagged linux -> there's a command-line too and API that have been added to the Linux kernel and do just that: inotify.
Here's the man page.
In Windows this little and dirty trick will work (if the file exists and you have the right permissions)
if ( 0 != rename("c:/foo.txt", "c:/foo.txt") ) {
printf("already opened\n");
}
It's likely to work also in Linux.