-
-
Notifications
You must be signed in to change notification settings - Fork 22
/
Copy pathPosixPluginFrontend.scala
85 lines (75 loc) · 2.41 KB
/
PosixPluginFrontend.scala
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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
package protocbridge.frontend
import java.nio.file.{Files, Path}
import protocbridge.ProtocCodeGenerator
import protocbridge.ExtraEnv
import java.nio.file.attribute.PosixFilePermission
import scala.concurrent.blocking
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import scala.sys.process._
import java.{util => ju}
/** PluginFrontend for Unix-like systems (Linux, Mac, etc)
*
* Creates a pair of named pipes for input/output and a shell script that
* communicates with them.
*/
object PosixPluginFrontend extends PluginFrontend {
case class InternalState(
inputPipe: Path,
outputPipe: Path,
tempDir: Path,
shellScript: Path
)
override def prepare(
plugin: ProtocCodeGenerator,
env: ExtraEnv
): (Path, InternalState) = {
val tempDirPath = Files.createTempDirectory("protopipe-")
val inputPipe = createPipe(tempDirPath, "input")
val outputPipe = createPipe(tempDirPath, "output")
val sh = createShellScript(inputPipe, outputPipe)
Future {
blocking {
val fsin = Files.newInputStream(inputPipe)
val response = PluginFrontend.runWithInputStream(plugin, fsin, env)
fsin.close()
val fsout = Files.newOutputStream(outputPipe)
fsout.write(response)
fsout.close()
}
}
(sh, InternalState(inputPipe, outputPipe, tempDirPath, sh))
}
override def cleanup(state: InternalState): Unit = {
if (sys.props.get("protocbridge.debug") != Some("1")) {
Files.delete(state.inputPipe)
Files.delete(state.outputPipe)
Files.delete(state.tempDir)
Files.delete(state.shellScript)
}
}
private def createPipe(tempDirPath: Path, name: String): Path = {
val pipeName = tempDirPath.resolve(name)
Seq("mkfifo", "-m", "600", pipeName.toAbsolutePath.toString).!!
pipeName
}
private def createShellScript(inputPipe: Path, outputPipe: Path): Path = {
val shell = sys.env.getOrElse("PROTOCBRIDGE_SHELL", "/bin/sh")
val scriptName = PluginFrontend.createTempFile(
"",
s"""|#!$shell
|set -e
|cat /dev/stdin > "$inputPipe"
|cat "$outputPipe"
""".stripMargin
)
val perms = new ju.HashSet[PosixFilePermission]
perms.add(PosixFilePermission.OWNER_EXECUTE)
perms.add(PosixFilePermission.OWNER_READ)
Files.setPosixFilePermissions(
scriptName,
perms
)
scriptName
}
}