"Copy" buffer?

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?

TIA
https://linux.die.net/man/1/xsel

It will sit happily at the end of a pipe, so
./pwgen | xsel

Plus you can also do the same thing directly within your program by setting up a https://linux.die.net/man/2/pipe
Ah! I never thought of that - thank you very much! I'll give that a shot and post back, fwiw.

:-)
Issuing this: ./pwgen | xsel -p

Results in this:

xsel: Can't open display: (null)
: Inappropriate ioctl for device

Any advice?
What does echo $DISPLAY say?
If DISPLAY is empty, try this:

 
export DISPLAY=:0

Maybe add it to your .bashrc.
You need to set DISPLAY
1
2
3
4
5
6
7
8
9
10
$ echo hello | xsel -p
$ xsel
hello
$ echo $DISPLAY
:0

$ export DISPLAY=
$ echo hello | xsel -p
xsel: Can't open display: (null)
: Inappropriate ioctl for device 


Edit: dutch beat me to it.
Last edited on
This is what I get after adding the export to .bashrc:

echo $DISPLAY
:0

$ echo hello | xsel -p
xsel: Can't open display: (null)
: Connection refused

Last edited on
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.
Last edited on
Have you enabled X11 forwarding on your Putty terminal?
https://www.google.com/search?q=PuTTY+X+forwarding
Yes. I got it working after installing Xming on the windows side and enabling X11 forwarding on the Linux side. In /etc/ssh/sshd_conf:

1
2
3
X11Forwarding yes
X11DisplayOffset 10
X11UseLocalhost yes


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?

Maybe read the answers here:
https://superuser.com/questions/440128/xming-clipboard-only-works-one-way
I'm sorry - I have a version of this which runs on windows. I modified it to run on Linux.
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.
The xsel manipulates "selection" that the X11 has. That is not the only clipboard in Linux, and X11 is not part of them all.
https://unix.stackexchange.com/questions/414303/does-non-x-linux-have-a-clipboard
https://stackoverflow.com/questions/749544/pipe-to-from-the-clipboard-in-bash-script
https://superuser.com/questions/451039/shared-clipboard-in-virtualbox-with-command-line-only-debian-guest


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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71

#include <iostream>
#include <Windows.h>
#include <ctime>

using namespace 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;

}

Last edited on
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.


Then a note:
The rand() of C Library is no longer state-of-art. https://channel9.msdn.com/Events/GoingNative/2013/rand-Considered-Harmful
Standard C++ Library has <random> http://www.cplusplus.com/reference/random/
(It is not "perfect" either.)
It definitely gets complicated. Therein lies the challenge.

Thx for the note on rand().
Registered users can post here. Sign in or register to post.