2 * libdpkg - Debian packaging suite library routines
3 * subproc.c - subprocess helper routines
5 * Copyright © 1995 Ian Jackson <ijackson@chiark.greenend.org.uk>
6 * Copyright © 2008-2014 Guillem Jover <guillem@debian.org>
8 * This is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
25 #include <sys/types.h>
35 #include <dpkg/i18n.h>
36 #include <dpkg/dpkg.h>
37 #include <dpkg/subproc.h>
39 static int signo_ignores
[] = { SIGQUIT
, SIGINT
};
40 static struct sigaction sa_save
[array_count(signo_ignores
)];
43 subproc_reset_signal(int sig
, struct sigaction
*sa_old
)
45 if (sigaction(sig
, sa_old
, NULL
)) {
46 fprintf(stderr
, _("error un-catching signal %s: %s\n"),
47 strsignal(sig
), strerror(errno
));
53 subproc_set_signal(int sig
, struct sigaction
*sa
, struct sigaction
*sa_old
,
56 if (sigaction(sig
, sa
, sa_old
))
57 ohshite(_("unable to ignore signal %s before running %.250s"),
58 strsignal(sig
), name
);
62 subproc_signals_ignore(const char *name
)
68 memset(&sa
, 0, sizeof(sa
));
69 sigemptyset(&sa
.sa_mask
);
70 sa
.sa_handler
= SIG_IGN
;
73 for (i
= 0; i
< array_count(signo_ignores
); i
++)
74 subproc_set_signal(signo_ignores
[i
], &sa
, &sa_save
[i
], name
);
76 push_cleanup(subproc_signals_cleanup
, ~0, 0);
81 subproc_signals_cleanup(int argc
, void **argv
)
85 for (i
= 0; i
< array_count(signo_ignores
); i
++)
86 subproc_reset_signal(signo_ignores
[i
], &sa_save
[i
]);
90 subproc_signals_restore(void)
92 pop_cleanup(ehflag_normaltidy
);
96 print_subproc_error(const char *emsg
, const void *data
)
98 fprintf(stderr
, _("%s (subprocess): %s\n"), dpkg_get_progname(), emsg
);
109 ohshite(_("fork failed"));
114 /* Push a new error context, so that we don't do the other cleanups,
115 * because they'll be done by/in the parent process. */
116 push_error_context_func(catch_fatal_error
, print_subproc_error
, NULL
);
122 subproc_check(int status
, const char *desc
, enum subproc_flags flags
)
124 void (*out
)(const char *fmt
, ...) DPKG_ATTR_PRINTF(1);
127 if (flags
& SUBPROC_WARN
)
132 if (WIFEXITED(status
)) {
133 n
= WEXITSTATUS(status
);
136 if (flags
& SUBPROC_RETERROR
)
139 out(_("%s subprocess returned error exit status %d"), desc
, n
);
140 } else if (WIFSIGNALED(status
)) {
141 n
= WTERMSIG(status
);
144 if ((flags
& SUBPROC_NOPIPE
) && n
== SIGPIPE
)
146 if (flags
& SUBPROC_RETSIGNO
)
150 out(_("%s subprocess was interrupted"), desc
);
152 out(_("%s subprocess was killed by signal (%s)%s"),
154 WCOREDUMP(status
) ? _(", core dumped") : "");
156 if (flags
& SUBPROC_RETERROR
)
159 out(_("%s subprocess failed with wait status code %d"), desc
,
167 subproc_wait(pid_t pid
, const char *desc
)
172 while ((dead_pid
= waitpid(pid
, &status
, 0)) == -1 && errno
== EINTR
) ;
174 if (dead_pid
!= pid
) {
176 ohshite(_("wait for %s subprocess failed"), desc
);
183 subproc_reap(pid_t pid
, const char *desc
, enum subproc_flags flags
)
187 status
= subproc_wait(pid
, desc
);
189 if (flags
& SUBPROC_NOCHECK
)
192 rc
= subproc_check(status
, desc
, flags
);