Search code examples
javascalainputgnupg

Generating PGP signatures from a Scala program


I am writing a small Scala script to generate PGP signatures for all the files in the current directory. This is what I wrote:

object PGPSign {
    def main(args: Array[String]) {
    signFilesInDirectory(new java.io.File("."))
  }

  def signFilesInDirectory(dir: java.io.File) {
    if(!dir.exists())
      throw new java.io.FileNotFoundException
    if(!dir.isDirectory())
      throw new RuntimeException("Expecting directory")
    println("Signing files in: " + dir.getAbsolutePath())
    for{ file <- dir.listFiles 
      if !file.isDirectory //ignoring directories
      val fileName = file.getName()
      if !fileName.startsWith(".") //ignoring hidden files
    } { 
      ("gpg -ab " + fileName).!!
    }
  }
}

In the console, the command gpg -ab FILE_NAME will request a password. When I execute my scala script I got this exception at the point of invoking the external command:

gpg: cannot open tty `/dev/tty': Device not configured
Exception in thread "main" java.lang.RuntimeException: Nonzero exit value: 2
at scala.sys.package$.error(package.scala:27)
at scala.sys.process.ProcessBuilderImpl$AbstractBuilder.slurp(ProcessBuilderImpl.scala:131)
at scala.sys.process.ProcessBuilderImpl$AbstractBuilder.$bang$bang(ProcessBuilderImpl.scala:101)
at PGPSign$$anonfun$signFilesInDirectory$3.apply(PGPSign.scala:25)
at PGPSign$$anonfun$signFilesInDirectory$3.apply(PGPSign.scala:20)
at scala.collection.TraversableLike$WithFilter$$anonfun$foreach$1.apply(TraversableLike.scala:743)
at scala.collection.IndexedSeqOptimized$class.foreach(IndexedSeqOptimized.scala:34)
at scala.collection.mutable.ArrayOps.foreach(ArrayOps.scala:38)
at scala.collection.TraversableLike$WithFilter.foreach(TraversableLike.scala:742)
at PGPSign$.signFilesInDirectory(PGPSign.scala:20)
at PGPSign$.main(PGPSign.scala:11)
at PGPSign.main(PGPSign.scala)

I have the idea this is related to the fact that the external command (gpg in this case) requests some input. If this is what is creating the problem(?), what is the easiest general way to make any external command (requesting any amount of inputs) to work when executed from Scala ?


Solution

  • gpg expects to be able to read from/write to a tty, which is not available unless gpg is started from an interactive shell. You should use the --no-tty option to disable this behavior. Also, you probably want batch mode, enabled with --batch.