Visit Jeremy's Blog.
Go Back > Forums > Non-*NIX Forums > Programming
User Name
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.


  Search this Thread
Old 01-02-2007, 06:28 PM   #1
Rain Duck
LQ Newbie
Registered: Jan 2007
Posts: 2

Rep: Reputation: 0
file descriptors in Perl-----I need to use gpg's "--passphrase-fd n" option


I would like to use gpg to encrypt something from the standard input
inside a perl program:
system( <<stuff>> | gpg -c -o $OutputFilename - )

This works fine interactively.

I also need to run this in a cron job. How can I read a password
from a file (yes, I understand there are security risks in doing
this)? gpg's help file tells me that I can use a "file descriptor n"
to do this:

--passphrase-fd n
Read the passphrase from file descriptor n. If you
use 0 for n, the passphrase will be read from stdin.
This can only be used if only one passphrase is
supplied. Don't use this option if you can avoid it.

I've seen this simple example:
system( cat $HOME/.BadPassword | gpg -c -passphrase-fd 0 -o $OutputFilename - )

However, this will not work for me because my input comes from the
standard input. So it looks like I need to set up another file
descriptor (say, "3") for my password file:
system( <<stuff>> | gpg -c -passphrase-fd 3 -o $OutputFilename - )

How can I do this in perl?

Thanks for your help!

Old 01-03-2007, 03:25 PM   #2
LQ 5k Club
Registered: Aug 2005
Distribution: OpenSuse, Fedora, Redhat, Debian
Posts: 5,398
Blog Entries: 2

Rep: Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908
How about something like the (untested) code fragment:

   my $password = SomeObfuscationFunction();
   open( ENCRYPTOR, "|gpg -c -o $OutputFilename -" ) || die "Cannot launch gpg : $!\n";
   print ENCRYPTOR $password;
   close ENCRYPTOR;
This launches the gpg program, with it's stdin piped to a perl file descriptor. You can then write to the file desciptor to send data to the child process's standard input.

--- rod.
Old 02-07-2007, 09:21 PM   #3
Rain Duck
LQ Newbie
Registered: Jan 2007
Posts: 2

Original Poster
Rep: Reputation: 0
Thanks for the suggestion, but it will not work for me because
some other process is using the standard input. Let me start
from scratch, filling in some of the details I left off the
first time:

For backup purposes, I tar certain files, burn to a DVD, and move
offsite. I would like to encrypt these files as well. Because these
tar'ed files are large (they fill a DVD), I would like to do both
operations simultaneously.

Suppose I have a directory called "cv". This command will tar and encrypt the directory:
tar cvvjf - cv 2>> cv.tar.log | gpg -ca -o cv.tar.bz2.asc -

This will decrypt and untar:
gpg -o - cv.tar.bz2.asc | tar xjvf -

This works great if I run them interactively---I am prompted for the
password each time. How do I get it to work in a (perl) script (so I can
have a cron job do this automatically when I am sleeping)? What
I cannot figure out is how to send a password (that resides in, say,
/password.txt) to gpg.

Here is a small Perl script that does not work:
open(PW, "/password.txt");
print ("filedescriptor=$filedescriptor\n");
print ("tar cvvjf - cv 2>> cv.tar.log | gpg -ca --passphrase-fd $filedescriptor -o cv.tar.bz2.asc -\n");
system("tar cvvjf - cv 2>> cv.tar.log | gpg -ca --passphrase-fd $filedescriptor -o cv.tar.bz2.asc -");

Here is the output from this program:
tar cvvjf - cv 2>> cv.tar.log | gpg -ca --passphrase-fd 3 -o cv.tar.bz2.asc -
Reading passphrase from file descriptor 3 ...

The program just hangs there. If I type something ("foo"), then that
is used as the password! Why does gpg report that it is reading from
file descriptor 3 when in fact it reads from the standard input (#=0)?

The password file is just one word ("foo"). I've tried ending
(and not ending) the line with a newline.

Any thoughts on this?

Is there a better way to solve my problem (tar and encrypt in a script)?

Old 02-09-2007, 10:09 AM   #4
LQ 5k Club
Registered: Aug 2005
Distribution: OpenSuse, Fedora, Redhat, Debian
Posts: 5,398
Blog Entries: 2

Rep: Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908
Is there no way to have the gpg program read from a file (I scanned the manpage quickly, but didn't see a definitive answer)? If yes, then you would have file descriptor 0 available to pipe your passphrase to gpg, while reading the encryption data from the specified file. This is inherently unsecure, so perhaps it isn't possible.

By inspection, it looks like your approach should work. I guess I would start by writing some short code stub in C which reads from a specified file descriptor, and echoes everything it reads to standard out. Use that to replace the gpg tool, for diagnostic puposes. This lets you test whether the problem is with the perl or the gpg side of the issue. If you aren't C literate enough to do this, I can probably help you out there.

The perl system() function can be replaced with discrete components: fork(), exec(), wait...
Perhaps using these separately will either solve the problem, or reveal a solution.

--- rod.
Old 02-24-2011, 10:24 AM   #5
LQ Newbie
Registered: Feb 2011
Posts: 1

Rep: Reputation: 0
perl parsing file descriptor with system

I had the same problem. That perl was closing my file descriptor when calling system. Perl set close-on-open flag on all file descriptors or uses $SYSTEM_FD_MAX.
I used the following code to get it to work.

use POSIX;
use Fcntl qw/ :mode  /;


fcntl (PWFILE,F_SETFD,0);
my $fd=fileno PWFILE;
my $cmd="sshpass -d$fd ssh thansen ls";
open (CMD,"$cmd|") or die "failed cmd:$cmd";
while(<CMD>) {
	print $_;
Old 02-25-2011, 09:52 AM   #6
Senior Member
Registered: Mar 2004
Location: england
Distribution: NetBSD, Void, Debian, Mint, Ubuntu, Puppy, Raspbian
Posts: 3,487

Rep: Reputation: 233Reputation: 233Reputation: 233
perl system does a fork/exec
If exec is specified without command or arguments, and any file descriptors with numbers greater than 2 are opened with associated redirection statements, it is unspecified whether those file descriptors remain open when the shell invokes another utility. Scripts concerned that child shells could misuse open file descriptors can always close them explicitly, as shown in one of the following examples.
why don't you just put the pipeline you
gave in a shell script for the cron job.


exec 7<passwd
gpg -c -passphrase-fd 7

oops, didn't see the previous post, fcntl may work
but why use perl to call a shell pipeline?

Last edited by bigearsbilly; 02-25-2011 at 09:58 AM.


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off

Similar Threads
Thread Thread Starter Forum Replies Last Post
bash script: using "select" to show multi-word options? (like "option 1"/"o zidane_tribal Programming 7 12-19-2015 01:03 AM
"Shutdown" and "Restart" option missing after upgrade hansalfredche Mandriva 8 11-02-2006 07:23 AM
"cc1: error: invalid option 'tune=i686'" while installing Perl modules via CPAN scuzzman Programming 12 08-21-2006 09:30 PM
problem "make"ing gtk+ "/usr/bin/env: perl -w" caid Linux - Newbie 8 07-29-2005 04:51 AM
anging "Protocol" option to "IMPS/2" in XF86Config-4 causes problems zstingx Linux - General 2 10-27-2003 09:47 AM > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 09:13 PM.

Main Menu
Write for LQ is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration