~ubuntu-branches/ubuntu/karmic/sbuild/karmic-updates

« back to all changes in this revision

Viewing changes to bin/sbuild

  • Committer: Bazaar Package Importer
  • Author(s): Roger Leigh, Roger Leigh
  • Date: 2009-05-17 15:52:53 UTC
  • mfrom: (8.1.7 upstream) (3.1.4 sid)
  • Revision ID: james.westby@ubuntu.com-20090517155253-fbxadfsyaf940ete
Tags: 0.58.3-1
[ Roger Leigh ]
* New release.
* debian/control:
  - Update to Standards Version 3.8.1.
  - Add buildd package.
  - Add libsbuild-perl package.
  - All packages depend upon libsbuild-perl.
* Add support for appending a tag to version numbers (Closes: #475777).
  Thanks to Timothy G Abbott for this patch.
* When using the --help or --version options, don't abort if not
  in the sbuild group (Closes: #523670).  Group membership is now
  only performed after options parsing, and only if required.
* Allow config files to use $HOME (Closes: #524564).  Thanks to
  James Vega for this patch.
* Restore buildd package.
* Split common library functions into new libsbuild-perl package.
* debian/sbuild.(preinst|postinst|postrm):
  - Remove special cases for versions older than oldstable.  Update
    addition and removal of sbuild group to use return value of getent
    rather than parsing getent output.
  - Use addgroup/delgroup in place of adduser/deluser.
  - Use --system when adding and deleting group, to ensure creation
    of a system group.  Migrate existing non-system group and group
    members if the system group is not present.
  - Handle removal of 50sbuild setup script.
* debian/buildd.(preinst|postinst|postrm): Add maintainer scripts for
  buildd package.  Move configuration file from /etc/buildd.conf to
  /etc/buildd/buildd.conf if present.  Also create buildd user and
  group for running the buildd daemon.
* Sbuild::Conf: Don't default MAINTAINER_NAME to $DEBEMAIL if unset
  in the configuration file (Closes: #520158).
* /etc/schroot/setup.d/50sbuild: Remove.  The setup tasks performed by
  this script are now handled internally by sbuild.

Show diffs side-by-side

added added

removed removed

Lines of Context:
3
3
# sbuild: build packages, obeying source dependencies
4
4
# Copyright © 1998-2000 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
5
5
# Copyright © 2005      Ryan Murray <rmurray@debian.org>
6
 
# Copyright © 2005-2008 Roger Leigh <rleigh@debian.org
 
6
# Copyright © 2005-2009 Roger Leigh <rleigh@debian.org
7
7
# Copyright © 2008      Timothy G Abbott <tabbott@mit.edu>
8
8
# Copyright © 2008      Simon McVittie <smcv@debian.org>
9
9
#
23
23
#
24
24
#######################################################################
25
25
 
26
 
package conf;
27
 
 
28
 
use Sbuild::Conf;
29
 
 
30
 
 
31
26
package main;
32
27
 
33
28
use strict;
34
29
use warnings;
35
30
 
36
31
use POSIX;
37
 
use File::Basename qw(basename dirname);
38
 
use IO::Handle;
39
 
use FileHandle;
40
 
use Sbuild qw($devnull binNMU_version version_compare copy);
41
32
use Data::Dumper;
42
 
use File::Temp qw(tempdir);
43
 
use Sbuild::ChrootInfoSchroot;
44
 
use Sbuild::ChrootInfoSudo;
45
33
use Sbuild::Log qw(open_log close_log);
46
34
use Sbuild::Sysconfig qw(%programs);
47
35
use Sbuild::Options;
48
36
use Sbuild::Build;
49
37
 
50
38
sub main ();
 
39
sub write_jobs_file ();
 
40
sub append_to_FINISHED ($);
 
41
sub add_givenback ($$);
 
42
sub should_skip ($);
 
43
sub analyze_fail_stage ($);
51
44
sub shutdown ($);
52
 
sub check_group_membership ($);
53
45
sub dump_main_state ();
54
46
 
55
47
my $conf = Sbuild::Conf->new();
56
48
exit 1 if !defined($conf);
57
 
my $options = Sbuild::Options->new($conf);
 
49
my $options = Sbuild::Options->new($conf, "sbuild", "1");
58
50
exit 1 if !defined($options);
59
 
 
60
 
check_group_membership($conf);
 
51
$conf->check_group_membership();
61
52
 
62
53
umask(022);
63
54
 
64
 
$main::build_object = undef;
 
55
# Job state
 
56
my %jobs = ();
 
57
my $current_job = "";
65
58
 
66
59
main();
67
60
 
73
66
    print "Selected architecture " . $conf->get('ARCH') . "\n"
74
67
        if $conf->get('DEBUG' && defined($conf->get('ARCH')));
75
68
 
76
 
    $conf->set('MAILTO',
77
 
               $conf->get('MAILTO_HASH')->{$conf->get('DISTRIBUTION')})
78
 
        if $conf->get('MAILTO_HASH')->{$conf->get('DISTRIBUTION')};
79
 
 
80
 
# see debsign for priorities, we will follow the same order
81
 
    $conf->set('SIGNING_OPTIONS',
82
 
               "-m".$conf->get('MAINTAINER_NAME')."")
83
 
        if defined $conf->get('MAINTAINER_NAME');
84
 
    $conf->set('SIGNING_OPTIONS',
85
 
               "-e".$conf->get('UPLOADER_NAME')."")
86
 
        if defined $conf->get('UPLOADER_NAME');
87
 
    $conf->set('SIGNING_OPTIONS',
88
 
               "-k".$conf->get('KEY_ID')."")
89
 
        if defined $conf->get('KEY_ID');
90
 
    $conf->set('MAINTAINER_NAME', $conf->get('UPLOADER_NAME')) if defined $conf->get('UPLOADER_NAME');
91
 
    $conf->set('MAINTAINER_NAME', $conf->get('KEY_ID')) if defined $conf->get('KEY_ID');
92
 
 
93
 
    if (!defined($conf->get('MAINTAINER_NAME')) &&
94
 
        $conf->get('BIN_NMU')) {
95
 
        die "A maintainer name, uploader name or key ID must be specified in .sbuildrc,\nor use -m, -e or -k, when performing a binNMU\n";
 
69
    open_log($conf);
 
70
 
 
71
    $SIG{'INT'} = \&main::shutdown;
 
72
    $SIG{'TERM'} = \&main::shutdown;
 
73
    $SIG{'ALRM'} = \&main::shutdown;
 
74
    $SIG{'PIPE'} = \&main::shutdown;
 
75
 
 
76
    # Create jobs
 
77
    foreach (@ARGV) {
 
78
        $jobs{$_} = Sbuild::Build->new($_, $conf);
 
79
        $jobs{$_}->set('Pkg Status Trigger', \&write_jobs_file)
96
80
    }
97
 
 
98
 
# variables for scripts:
99
 
    open_log($conf->get('DISTRIBUTION'), $conf);
100
 
    $SIG{'INT'} = \&shutdown;
101
 
    $SIG{'TERM'} = \&shutdown;
102
 
    $SIG{'ALRM'} = \&shutdown;
103
 
    $SIG{'PIPE'} = \&shutdown;
104
 
 
105
 
    my $dscfile;
106
 
    foreach $dscfile (@ARGV) {
107
 
 
108
 
        # TODO: Append to build list, to allow parallel builds.
109
 
        my $build = Sbuild::Build->new($dscfile, $conf);
110
 
        $main::build_object = $build;
111
 
 
112
 
        $build->set('Pkg Start Time', time);
113
 
 
114
 
        $main::build_object->write_jobs_file("");
115
 
        $build->parse_manual_srcdeps(map { m,(?:.*/)?([^_/]+)[^/]*, } @ARGV);
116
 
 
117
 
        if ($build->get('Invalid Source')) {
118
 
            $build->log("Invalid source: $dscfile\n");
119
 
            $build->log("Skipping " . $build->get('Package') . " \n");
120
 
            $build->set('Pkg Status', 'skipped');
121
 
            goto cleanup_skip;
122
 
        }
123
 
 
124
 
        my $chroot_info;
125
 
        if ($conf->get('CHROOT_MODE') eq 'schroot') {
126
 
            $chroot_info = Sbuild::ChrootInfoSchroot->new($conf);
127
 
        } else {
128
 
            $chroot_info = Sbuild::ChrootInfoSudo->new($conf);
129
 
        }
130
 
 
131
 
        my $session = $chroot_info->create($conf->get('DISTRIBUTION'),
132
 
                                           $conf->get('CHROOT'),
133
 
                                           $conf->get('ARCH'));
134
 
 
135
 
        if (!$session->begin_session()) {
136
 
            $build->log("Error creating chroot session: skipping " .
137
 
                $build->get('Package') . "\n");
138
 
            $build->set('Pkg Status', 'skipped');
139
 
            goto cleanup_close;
140
 
        }
141
 
 
142
 
        $build->set('Session', $session);
143
 
        $build->set('Arch', $build->chroot_arch());
144
 
 
145
 
        $build->set('Chroot Dir', $session->get('Location'));
146
 
        $build->set('Chroot Build Dir',
147
 
                    tempdir($conf->get('USERNAME') . '-' .
148
 
                            $build->get('Package_SVersion') . '-' .
149
 
                            $build->get('Arch') . '-XXXXXX',
150
 
                            DIR => $session->get('Build Location')));
151
 
        # TODO: Don't hack the build location in; add a means to customise
152
 
        # the chroot directly.
153
 
        $session->set('Build Location', $build->get('Chroot Build Dir'));
154
 
 
155
 
        {
156
 
            my $tpkg = basename($build->get('Package_Version'));
157
 
            # TODO: This should be 'Pkg Start Time', set in build().
158
 
            my $date = strftime("%Y%m%d-%H%M",localtime);
159
 
 
160
 
            if ($conf->get('BIN_NMU')) {
161
 
                $tpkg =~ /^([^_]+)_([^_]+)(.*)$/;
162
 
                $tpkg = $1 . "_" . binNMU_version($2,$conf->get('BIN_NMU_VERSION'));
163
 
                $build->set('binNMU Name', $tpkg);
164
 
                $tpkg .= $3;
165
 
            }
166
 
 
167
 
            # TODO: Get package name from build object
168
 
            next if !$build->open_build_log($tpkg);
169
 
        }
170
 
 
171
 
        # Needed so chroot commands log to build log
172
 
        $session->set('Log Stream', $build->get('Log Stream'));
173
 
 
174
 
        # Chroot execution defaults
175
 
        my $chroot_defaults = $session->get('Defaults');
176
 
        $chroot_defaults->{'DIR'} =
177
 
            $session->strip_chroot_path($session->get('Build Location'));
178
 
        $chroot_defaults->{'STREAMIN'} = $devnull;
179
 
        $chroot_defaults->{'STREAMOUT'} = $build->get('Log Stream');
180
 
        $chroot_defaults->{'STREAMERR'} = $build->get('Log Stream');
181
 
        $chroot_defaults->{'ENV'}->{'LC_ALL'} = 'POSIX';
182
 
        $chroot_defaults->{'ENV'}->{'SHELL'} = $programs{'SHELL'};
183
 
 
184
 
        $build->set('Session', $session);
185
 
 
186
 
        $build->set('Pkg Status', 'failed'); # assume for now
187
 
        $main::current_job = $build->get('Package_Version');
188
 
        $build->set('Additional Deps', []);
189
 
        $main::build_object->write_jobs_file("currently building");
190
 
        if ($build->should_skip()) {
191
 
            $build->set('Pkg Status', 'skipped');
192
 
            goto cleanup_close;
193
 
        }
194
 
 
195
 
 
196
 
        # Update APT cache.
197
 
        if ($conf->get('APT_UPDATE')) {
198
 
            $session->run_apt_command(
199
 
                { COMMAND => [$conf->get('APT_GET'), 'update'],
200
 
                  USER => 'root',
201
 
                  PRIORITY => 1,
202
 
                  DIR => '/'});
203
 
 
204
 
            if ($?) {
205
 
                $build->log("apt-get update failed\n");
206
 
                $build->set('Pkg Status', 'skipped');
207
 
                goto cleanup_close;
208
 
            }
209
 
        }
210
 
 
211
 
        $build->set('Pkg Fail Stage', 'fetch-src');
212
 
        if (!$build->fetch_source_files()) {
213
 
            goto cleanup_close;
214
 
        }
215
 
 
216
 
        # Setup command
217
 
        if ($conf->get('SETUP_HOOK')) {
218
 
            my $pipe = $session->pipe_command({
219
 
                COMMAND => [$conf->get('SETUP_HOOK')],
220
 
                ENV => $build->get_env('SBUILD_BUILD_'),
221
 
                USER => "root",
222
 
                PRIORITY => 0,
223
 
                CHROOT => 1 });
224
 
            while(<$pipe>) {
225
 
                $build->log($_);
226
 
            }
227
 
            close($pipe);
228
 
            if ($?) {
229
 
                $build->log("setup-hook failed\n");
230
 
                $build->set('Pkg Status', 'skipped');
231
 
                goto cleanup_packages;
232
 
            }
233
 
        }
234
 
 
235
 
        $build->set('Pkg Fail Stage', 'install-deps');
236
 
        if (!$build->install_deps()) {
237
 
            $build->log("Source-dependencies not satisfied; skipping " .
238
 
                $build->get('Package') . "\n");
239
 
            goto cleanup_packages;
240
 
        }
241
 
 
242
 
        $build->set('Pkg Status', 'successful')
243
 
            if $build->build();
244
 
        $build->write_jobs_file($build->get('Pkg Status'));
245
 
        $build->append_to_FINISHED();
246
 
 
247
 
      cleanup_packages:
248
 
        if (defined ($session->get('Session Purged')) &&
249
 
            $session->get('Session Purged') == 1) {
250
 
            $build->log("Not removing build depends: cloned chroot in use\n");
251
 
        } else {
252
 
            $build->uninstall_deps();
253
 
        }
254
 
        $build->remove_srcdep_lock_file();
255
 
      cleanup_close:
256
 
        $build->analyze_fail_stage();
257
 
        $main::build_object->write_jobs_file($build->get('Pkg Status'));
258
 
 
259
 
        $session->end_session();
260
 
        $session = undef;
261
 
        $build->set('Session', undef);
262
 
 
263
 
        $build->close_build_log();
264
 
 
265
 
      cleanup_skip:
266
 
        $build->set('binNMU Name', undef);
267
 
        $main::current_job = "";
268
 
        if ($conf->get('BATCH_MODE') and (-f $conf->get('HOME') . '/EXIT-DAEMON-PLEASE') ) {
 
81
    write_jobs_file(); # Will now update on trigger.
 
82
 
 
83
    # Run each job.  Potential for parallelising this step.
 
84
    foreach (keys %jobs) {
 
85
        my $jobname = $_;
 
86
 
 
87
        my $job = $jobs{$jobname};
 
88
        $current_job = $jobname;
 
89
 
 
90
 
 
91
        # Do the build
 
92
        if (should_skip($job)) {
 
93
            $job->set('Pkg Status', 'skipped');
 
94
        } else {
 
95
            $job->run();
 
96
        }
 
97
 
 
98
        # Give back if build failed
 
99
        analyze_fail_stage($job);
 
100
 
 
101
        dump_main_state() if $conf->get('DEBUG');
 
102
 
 
103
        if ($conf->get('BATCH_MODE') &&
 
104
            (-f $conf->get('HOME') . '/EXIT-DAEMON-PLEASE')) {
269
105
            main::shutdown("NONE (flag file exit)");
270
106
        }
271
 
        dump_main_state() if $conf->get('DEBUG');
272
 
        $main::build_object->write_jobs_file("");
273
107
    }
274
108
 
275
109
    close_log($conf);
276
 
    unlink($main::build_object->get('Jobs File'))
 
110
    unlink($conf->get('JOB_FILE'))
277
111
        if $conf->get('BATCH_MODE');
278
112
    unlink("SBUILD-FINISHED") if $conf->get('BATCH_MODE');
279
 
    if ($conf->get('SBUILD_MODE') eq "user" && defined($main::build_object)) {
280
 
            exit ($main::build_object->get('Pkg Status') ne "successful") ? 1 : 0;
 
113
    if ($conf->get('SBUILD_MODE') eq "user" && defined($current_job) &&
 
114
        defined($jobs{$current_job})) {
 
115
        exit ($jobs{$current_job}->get('Pkg Status') ne "successful") ? 1 : 0;
281
116
    }
282
117
    exit 0;
283
118
}
284
119
 
 
120
# only called from main loop, but depends on job state.
 
121
sub write_jobs_file () {
 
122
    if ($conf->get('BATCH_MODE')) {
 
123
 
 
124
        my $file = $conf->get('JOB_FILE');
 
125
        local( *F );
 
126
 
 
127
        return if !open( F, ">$file" );
 
128
        foreach (keys %jobs) {
 
129
            my $job = $jobs{$_};
 
130
 
 
131
            print F $job->get('Package_OVersion') . ": " .
 
132
                $job->get('Pkg Status') . "\n";
 
133
        }
 
134
        close( F );
 
135
    }
 
136
}
 
137
 
 
138
sub append_to_FINISHED ($) {
 
139
    my $job = shift;
 
140
 
 
141
    local( *F );
 
142
 
 
143
    if ($conf->get('BATCH_MODE')) {
 
144
        open(F, ">>SBUILD-FINISHED");
 
145
        print F $job->get('Package_OVersion');
 
146
        close(F);
 
147
    }
 
148
}
 
149
 
 
150
sub add_givenback ($$) {
 
151
    my $build = shift;
 
152
    my $time = shift;
 
153
 
 
154
    if ($conf->get('BATCH_MODE')) {
 
155
        my $pkgv = $build->get('Package_OVersion');
 
156
        local( *F );
 
157
 
 
158
        $build->lock_file("SBUILD-GIVEN-BACK", 0);
 
159
 
 
160
        if (open( F, ">>SBUILD-GIVEN-BACK" )) {
 
161
            print F "$pkgv $time\n";
 
162
            close( F );
 
163
        }
 
164
        else {
 
165
            $build->log("Can't open SBUILD-GIVEN-BACK: $!\n");
 
166
        }
 
167
 
 
168
        $build->unlock_file("SBUILD-GIVEN-BACK");
 
169
    }
 
170
}
 
171
 
 
172
sub should_skip ($) {
 
173
    my $build = shift;
 
174
 
 
175
    if ($conf->get('BATCH_MODE')) {
 
176
        my $pkgv = $build->get('Package_OVersion');
 
177
 
 
178
        $pkgv = $build->fixup_pkgv($pkgv);
 
179
        $build->lock_file("SKIP", 0);
 
180
        goto unlock if !open( F, "SKIP" );
 
181
        my @pkgs = <F>;
 
182
        close( F );
 
183
 
 
184
        if (!open( F, ">SKIP" )) {
 
185
            print "Can't open SKIP for writing: $!\n",
 
186
            "Would write: @pkgs\nminus $pkgv\n";
 
187
            goto unlock;
 
188
        }
 
189
        my $found = 0;
 
190
        foreach (@pkgs) {
 
191
            if (/^\Q$pkgv\E$/) {
 
192
                ++$found;
 
193
                print "$pkgv found in SKIP file -- skipping building it\n";
 
194
            }
 
195
            else {
 
196
                print F $_;
 
197
            }
 
198
        }
 
199
        close( F );
 
200
      unlock:
 
201
        $build->unlock_file("SKIP");
 
202
        return $found;
 
203
        }
 
204
}
 
205
 
 
206
sub analyze_fail_stage ($) {
 
207
    my $build = shift;
 
208
 
 
209
    if ($conf->get('BATCH_MODE')) {
 
210
        my $pkgv = $build->get('Package_OVersion');
 
211
 
 
212
        return if $build->get('Pkg Status') ne "failed";
 
213
        return if !$build->get_conf('AUTO_GIVEBACK');
 
214
        if (isin( $build->get('Pkg Fail Stage'),
 
215
                  qw(find-dsc fetch-src unpack-check check-space install-deps-env))) {
 
216
            $build->set('Pkg Status', "given-back");
 
217
            $build->log("Giving back package $pkgv after failure in ".
 
218
                        "$build->{'Pkg Fail Stage'} stage.\n");
 
219
            my $cmd = "";
 
220
            $cmd = "ssh -l " . $build->get_conf('AUTO_GIVEBACK_USER') . " " .
 
221
                $build->get_conf('AUTO_GIVEBACK_HOST') . " "
 
222
                if $build->get_conf('AUTO_GIVEBACK_HOST');
 
223
            $cmd .= "-S " . $build->get_conf('AUTO_GIVEBACK_SOCKET') . " "
 
224
                if $build->get_conf('AUTO_GIVEBACK_SOCKET');
 
225
            $cmd .= "wanna-build --give-back --no-down-propagation ".
 
226
                "--dist=" . $build->get_conf('DISTRIBUTION') . " ";
 
227
            $cmd .= "--database=" . $build->get_conf('WANNABUILD_DATABASE') . " "
 
228
                if $build->get_conf('WANNABUILD_DATABASE');
 
229
            $cmd .= "--user=" . $build->get_conf('AUTO_GIVEBACK_WANNABUILD_USER') . " "
 
230
                if $build->get_conf('AUTO_GIVEBACK_WANNABUILD_USER');
 
231
            $cmd .= "$pkgv";
 
232
            system $cmd;
 
233
            if ($?) {
 
234
                $build->log("wanna-build failed with status $?\n");
 
235
            }
 
236
            else {
 
237
                $build->add_givenback($build, time);
 
238
                $build->write_stats('give-back', 1);
 
239
            }
 
240
        }
 
241
    }
 
242
}
 
243
 
285
244
sub shutdown ($) {
286
245
    my $signame = shift;
287
 
    my($job,@npkgs,@pkgs);
 
246
    my(@npkgs,@pkgs);
288
247
    local( *F );
289
248
 
290
249
    $SIG{'INT'} = 'IGNORE';
292
251
    $SIG{'TERM'} = 'IGNORE';
293
252
    $SIG{'ALRM'} = 'IGNORE';
294
253
    $SIG{'PIPE'} = 'IGNORE';
295
 
    $main::build_object->log("sbuild received SIG$signame -- shutting down\n");
296
 
 
297
 
    goto not_ni_shutdown if !$conf->get('BATCH_MODE');
298
 
 
299
 
    # most important: dump out names of unfinished jobs to REDO
300
 
    foreach $job (@ARGV) {
301
 
        my $job2 = $job;
302
 
        $job2 = $main::build_object->fixup_pkgv($job2);
303
 
        push( @npkgs, $job2 )
304
 
            if !$main::job_state{$job} || $job eq $main::current_job;
305
 
    }
306
 
    print LOG "The following jobs were not finished: @npkgs\n";
307
 
 
308
 
    my $f = "REDO";
309
 
    if (-f "REDO.lock") {
310
 
        # if lock file exists, write to a different file -- timing may
311
 
        # be critical
312
 
        $f = "REDO2";
313
 
    }
314
 
    if (open( F, "<$f" )) {
315
 
        @pkgs = <F>;
316
 
        close( F );
317
 
    }
318
 
    if (open( F, ">>$f" )) {
319
 
        foreach $job (@npkgs) {
320
 
            next if grep( /^\Q$job\E\s/, @pkgs );
321
 
            if (not defined $main::build_object->get_conf('BIN_NMU_VERSION')) {
322
 
                print F "$job " .
323
 
                    $main::build_object->get_conf('DISTRIBUTION') . "\n";
324
 
            } else {
325
 
                print F "$job " .
326
 
                    $main::build_object->get_conf('DISTRIBUTION')
327
 
                    . " " .
328
 
                    $main::build_object->get_conf('BIN_NMU_VERSION')
329
 
                    . " " .
330
 
                    $main::build_object->get_conf('BIN_NMU') . "\n";
331
 
            }
332
 
        }
333
 
        close( F );
334
 
    }
335
 
    else {
336
 
        print "Cannot open $f: $!\n";
337
 
    }
338
 
    open( F, ">SBUILD-REDO-DUMPED" );
339
 
    close( F );
340
 
    print LOG "SBUILD-REDO-DUMPED created\n";
341
 
    unlink( "SBUILD-FINISHED" );
342
 
 
343
 
    # next: say which packages should be uninstalled
344
 
    @pkgs = keys %{$main::build_object->get('Changes')->{'installed'}};
345
 
    if (@pkgs) {
346
 
        if (open( F, ">>NEED-TO-UNINSTALL" )) {
347
 
            print F "@pkgs\n";
348
 
            close( F );
349
 
        }
350
 
        print "The following packages still need to be uninstalled ",
351
 
        "(--purge):\n@pkgs\n";
352
 
    }
353
 
 
354
 
  not_ni_shutdown:
355
 
    # next: kill currently running command (if one)
356
 
    if ($main::build_object->get('Sub PID')) {
357
 
        print "Killing " . $main::build_object->get('Sub Task') .
358
 
            " subprocess " . $main::build_object->get('Sub PID') . "\n";
359
 
        $main::build_object->get('Session')->run_command(
360
 
                { COMMAND => ['perl', '-e',
361
 
                              "\"kill( \\\"TERM\\\", " .
362
 
                              $main::build_object->get('Sub PID') .
363
 
                              " )\""],
364
 
                  USER => 'root',
365
 
                  CHROOT => 1,
366
 
                  PRIORITY => 0,
367
 
                  DIR => '/' });
368
 
    }
369
 
    $main::build_object->remove_srcdep_lock_file();
370
 
 
371
 
    # close logs and send mails
372
 
    if ( $main::current_job && defined($main::build_object->get('Session'))) {
 
254
 
 
255
    $jobs{$current_job}->log("sbuild received SIG$signame -- shutting down\n");
 
256
 
 
257
    if ($conf->get('BATCH_MODE')) {
 
258
 
 
259
        # Dump names of unfinished jobs to REDO
 
260
        foreach (keys %jobs) {
 
261
            my $job = $jobs{$_};
 
262
 
 
263
            push(@npkgs, $job->get('Package_OVersion'))
 
264
                if $job->get('Pkg Status') ne "successful";
 
265
        }
 
266
        print "The following jobs were not finished: @npkgs\n";
 
267
 
 
268
        my $f = "REDO";
 
269
        if (-f "REDO.lock") {
 
270
            # if lock file exists, write to a different file -- timing may
 
271
            # be critical
 
272
            $f = "REDO2";
 
273
        }
 
274
        if (open(F, "<$f")) {
 
275
            @pkgs = <F>;
 
276
            close(F);
 
277
        }
 
278
        if (open(F, ">>$f")) {
 
279
            foreach (@npkgs) {
 
280
                next if grep( /^\Q$_\E\s/, @pkgs );
 
281
                print F "$_ " .
 
282
                    $jobs{$current_job}->get_conf('DISTRIBUTION');
 
283
                print F " " . $jobs{$current_job}->get_conf('BIN_NMU_VERSION')
 
284
                    . " " . $jobs{$current_job}->get_conf('BIN_NMU')
 
285
                    if (defined $jobs{$current_job}->get_conf('BIN_NMU_VERSION'));
 
286
                print F "\n";
 
287
            }
 
288
            close(F);
 
289
        }
 
290
        else {
 
291
            print "Cannot open $f: $!\n";
 
292
        }
 
293
        open(F, ">SBUILD-REDO-DUMPED");
 
294
        close(F);
 
295
        print "SBUILD-REDO-DUMPED created\n";
 
296
 
 
297
        unlink("SBUILD-FINISHED");
 
298
 
 
299
        # next: say which packages should be uninstalled
 
300
        @pkgs = keys %{$jobs{$current_job}->get('Changes')->{'installed'}};
 
301
        if (@pkgs) {
 
302
            if (open( F, ">>NEED-TO-UNINSTALL" )) {
 
303
                print F "@pkgs\n";
 
304
                close( F );
 
305
            }
 
306
            print "The following packages still need to be uninstalled ",
 
307
            "(--purge):\n@pkgs\n";
 
308
        }
 
309
    }
 
310
 
 
311
    # Kill currently running command (if any)
 
312
    if ($jobs{$current_job}->get('Sub PID')) {
 
313
        print "Killing " . $jobs{$current_job}->get('Sub Task') .
 
314
            " subprocess " . $jobs{$current_job}->get('Sub PID') . "\n";
 
315
        $jobs{$current_job}->get('Session')->run_command(
 
316
            { COMMAND => ['perl', '-e',
 
317
                          "\"kill( \\\"TERM\\\", " .
 
318
                          $jobs{$current_job}->get('Sub PID') .
 
319
                          " )\""],
 
320
                          USER => 'root',
 
321
                          CHROOT => 1,
 
322
                          PRIORITY => 0,
 
323
                          DIR => '/' });
 
324
    }
 
325
    $jobs{$current_job}->remove_srcdep_lock_file();
 
326
 
 
327
    # Close logs and send mails
 
328
    if ( $current_job && defined($jobs{$current_job}->get('Session'))) {
373
329
        if ($conf->get('PURGE_BUILD_DIRECTORY') eq "always") {
374
 
            $main::build_object->log("Purging " . $main::build_object->get('Chroot Build Dir') . "\n");
375
 
            my $bdir = $main::build_object->get('Session')->strip_chroot_path($main::build_object->get('Chroot Build Dir'));
376
 
            $main::build_object->get('Session')->run_command(
 
330
            $jobs{$current_job}->log("Purging " . $jobs{$current_job}->get('Chroot Build Dir') . "\n");
 
331
            my $bdir = $jobs{$current_job}->get('Session')->strip_chroot_path($jobs{$current_job}->get('Chroot Build Dir'));
 
332
            $jobs{$current_job}->get('Session')->run_command(
377
333
                { COMMAND => [$Sbuild::Sysconfig::programs{'RM'},
378
334
                              '-rf', $bdir],
379
335
                  USER => 'root',
382
338
                  DIR => '/' });
383
339
        }
384
340
 
385
 
        $main::current_job =
386
 
            $main::build_object->fixup_pkgv($main::current_job);
387
 
 
388
 
        $main::build_object->get('Session')->end_session();
389
 
        $main::build_object->set('Session', undef);
390
 
 
391
 
        $main::build_object->close_build_log();
392
 
        $main::build_object->set('binNMU Name', undef);
 
341
        $current_job =
 
342
            $jobs{$current_job}->fixup_pkgv($current_job);
 
343
 
 
344
        $jobs{$current_job}->get('Session')->end_session();
 
345
        $jobs{$current_job}->set('Session', undef);
 
346
 
 
347
        $jobs{$current_job}->close_build_log();
 
348
        $jobs{$current_job}->set('binNMU Name', undef);
393
349
    }
394
350
    close_log($conf);
395
 
    unlink( $main::build_object->get('Jobs File') ) if $conf->get('BATCH_MODE');
 
351
    unlink( $jobs{$current_job}->get('Jobs File') ) if $conf->get('BATCH_MODE');
396
352
    $? = 0; $! = 0;
397
353
    if ($conf->get('SBUILD_MODE') eq "user") {
398
354
        exit 1;
400
356
    exit 0;
401
357
}
402
358
 
403
 
sub check_group_membership ($) {
404
 
    my $conf = shift;
405
 
 
406
 
    my $user = getpwuid($<);
407
 
    my ($name,$passwd,$gid,$members) = getgrnam("sbuild");
408
 
 
409
 
    if (!$gid) {
410
 
        die "Group sbuild does not exist";
411
 
    }
412
 
 
413
 
    my $in_group = 0;
414
 
    foreach (split(' ', $members)) {
415
 
        $in_group = 1 if $_ eq $conf->get('USERNAME');
416
 
    }
417
 
 
418
 
    if (!$in_group) {
419
 
        print STDERR "User $user is not a member of group $name\n";
420
 
        print STDERR "See \"User Setup\" in sbuild-setup(7)\n";
421
 
        exit(1);
422
 
    }
423
 
 
424
 
    return;
425
 
}
426
 
 
427
359
sub dump_main_state () {
428
 
    print STDERR Data::Dumper->Dump([$main::build_object,
429
 
                                     $main::current_job,
430
 
                                     \%main::job_state],
431
 
                                    [qw($main::build_object
432
 
                                        $main::current_job
433
 
                                        %main::job_state)] );
 
360
    print STDERR Data::Dumper->Dump([$current_job,
 
361
                                     \%jobs],
 
362
                                    [qw($current_job
 
363
                                        %jobs)] );
434
364
}
435
365
 
436
366
# avoid intermixing of stdout and stderr