在perl中,如何将字符串传递给需要文件输入的CLI程序

在perl中,如何将字符串传递给需要文件输入的CLI程序,perl,macros,spamassassin,Perl,Macros,Spamassassin,我正在尝试构建一个SpamAssassin测试,该测试使用ClamAV的CLI工具sigtool来检测附加的MS Office遗留文件(如可能具有宏的.xls或.doc)是否实际具有可执行宏 在perl中调用sigtool并向其传递一个文件名以进行如下扫描非常简单 my $filename = "email_attach"; my $scan = `/usr/bin/sigtool --vba="$filename"`; if ($scan =~ /autoopen/i ) { print

我正在尝试构建一个SpamAssassin测试,该测试使用ClamAV的CLI工具sigtool来检测附加的MS Office遗留文件(如可能具有宏的.xls或.doc)是否实际具有可执行宏

在perl中调用sigtool并向其传递一个文件名以进行如下扫描非常简单

my $filename = "email_attach";
my $scan = `/usr/bin/sigtool --vba="$filename"`;
if ($scan =~ /autoopen/i ) {
  print "Scanning $file: INFECTED VBA\n";
}
然而,作为SpamAssassin测试,我已经将电子邮件附件作为变量传递到了我的测试中。因此,我不想花时间将每个附件写入磁盘,然后告诉sigtool去读取它

我研究了关于进程间通信和进程管理与通信的整个第16章编程Perl和Perl Cookbook,其中有大量的信息,但我没有看到任何东西能够将内部perl程序数据作为输入流传输到外部应用程序,该应用程序正在寻找作为命令行参数传递的路径/文件名


感谢您对如何实现这一目标的任何想法。或者,如果有人知道一种更简单的方法来检测MS Office遗留文件中的VBA宏或可执行文件,也可以。

sigtool
需要一个文件名。在某些系统上,可以通过多种方式获取管道的文件名,因此您仍然可以使用管道。然而,如果你这样做了,你会得到两个管道(一个孩子从中读取,另一个孩子从中写入),这是一个混乱的处理

通常,您必须使用非阻塞IO、异步IO、
select
循环或线程,但IPC::Run有利于我们这样做

进程通常在3个文件句柄打开时启动:STDIN(fd0)、STDOUT(fd1)和STDERR(fd2)。但是子级也可以继承任意数量的其他句柄。下面创建一个绑定到孩子的FD3的管道,并告诉孩子通过Linux特定的虚拟文件系统从该管道读取数据

use IPC::Run qw( run );
run [ '/usr/bin/sigtool', "--vba=/proc/self/fd/3" ], '3<', \$doc, '>', \my $scan;
使用IPC::运行qw(运行);
运行['/usr/bin/sigtool',“--vba=/proc/self/fd/3”],'3',\my$scan;

使用a非常简单,但IPC::Run让它相形见绌

如果
sigtool
像sane Unix实用程序一样编写,则它支持stdin的
-
。如果没有,它可能仍然支持
/dev/stdin
。但是,如果它真的依赖于一个文件(例如,可读多次),那么你就不走运了。你可以使用管道调用sigtool并将数据传递给sigtool,但要让它输出VBA宏信息,它需要那个愚蠢的文件名。我们已经尽了最大努力将磁盘IO保持在绝对最小,因为在大容量垃圾邮件过滤中,这是我们的限制因素,但我可能不得不咬紧牙关编写临时文件。您可以尝试使用内存备份的文件系统,例如
/dev/shm
。对于输出,
/dev/stdout