controllib.pl 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. $parsechangelog= 'dpkg-parsechangelog';
  2. grep($capit{lc $_}=$_, qw(Pre-Depends Standards-Version Installed-Size));
  3. $substvar{'Format'}= 1.5;
  4. $substvar{'Newline'}= "\n";
  5. $substvar{'Space'}= " ";
  6. $substvar{'Tab'}= "\t";
  7. $maxsubsts=50;
  8. $progname= $0; $progname= $& if $progname =~ m,[^/]+$,;
  9. sub capit {
  10. return defined($capit{lc $_[0]}) ? $capit{lc $_[0]} :
  11. (uc substr($_[0],0,1)).(lc substr($_[0],1));
  12. }
  13. sub findarch {
  14. $arch=`dpkg --print-architecture`;
  15. $? && &subprocerr("dpkg --print-archictecture");
  16. $arch =~ s/\n$//;
  17. $substvar{'Arch'}= $arch;
  18. }
  19. sub substvars {
  20. my ($v) = @_;
  21. my $lhs,$vn,$rhs,$count;
  22. $count=0;
  23. while ($v =~ m/\$\{([-:0-9a-z]+)\}/i) {
  24. $count < $maxsubsts ||
  25. &error("too many substitutions - recursive ? - in \`$v'");
  26. $lhs=$`; $vn=$1; $rhs=$';
  27. if (defined($substvar{$vn})) {
  28. $v= $lhs.$substvar{$vn}.$rhs;
  29. $count++;
  30. } else {
  31. &warn("unknown substitution variable \${$vn}");
  32. $v= $lhs.$rhs;
  33. }
  34. }
  35. return $v;
  36. }
  37. sub outputclose {
  38. for $f (keys %f) { $substvar{"F:$f"}= $f{$f}; }
  39. if (length($varlistfile)) {
  40. $varlistfile="./$varlistfile" if $varlistfile =~ m/\s/;
  41. if (open(SV,"< $varlistfile")) {
  42. while (<SV>) {
  43. next if m/^\#/ || !m/\S/;
  44. s/\s*\n$//;
  45. m/^(\w[-:0-9A-Za-z]*)\=/ ||
  46. &error("bad line in substvars file $varlistfile at line $.");
  47. $substvar{$1}= $';
  48. }
  49. close(SV);
  50. } elsif ($! !~ m/no such file or directory/i) {
  51. &error("unable to open substvars file $varlistvile: $!");
  52. }
  53. }
  54. for $f (sort { $fieldimps{$b} <=> $fieldimps{$a} } keys %f) {
  55. $v= $f{$f};
  56. $v= &substvars($v);
  57. $v =~ m/\S/ || next; # delete whitespace-only fields
  58. $v =~ m/\n\S/ && &internerr("field $f has newline then non whitespace >$v<");
  59. $v =~ m/\n[ \t]*\n/ && &internerr("field $f has blank lines >$v<");
  60. $v =~ m/\n$/ && &internerr("field $f has trailing newline >$v<");
  61. $v =~ s/\$\{\}/\$/g;
  62. print("$f: $v\n") || &syserr("write error on control data");
  63. }
  64. close(STDOUT) || &syserr("write error on close control data");
  65. }
  66. sub parsecontrolfile {
  67. $controlfile="./$controlfile" if $controlfile =~ m/^\s/;
  68. open(CDATA,"< $controlfile") || &error("cannot read control file $controlfile: $!");
  69. $indices= &parsecdata('C',1,"control file $controlfile");
  70. $indices >= 2 || &error("control file must have at least one binary package part");
  71. for ($i=1;$i<$indices;$i++) {
  72. defined($fi{"C$i Package"}) ||
  73. &error("per-package paragraph $i in control info file is ".
  74. "missing Package line");
  75. }
  76. }
  77. sub parsechangelog {
  78. defined($c=open(CDATA,"-|")) || &syserr("fork for parse changelog");
  79. if (!$c) {
  80. @al=($parsechangelog);
  81. push(@al,"-F$changelogformat") if length($changelogformat);
  82. push(@al,"-v$since") if length($since);
  83. push(@al,"-l$changelogfile");
  84. exec(@al) || &syserr("exec parsechangelog $parsechangelog");
  85. }
  86. &parsecdata('L',0,"parsed version of changelog");
  87. close(CDATA); $? && &subprocerr("parse changelog");
  88. $substvar{'Source-Version'}= $fi{"L Version"};
  89. }
  90. sub setsourcepackage {
  91. if (length($sourcepackage)) {
  92. $v eq $sourcepackage ||
  93. &error("source package has two conflicting values - $sourcepackage and $v");
  94. } else {
  95. $sourcepackage= $v;
  96. }
  97. }
  98. sub parsecdata {
  99. local ($source,$many,$whatmsg) = @_;
  100. # many=0: ordinary control data like output from dpkg-parsechangelog
  101. # many=1: many paragraphs like in source control file
  102. # many=-1: single paragraph of control data optionally signed
  103. local ($index,$cf);
  104. $index=''; $cf='';
  105. while (<CDATA>) {
  106. s/\s*\n$//;
  107. if (m/^(\S+)\s*:\s*(.*)$/) {
  108. $cf=$1; $v=$2;
  109. $cf= &capit($cf);
  110. $fi{"$source$index $cf"}= $v;
  111. if (lc $cf eq 'package') { $p2i{"$source $v"}= $index; }
  112. } elsif (m/^\s+\S/) {
  113. length($cf) || &syntax("continued value line not in field");
  114. $fi{"$source$index $cf"}.= "\n$_";
  115. } elsif (m/^-----BEGIN PGP/ && $many<0) {
  116. while (<CDATA>) { last if m/^$/; }
  117. $many= -2;
  118. } elsif (m/^$/) {
  119. if ($many>0) {
  120. $index++; $cf='';
  121. } elsif ($many == -2) {
  122. $_= <CDATA>;
  123. length($_) ||
  124. &syntax("expected PGP signature, found EOF after blank line");
  125. s/\n$//;
  126. m/^-----BEGIN PGP/ ||
  127. &syntax("expected PGP signature, found something else \`$_'");
  128. $many= -3; last;
  129. } else {
  130. &syntax("found several \`paragraphs' where only one expected");
  131. }
  132. } else {
  133. &syntax("line with unknown format (not field-colon-value)");
  134. }
  135. }
  136. $many == -2 && &syntax("found start of PGP body but no signature");
  137. if (length($cf)) { $index++; }
  138. $index || &syntax("empty file");
  139. return $index;
  140. }
  141. sub unknown {
  142. &warn("unknown information field $_ in input data in $_[0]");
  143. }
  144. sub syntax {
  145. &error("syntax error in $whatmsg at line $.: $_[0]");
  146. }
  147. sub failure { die "$progname: failure: $_[0]\n"; }
  148. sub syserr { die "$progname: failure: $_[0]: $!\n"; }
  149. sub error { die "$progname: error: $_[0]\n"; }
  150. sub internerr { die "$progname: internal error: $_[0]\n"; }
  151. sub warn { warn "$progname: warning: $_[0]\n"; }
  152. sub usageerr { print(STDERR "$progname: @_\n\n"); &usageversion; exit(2); }
  153. sub subprocerr {
  154. local ($p) = @_;
  155. if (WIFEXITED($?)) {
  156. die "$progname: failure: $p gave error exit status ".WEXITSTATUS($?)."\n";
  157. } elsif (WIFSIGNALED($?)) {
  158. die "$progname: failure: $p died from signal ".WTERMSIG($?)."\n";
  159. } else {
  160. die "$progname: failure: $p failed with unknown exit code $?\n";
  161. }
  162. }
  163. 1;