Hi. I have a small console program which creates a password for a user. Right now it is running on Windows but I want to run it on various Linux distros as well. Here's all it does:
1. Ask the user how many characters they want in their password (8 to 20).
2. It generates the password.
3. It then copies the pw to the clipboard (Windows)
The user can then paste the password wherever they need it.
I want to do this same thing in a console application on a Linux server - say, Ubuntu for example. So the user would open a terminal if they are using a GUI or just use the command line to run the program (./pwgen) if they are not using a GUI. How would I get the generated password into a buffer so the user can then paste it where they need it? I realize that the basic copy/paste would be different for different GUIs but what about right on the command line?
Try export DISPLAY=:1
You can try different display names with echo hello | xsel --display :1
The -p (primary) mode is the default so you can leave out the switch.
I think you might want -b (clipboard) mode. (Won't affect display problem, though.)
Ok I have a clue as to what's going on. If I am running from a terminal on a Windows box I get all these errors. If I jump on the actual server and run these same commands everything works as it should. So is the xsel service looking at my Windows machine when I run it in a PuTTY terminal which is logged into the server?
Update:
It doesn't work from ANY terminal regardless of the underlying OS. I just tried it from my Mint laptop and no luck. This only seems to work if I'm directly on the server itself.
It doesn't error out but it doesn't carry over the clipboard text to the windows side. This is going to be a little tricky because when I run my little program like this : ./pwgen | xsel -b, the entire output of the program is sent to the Primary Selection and the user never sees the prompts. Everything is then shown after running the xsel command by itself.
The program's entire output is this:
This utility will generate a STRONG password.
How many characters do you want the password to be? <<HERE IS WHERE USER ENTERS A NUMBER AND HITS "ENTER">>
12
This is your new 12 character STRONG password which has been copied to the clipboard: ~~rV6gGK>BUO
I would like to have only the generated password to be copied to the Primary Selection. I tried using the system() command but I am not bright enough to figure out how to send the output to xsel in C++ code.
Running this program on a windows machine works fine. As a challenge to myself I want to get it running on a Linux box as well.
Print everything but the password to stderr instead of stdout. Only print the password to stdout, which is what goes through the pipe.
fprintf(stderr, "This utility ...\n");
You say "it doesn't carry over the clipboard text to the windows side." and also "running this program on a windows machine works fine." That seems contradictory to me. Assuming copying to the windows clipboard is not working, have you tried with and without -b?
So printing everything except the password to stderr works until I pipe through to xsel, then the output doesn't show on the screen until I invoke xsel.
I have to heap kudos upon the folks here who are willing to help me with such a trivial issue. Can you even imagine what I would be facing had I dared to ask this question on stack overflow? I would have been digitally assassinated by now!
Got it. I canned Xming and installed VcXsrv and copy/paste works fine between the two OSs. Now for my next challenge - I am going to try and get the pword into xsel programmatically.
Lets say that you sit on Windows, take ssh connection with Putty to remote and run program in remote. You want the stdout of that process to somehow go to Putty, which possibly will relay it to Windows' clipboard?
I prefer openssh client, there I can:
[Windows]$ ssh remotepc 'pwgen' | something
The 'ssh' creates connection to 'remotepc' and executes program 'pwgen' there.
The output of pwgen is transferred to local (Windows) client via the ssh tunnel.
Effectively, we run ssh | something on Windows, but the output of ssh is the output of (Linux version) of 'pwgen'.
I have no idea whether there is Windows program 'something' that feeds its stdin into Windows clipboard.
Not exactly - I just want the output to be placed into a "clipboard" which can be pasted into either a windows or linux application which requires a new password. Whether the pwgen executable runs on windows or linux, it should be able to be pasted into either. That part is working now. Next up, I want to have the program itself place the pword into the "clipboard" on linux just like it does on the windows version. In the windows version you just run pwgen.exe, tell it how many characters you want in the pword and it generates the pword and copies it to the clipboard for you. I use it all the time when I'm creating accounts on various sites or creating users for databases, network users etc.
Here's the code for the windows version - grab it and compile it. You'll see how it runs. It's no big deal - just a programming exercise for me to get my brain working again. I used to be an Oracle DBA and back-end programmer back in my youth. After 20 years out of the industry I wanted to get back into coding so I'm doing little projects like this one.
#include <iostream>
#include <Windows.h>
#include <ctime>
usingnamespace std;
int pwlen;
void toClipboard(HWND hwnd, const std::string &s)
{
OpenClipboard(hwnd);
EmptyClipboard();
HGLOBAL hg=GlobalAlloc(GMEM_MOVEABLE,s.size()+1);
if (!hg){
CloseClipboard();
return;
}
memcpy(GlobalLock(hg),s.c_str(),s.size()+1);
GlobalUnlock(hg);
SetClipboardData(CF_TEXT,hg);
CloseClipboard();
GlobalFree(hg);
}
void createmenu()
{
cout << "How many characters do you want the password to be? ";
cin >> pwlen;
}
int main ()
{
string password, ans;
int max, pwordchar, i;
max = 94; //set the upper bound to generate the random number
cout << "This utility will generate a STRONG password. \n\n A STRONG password should be at least 16 characters long and preferably 20 or more. \n\n";
cout << "They should contain mixed case letters, numbers and symbols.\n\n";
createmenu();
srand(time(0));
for (i=1; i<=pwlen; i++)
{
pwordchar=rand()% max + 33; //we want to skip the first 32 ASCII characters
password = password += (char)pwordchar;
}
cout << endl;
cout << "This is your new " << pwlen <<" character STRONG password which has been copied to the clipboard: ";
cout << password << endl;
cout << "\nPress \"RETURN\" key to exit" << endl;
// get desktop windows and the call toClipboard
HWND hwnd = GetDesktopWindow();
toClipboard(hwnd, password);
cin.clear();
cin.ignore(255, '\n');
cin.get();
return 0;
}
The twist is that Linux does not have clipboard. X11 has its "selection". The gpm (mouse on virtual console) has its selection. Wayland (which finally starts to replace X11) ... no idea what it has. You can run separate 'clipboard' process. Whichever solutions you have -- applications have to interact with them.
For your program to use direct access the question is then: "Which clipboard(s) the user has?"
Is this a Wayland session?
Is this a X11 session?
Is this a CLI session?
Are we running in X11-based terminal within XWayland started by Wayland session?
...
Are we running in OS X?
A Unix idiom is to have simple tools and form more complex workflows by piping them together.