1#!/usr/local/bin/perl 2 3# Copyright Rainer Wichmann (2004) 4# 5# License Information: 6# This program is free software; you can redistribute it and/or modify 7# it under the terms of the GNU General Public License as published by 8# the Free Software Foundation; either version 2 of the License, or 9# (at your option) any later version. 10# 11# This program is distributed in the hope that it will be useful, 12# but WITHOUT ANY WARRANTY; without even the implied warranty of 13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14# GNU General Public License for more details. 15# 16# You should have received a copy of the GNU General Public License 17# along with this program; if not, write to the Free Software 18# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19# 20 21use warnings; 22use strict; 23use Getopt::Long; 24use File::Basename; 25use File::Copy; 26use File::stat; 27use File::Temp qw/ tempfile tempdir unlink0 /; 28use IO::Handle; 29use Fcntl qw(:DEFAULT :flock); 30use Tie::File; 31 32# Do I/O to the data file in binary mode (so it 33# wouldn't complain about invalid UTF-8 characters). 34use bytes; 35 36File::Temp->safe_level( File::Temp::HIGH ); 37 38my %opts = (); 39my $action; 40my $file1; 41my $file2; 42my $passphrase; 43my $secretkeyring; 44my $return_from_sign = 0; 45my $no_print_examine = 0; 46my $no_remove_lock = 0; 47my $base = basename($0); 48 49my $cfgfile = "@myconffile@"; 50my $datafile = "@mydatafile@"; 51my $daemon = "@sbindir@/@install_name@"; 52my $gpg = "@mygpg@"; 53 54my $TARGETKEYID = "@mykeyid@"; 55my $KEYTAG = "@mykeytag@"; 56 57$cfgfile =~ s/^REQ_FROM_SERVER//; 58$datafile =~ s/^REQ_FROM_SERVER//; 59 60$gpg = "gpg" if ($gpg eq ""); 61 62sub check_gpg_agent() { 63 my $gpgconf = "$ENV{'HOME'}/.gnupg/gpg.conf"; 64 65 if (!-f "$gpgconf") { 66 $gpgconf = "$ENV{'HOME'}/.gnupg/options"; 67 } 68 69 if (-f $gpgconf) { 70 71 my @array = (); 72 tie @array, 'Tie::File', $gpgconf or die "Cannot tie ${gpgconf}: $!"; 73 my @grep = grep(/^\s*use-agent/, @array); 74 75 # print "matches = $#grep\n"; 76 77 if ($#grep >= 0) 78 { 79 if (exists $ENV{'GPG_AGENT_INFO'}) 80 { 81 my $socke = $ENV{'GPG_AGENT_INFO'}; 82 $socke =~ s/:.*//; 83 84 # print "socke = $socke\n"; 85 86 if (! -S $socke) 87 { 88 print "--------------------------------------------------\n"; 89 print "\n"; 90 print " GPG is set to use gpg-agent, but GPG agent is"; 91 print " not running, though GPG_AGENT_INFO is defined.\n\n"; 92 print " Please restart gpg-agent, or remove the use-agent\n"; 93 print " option from ${gpgconf} and unset GPG_AGENT_INFO\n\n"; 94 print "--------------------------------------------------\n"; 95 print "\n"; 96 exit 1; 97 } 98 } 99 else 100 { 101 print "--------------------------------------------------\n"; 102 print "\n"; 103 print " GPG is set to use gpg-agent, but "; 104 print " GPG_AGENT_INFO is not defined.\n\n"; 105 print " Please start gpg-agent, or remove the use-agent\n"; 106 print " option from ${gpgconf}\n\n"; 107 print "--------------------------------------------------\n"; 108 print "\n"; 109 exit 1; 110 } 111 } 112 untie @array; 113 } 114} 115 116 117sub usage() { 118 print "Usage:\n"; 119 print " $base { -m F | --create-cfgfile } [options] [in.cfgfile]\n"; 120 print " Sign the configuration file. If in.cfgfile is given, sign it\n"; 121 print " and install it as configuration file.\n\n"; 122 123 print " $base { -m f | --print-cfgfile } [options] \n"; 124 print " Print the configuration file to stdout. Signatures are removed.\n\n"; 125 126 print " $base { -m D | --create-datafile } [options] [in.datafile]\n"; 127 print " Sign the database file. If in.datafile is given, sign it\n"; 128 print " and install it as database file.\n\n"; 129 130 print " $base { -m d | --print-datafile } [options] \n"; 131 print " Print the database file to stdout. Signatures are removed. Use\n"; 132 print " option --list to list files in database rather than printing the raw file.\n\n"; 133 134 print " $base { -m R | --remove-signature } [options] file1 [file2 ...]\n"; 135 print " Remove cleartext signature from input file(s). The file\n"; 136 print " is replaced by the non-signed file.\n\n"; 137 138 print " $base { -m E | --sign } [options] file1 [file2 ...]\n"; 139 print " Sign file(s) with a cleartext signature. The file\n"; 140 print " is replaced by the signed file.\n\n"; 141 142 print " $base { -m e | --examine } [options] file1 [file2 ...]\n"; 143 print " Report signature status of file(s).\n\n"; 144 145 print " $base { -m G | --generate-keys } [options] \n"; 146 print " Generate a PGP keypair to use for signing.\n\n"; 147 148 print "Options:\n"; 149 print " -c cfgfile --cfgfile cfgfile\n"; 150 print " Select an alternate configuration file.\n\n"; 151 152 print " -d datafile --datafile datafile\n"; 153 print " Select an alternate database file.\n\n"; 154 155 print " -p passphrase --passphrase passphrase\n"; 156 print " Set the passphrase for gpg. By default, gpg will ask.\n\n"; 157 158 print " -s gnupg_homedir --secretkeyring gnupg_homedir\n"; 159 print " Select an alternate gpg homedirectory to locate the secret keyring.\n"; 160 print " Will use '$ENV{'HOME'}/.gnupg/' by default.\n\n"; 161 162 print " -k keyid --keyid keyid\n"; 163 print " Select the keyid to use for signing.\n\n"; 164 165 print " -l --list\n"; 166 print " List the files in database rather than printing the raw file.\n\n"; 167 168 print " -v --verbose\n"; 169 print " Verbose output.\n\n"; 170 return; 171} 172 173sub check_gpg_uid () { 174 if (0 != $>) { 175 print "--------------------------------------------------\n"; 176 print "\n"; 177 print " You are not root. Please remember that samhain/yule\n"; 178 print " will use the public keyring of root to verify a signature.\n"; 179 print "\n"; 180 print "--------------------------------------------------\n"; 181 } else { 182 if (!("@yulectl_prg@" =~ //)) { 183 print "--------------------------------------------------\n"; 184 print "\n"; 185 print " Please remember that yule will drop root after startup. Signature\n"; 186 print " verification on SIGHUP will fail if you do not import the public key\n"; 187 print " into the keyring of the non-root yule user.\n"; 188 print "\n"; 189 print "--------------------------------------------------\n"; 190 } 191 } 192} 193 194sub check_gpg_sign () { 195 if ( defined($secretkeyring)) { 196 if ( (!-d "$secretkeyring")){ 197 print "--------------------------------------------------\n"; 198 print "\n"; 199 print " Secret keyring $secretkeyring not found!\n"; 200 print "\n"; 201 print " Please check the path/name of the alternate secret keyring.\n"; 202 print "\n"; 203 print "--------------------------------------------------\n"; 204 print "\n"; 205 exit; 206 } 207 } else { 208 if ( (!-d "$ENV{'HOME'}/.gnupg") || (!-e "$ENV{'HOME'}/.gnupg/secring.gpg")) { 209 print "--------------------------------------------------\n"; 210 print "\n"; 211 if (!-d "$ENV{'HOME'}/.gnupg") { 212 print " Directory \$HOME/.gnupg not found!\n"; 213 } else { 214 print " Secret keyring \$HOME/.gnupg/secring.gpg not found!\n"; 215 } 216 print "\n"; 217 print " This indicates that you have never created a \n"; 218 print " public/private keypair, and thus cannot sign.\n"; 219 print " \n"; 220 print " Please use $0 --generate-keys or gpg --gen-key\n"; 221 print " to generate a public/private keypair first.\n"; 222 print "\n"; 223 print "--------------------------------------------------\n"; 224 print "\n"; 225 exit; 226 } 227 } 228} 229 230sub check_gpg_verify () { 231 if ( (!-d "$ENV{'HOME'}/.gnupg") || (!-e "$ENV{'HOME'}/.gnupg/pubring.gpg")) { 232 print "--------------------------------------------------\n"; 233 print "\n"; 234 if (!-d "$ENV{'HOME'}/.gnupg") { 235 print " Directory \$HOME/.gnupg not found!\n"; 236 } else { 237 print " Public keyring \$HOME/.gnupg/pubring.gpg not found!\n"; 238 } 239 print "\n"; 240 print " This indicates that you have never used gpg before \n"; 241 print " and/or have no public keys to verify signatures.\n"; 242 print " \n"; 243 print " Please use 'gpg --export key_id' to export the public\n"; 244 print " signing key of the user who is signing the\n"; 245 print " configuration/database files.\n\n"; 246 print " Then you can use 'gpg --import keyfile' to import the key\n"; 247 print " into this user's public keyring.\n"; 248 print "\n"; 249 print "--------------------------------------------------\n"; 250 print "\n"; 251 exit; 252 } 253} 254 255 256sub generate () { 257 my $command = "$gpg --homedir $ENV{'HOME'}/.gnupg --gen-key"; 258 check_gpg_uid(); 259 system ($command) == 0 260 or die "system $command failed: $?"; 261 exit; 262} 263 264sub examine () { 265 my $iscfg = 0; 266 my $have_fp = 0; 267 my $have_sig = 0; 268 my $message = ''; 269 my $retval = 9; 270 my $fh; 271 my $filename; 272 273 if (!($file1 =~ /^\-$/)) { 274 die ("Cannot open $file1 for read: $!") unless ((-e $file1) && (-r _)); 275 } 276 open FIN, "<$file1" or die "Cannot open $file1 for read: $!"; 277 278 my $dir = tempdir( CLEANUP => 1 ); 279 $filename = $dir . "/exa_jhfdbilw." . $$; 280 open $fh, ">$filename" or die "Cannot open $filename"; 281 autoflush $fh 1; 282 283 while (<FIN>) { 284 print $fh $_; 285 if ($_ =~ /^\s*\[Misc\]/) { 286 $iscfg = 1; 287 } 288 } 289 if ($iscfg == 1) { 290 $message .= "File $file1 is a configuration file\n\n"; 291 } else { 292 $message .= "File $file1 is a database file\n\n"; 293 } 294 295 296 my $command = "$gpg --homedir $ENV{'HOME'}/.gnupg --status-fd 1 "; 297 $command .= "--verbose " if (defined($opts{'v'})); 298 $command .= "--verify $filename "; 299 if (defined($opts{'v'})) { 300 $command .= "2>&1"; 301 } else { 302 $command .= "2>/dev/null"; 303 } 304 305 print STDOUT "Using: $command\n\n" if (defined($opts{'v'})); 306 open GPGIN, "$command |" or die "Cannot fork: $!"; 307 308 while (<GPGIN>) { 309 if ($_ =~ /^\[GNUPG:\] GOODSIG ([0-9A-F]+) (.*)$/) { 310 $message .= "GOOD signature with key: $1\n"; 311 $message .= "Key owner: $2\n"; 312 $have_sig = 1; 313 $retval = 0; 314 } 315 if ($_ =~ /^\[GNUPG:\] VALIDSIG ([0-9A-F]+) ([0-9\-]+)\s/) { 316 $message .= "Key fingerprint: $1\n"; 317 $message .= "Signature generated on: $2\n\n"; 318 $have_fp = 1; 319 $message .= "This file is signed with a valid signature.\n" 320 if ($have_sig == 1); 321 $have_sig = 1; 322 $have_fp = 1; 323 } 324 if ($_ =~ /^\[GNUPG:\] NODATA 1/) { 325 $message .= "NO signature found.\n\n"; 326 $message .= "This file is not signed !!!\n"; 327 $have_sig = 1; 328 $have_fp = 1; 329 $retval = 2; 330 } 331 if ($_ =~ /^\[GNUPG:\] BADSIG ([0-9A-F]+) (.*)$/) { 332 $message .= "BAD signature with key: $1\n"; 333 $message .= "Key owner: $2\n\n"; 334 $message .= "This file is signed with an invalid signature !!!\n"; 335 $have_sig = 1; 336 $have_fp = 1; 337 $retval = 1; 338 } 339 if ($_ =~ /^\[GNUPG:\] NO_PUBKEY ([0-9A-F]+)/) { 340 $message .= "NOT CHECKED signature with key: $1\n\n"; 341 $message .= "The signature of this file cannot be checked: no public key available !!!\n"; 342 $have_sig = 1; 343 $have_fp = 1; 344 $retval = 1; 345 } 346 print STDOUT $_ if (defined($opts{'v'})); 347 } 348 close (GPGIN); 349 print STDOUT "\n" if (defined($opts{'v'})); 350 if ($have_sig == 0) { 351 $message .= "NO valid signature found\n"; 352 } 353 elsif ($have_fp == 0) { 354 $message .= "NO fingerprint found\n"; 355 } 356 close (FIN); 357 if ($no_print_examine == 0) { 358 print STDOUT $message; 359 } 360 unlink0( $fh, $filename ) or die "Cannot unlink $filename safely"; 361 return $retval; 362} 363 364sub remove () { 365 my $bodystart = 1; 366 my $sigstart = 0; 367 my $sigend = 0; 368 my $filename = ""; 369 my $fh; 370 my $stats; 371 372 open FH, "<$file1" or die "Cannot open file $file1 for read: $!"; 373 if (!($file1 =~ /^\-$/)) { 374 flock(FH, LOCK_EX) unless ($no_remove_lock == 1); 375 my $dir = tempdir( CLEANUP => 1 ) or die "Tempdir failed"; 376 $filename = $dir . "/rem_iqegBCQb." . $$; 377 open $fh, ">$filename" or die "Cannot open $filename"; 378 $stats = stat($file1); 379 # ($fh, $filename) = tempfile(UNLINK => 1); 380 } else { 381 open $fh, ">$file1" or die "Cannot open file $file1 for write: $!"; 382 } 383 autoflush $fh 1; 384 while (<FH>) { 385 if ($_ =~ /^-----BEGIN PGP SIGNED MESSAGE-----/) { 386 $sigstart = 1; 387 $bodystart = 0; 388 next; 389 } elsif (($sigstart == 1) && ($_ =~ /^\s+$/)) { 390 $sigstart = 0; 391 $bodystart = 1; 392 next; 393 } elsif ($_ =~ /^-----BEGIN PGP SIGNATURE-----/) { 394 $bodystart = 0; 395 $sigend = 1; 396 next; 397 } elsif (($sigend == 1) && ($_ =~ /^-----END PGP SIGNATURE-----/)) { 398 $sigend = 0; 399 $bodystart = 1; 400 next; 401 } 402 if ($bodystart == 1) { 403 print $fh $_; 404 } 405 } 406 if (!($file1 =~ /^\-$/)) { 407 copy("$filename", "$file1") 408 or die "Copy $filename to $file1 failed: $!"; 409 chmod $stats->mode, $file1; 410 chown $stats->uid, $stats->gid, $file1; 411 flock(FH, LOCK_UN) unless ($no_remove_lock == 1); 412 close FH; 413 } 414 unlink0( $fh, $filename ) or die "Cannot unlink $filename safely"; 415 return; 416} 417 418sub print_cfgfile () { 419 my $bodystart = 0; 420 my $sigstart = 0; 421 422 if (!defined($file2)) { 423 $file2 = '-'; 424 } 425 426 open FH, "<$file1" or die "Cannot open file $file1 for read: $!"; 427 open FO, ">$file2" or die "Cannot open file $file2 for write: $!"; 428 while (<FH>) { 429 if ($_ =~ /^-----BEGIN PGP SIGNED MESSAGE-----/) { 430 $sigstart = 1; 431 next; 432 } elsif (($sigstart == 1) && ($_ =~ /^\s+$/)) { 433 $sigstart = 0; 434 $bodystart = 1; 435 next; 436 } elsif ($_ =~ /^-----BEGIN PGP SIGNATURE-----/) { 437 $bodystart = 0; 438 exit; 439 } 440 if ($bodystart == 1) { 441 print FO $_; 442 } 443 } 444 exit; 445} 446sub print_datafile () { 447 die ("Cannot find program $daemon") 448 unless (-e $daemon); 449 if (defined($opts{'v'})) { 450 open FH, "$daemon --full-detail -d $datafile |" 451 or die "Cannot open datafile $datafile for read: $!"; 452 } else { 453 open FH, "$daemon -d $datafile |" 454 or die "Cannot open datafile $datafile for read: $!"; 455 } 456 while (<FH>) { 457 print $_; 458 } 459 exit; 460} 461 462sub sign_file () { 463 464 my $fileout = ''; 465 my $bodystart = 1; 466 my $sigstart = 0; 467 my $sigend = 0; 468 my $stats; 469 my $fh1; 470 my $filename1; 471 my $flag1 = 0; 472 473 check_gpg_uid(); 474 check_gpg_agent(); 475 476 if (!defined($file2)) { 477 $file2 = $file1; 478 } 479 480 if ($file1 =~ /^\-$/) { 481 my $dir = tempdir( CLEANUP => 1 ) or die "Tempdir failed"; 482 $filename1 = $dir . "/sig_vs8827sd." . $$; 483 open $fh1, ">$filename1" or die "Cannot open $filename1"; 484 $flag1 = 1; 485 # my ($fh1, $filename1) = tempfile(UNLINK => 1); 486 487 while (<STDIN>) { 488 if ($_ =~ /^-----BEGIN PGP SIGNED MESSAGE-----/) { 489 $sigstart = 1; 490 $bodystart = 0; 491 next; 492 } elsif (($sigstart == 1) && ($_ =~ /^\s+$/)) { 493 $sigstart = 0; 494 $bodystart = 1; 495 next; 496 } elsif ($_ =~ /^-----BEGIN PGP SIGNATURE-----/) { 497 $bodystart = 0; 498 $sigend = 1; 499 next; 500 } elsif (($sigend == 1) && ($_ =~ /^-----END PGP SIGNATURE-----/)) { 501 $sigend = 0; 502 $bodystart = 1; 503 next; 504 } 505 if ($bodystart == 1) { 506 print $fh1 $_; 507 } 508 # 509 # print $fh1 $_; 510 # 511 } 512 $file1 = $filename1; 513 $fileout = '-'; 514 } else { 515 open (LOCKFILE, "<$file1") or die "Cannot open $file1: $!"; 516 flock(LOCKFILE, LOCK_EX); 517 $no_print_examine = 1; 518 $no_remove_lock = 1; 519 if (examine() < 2) { 520 remove(); 521 } 522 $fileout = $file1 . ".asc"; 523 $stats = stat($file1) 524 or die "No file $file1: $!"; 525 } 526 527 if (defined($passphrase)) { 528 local $SIG{PIPE} = 'IGNORE'; 529 my $command = "$gpg --homedir $ENV{'HOME'}/.gnupg --passphrase-fd 0 -a ${KEYTAG} ${TARGETKEYID} --clearsign -o $fileout --not-dash-escaped "; 530 $command .= "--secret-keyring $secretkeyring " if (defined($opts{'s'})); 531 $command .= "$file1"; 532 open (FH, "|$command") or die "can't fork: $!"; 533 print FH "$passphrase" or die "can't write: $!"; 534 close FH or die "can't close: status=$?"; 535 } else { 536 my $command = "$gpg --homedir $ENV{'HOME'}/.gnupg -a ${KEYTAG} ${TARGETKEYID} --clearsign -o $fileout --not-dash-escaped "; 537 $command .= "--secret-keyring $secretkeyring " if (defined($opts{'s'})); 538 $command .= "$file1"; 539 system("$command") == 0 540 or die "system $command failed: $?"; 541 } 542 543 if (!($fileout =~ /^\-$/)) { 544 my $st_old = stat($file1) 545 or die "No file $file1: $!"; 546 my $st_new = stat($fileout) 547 or die "No file $fileout: $!"; 548 die ("Signed file is smaller than unsigned file") 549 unless ($st_new->size > $st_old->size); 550 move("$fileout", "$file2") 551 or die "Move $fileout to $file2 failed: $!"; 552 chmod $stats->mode, $file2; 553 chown $stats->uid, $stats->gid, $file2; 554 flock(LOCKFILE, LOCK_UN); 555 } 556 557 if ($flag1 == 1) { 558 unlink0( $fh1, $filename1 ) or die "Cannot unlink $filename1 safely"; 559 } 560 if ($return_from_sign == 1) { 561 return; 562 } 563 exit; 564} 565 566Getopt::Long::Configure ("posix_default"); 567Getopt::Long::Configure ("bundling"); 568# Getopt::Long::Configure ("debug"); 569 570GetOptions (\%opts, 'm=s', 'h|help', 'v|verbose', 'l|list', 571 'c|cfgfile=s', 572 'd|datafile=s', 573 'p|passphrase=s', 574 's|secretkeyring=s', 575 'k|keyid=s', 576 'create-cfgfile', # -m F 577 'print-cfgfile', # -m f 578 'create-datafile', # -m D 579 'print-datafile', # -m d 580 'remove-signature',# -m R 581 'sign', # -m E 582 'examine', # -m e 583 'generate-keys'); # -m G 584 585if (defined ($opts{'h'})) { 586 usage(); 587 exit; 588} 589 590if (defined($opts{'k'})) { 591 $TARGETKEYID = $opts{'k'}; 592 $KEYTAG = "--default-key"; 593} 594if (defined($opts{'c'})) { 595 $cfgfile = $opts{'c'}; 596} 597if (defined($opts{'d'})) { 598 $datafile = $opts{'d'}; 599} 600if (defined($opts{'p'})) { 601 $passphrase = $opts{'p'}; 602} 603if (defined($opts{'s'})) { 604 $secretkeyring = $opts{'s'}; 605} 606 607if (defined ($opts{'m'}) && ($opts{'m'} =~ /[FfDdREeG]{1}/) ) { 608 $action = $opts{'m'}; 609} 610elsif (defined ($opts{'create-cfgfile'})) { 611 $action = 'F'; 612} 613elsif (defined ($opts{'print-cfgfile'})) { 614 $action = 'f'; 615} 616elsif (defined ($opts{'create-datafile'})) { 617 $action = 'D'; 618} 619elsif (defined ($opts{'print-datafile'})) { 620 $action = 'd'; 621} 622elsif (defined ($opts{'remove-signature'})) { 623 $action = 'R'; 624} 625elsif (defined ($opts{'sign'})) { 626 $action = 'E'; 627} 628elsif (defined ($opts{'examine'})) { 629 $action = 'e'; 630} 631elsif (defined ($opts{'generate-keys'})) { 632 $action = 'G'; 633} 634else { 635 usage(); 636 die ("No valid action specified !"); 637} 638 639if (defined($ARGV[0])) { 640 $file1 = $ARGV[0]; 641} 642if (defined($ARGV[1])) { 643 $file2 = $ARGV[1]; 644} 645 646 647if (($action =~ /[REe]{1}/) && !defined($file1)) { 648 usage(); 649 die("Option -m $action requires a filename (or '-' for stdio)\n"); 650} 651 652if ($action =~ /^F$/) { 653 if (!defined($file1)) { 654 $file1 = $cfgfile; 655 } 656 $file2 = $cfgfile; 657 sign_file (); 658} 659 660if ($action =~ /^D$/) { 661 if (!defined($file1)) { 662 $file1 = $datafile; 663 } 664 $file2 = $datafile; 665 sign_file (); 666} 667 668if ($action =~ /^R$/) { 669 # $file1 defined 670 my $i = 0; 671 while (defined($ARGV[$i])) { 672 $file1 = $ARGV[$i]; 673 remove (); 674 ++$i; 675 } 676} 677 678if ($action =~ /^E$/) { 679 # $file1 defined 680 # default: $file2 = $file1 681 check_gpg_sign(); 682 my $i = 0; 683 while (defined($ARGV[$i])) { 684 $file1 = $ARGV[$i]; 685 $file2 = $file1; 686 $return_from_sign = 1; 687 sign_file (); 688 ++$i; 689 } 690} 691 692if ($action =~ /^e$/) { 693 # $file1 defined 694 # default: $file2 = stdout 695 check_gpg_verify(); 696 my $i = 0; 697 my $ret = 0; 698 while (defined($ARGV[$i])) { 699 print "\n"; 700 $file1 = $ARGV[$i]; 701 $ret += examine (); 702 ++$i; 703 print "\n--------------------------------\n" if (defined($ARGV[$i])); 704 } 705 exit($ret); 706} 707 708if ($action =~ /^f$/) { 709 $file1 = $cfgfile; 710 $file2 = "-"; 711 print_cfgfile (); 712} 713 714if ($action =~ /^d$/) { 715 # $file1 irrelevant 716 if (defined($opts{'l'})) { 717 print_datafile (); 718 } else { 719 $file1 = $datafile; 720 $file2 = "-"; 721 print_cfgfile (); 722 } 723} 724 725 726 727