libdpkg: Deindent an else clause
[dpkg.git] / src / main / script.c
blobb4f369dfa25ea248cdf34b2349cc61abfa74b395
1 /*
2 * dpkg - main program for package management
3 * script.c - maintainer script routines
5 * Copyright © 1995 Ian Jackson <ijackson@chiark.greenend.org.uk>
6 * Copyright © 2007-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/>.
22 #include <config.h>
23 #include <compat.h>
25 #include <sys/types.h>
26 #include <sys/stat.h>
28 #include <errno.h>
29 #include <string.h>
30 #include <unistd.h>
31 #include <stdlib.h>
33 #ifdef WITH_LIBSELINUX
34 #include <selinux/selinux.h>
35 #endif
37 #include <dpkg/i18n.h>
38 #include <dpkg/debug.h>
39 #include <dpkg/dpkg.h>
40 #include <dpkg/dpkg-db.h>
41 #include <dpkg/pkg.h>
42 #include <dpkg/subproc.h>
43 #include <dpkg/command.h>
44 #include <dpkg/triglib.h>
45 #include <dpkg/db-ctrl.h>
46 #include <dpkg/db-fsys.h>
48 #include "main.h"
50 void
51 post_postinst_tasks(struct pkginfo *pkg, enum pkgstatus new_status)
53 if (new_status < PKG_STAT_TRIGGERSAWAITED)
54 pkg_set_status(pkg, new_status);
55 else if (pkg->trigaw.head)
56 pkg_set_status(pkg, PKG_STAT_TRIGGERSAWAITED);
57 else if (pkg->trigpend_head)
58 pkg_set_status(pkg, PKG_STAT_TRIGGERSPENDING);
59 else
60 pkg_set_status(pkg, PKG_STAT_INSTALLED);
61 modstatdb_note(pkg);
63 debug(dbg_triggersdetail, "post_postinst_tasks - trig_incorporate");
64 trig_incorporate(modstatdb_get_status());
67 static void
68 post_script_tasks(void)
70 debug(dbg_triggersdetail, "post_script_tasks - ensure_diversions");
71 ensure_diversions();
73 debug(dbg_triggersdetail, "post_script_tasks - trig_incorporate");
74 trig_incorporate(modstatdb_get_status());
77 static void
78 cu_post_script_tasks(int argc, void **argv)
80 post_script_tasks();
83 static void
84 setexecute(const char *path, struct stat *stab)
86 if ((stab->st_mode & 0555) == 0555)
87 return;
88 if (!chmod(path, 0755))
89 return;
90 ohshite(_("unable to set execute permissions on '%.250s'"), path);
93 /**
94 * Returns the path to the script inside the chroot.
96 static const char *
97 maintscript_pre_exec(struct command *cmd)
99 const char *instdir = dpkg_fsys_get_dir();
100 const char *admindir = dpkg_db_get_dir();
101 const char *changedir;
102 size_t instdirlen = strlen(instdir);
104 if (instdirlen > 0 && in_force(FORCE_SCRIPT_CHROOTLESS))
105 changedir = instdir;
106 else
107 changedir = "/";
109 if (instdirlen > 0 && !in_force(FORCE_SCRIPT_CHROOTLESS)) {
110 int rc;
112 if (strncmp(admindir, instdir, instdirlen) != 0)
113 ohshit(_("admindir must be inside instdir for dpkg to work properly"));
114 if (setenv("DPKG_ADMINDIR", admindir + instdirlen, 1) < 0)
115 ohshite(_("unable to setenv for subprocesses"));
116 if (setenv("DPKG_ROOT", "", 1) < 0)
117 ohshite(_("unable to setenv for subprocesses"));
119 rc = chroot(instdir);
120 if (rc && in_force(FORCE_NON_ROOT) && errno == EPERM)
121 ohshit(_("not enough privileges to change root "
122 "directory with --force-not-root, consider "
123 "using --force-script-chrootless?"));
124 else if (rc)
125 ohshite(_("failed to chroot to '%.250s'"), instdir);
127 /* Switch to a known good directory to give the maintainer script
128 * a saner environment, also needed after the chroot(). */
129 if (chdir(changedir))
130 ohshite(_("failed to chdir to '%.255s'"), changedir);
131 if (debug_has_flag(dbg_scripts)) {
132 struct varbuf args = VARBUF_INIT;
133 const char **argv = cmd->argv;
135 while (*++argv) {
136 varbuf_add_char(&args, ' ');
137 varbuf_add_str(&args, *argv);
139 varbuf_end_str(&args);
140 debug(dbg_scripts, "fork/exec %s (%s )", cmd->filename,
141 args.buf);
142 varbuf_destroy(&args);
144 if (instdirlen == 0 || in_force(FORCE_SCRIPT_CHROOTLESS))
145 return cmd->filename;
147 if (strlen(cmd->filename) < instdirlen)
148 internerr("maintscript name '%s' length < instdir length %zd",
149 cmd->filename, instdirlen);
151 return cmd->filename + instdirlen;
155 * Set a new security execution context for the maintainer script.
157 * Try to create a new execution context based on the current one and the
158 * specific maintainer script filename. If it's the same as the current
159 * one, use the given fallback.
161 static int
162 maintscript_set_exec_context(struct command *cmd)
164 #ifdef WITH_LIBSELINUX
165 return setexecfilecon(cmd->filename, "dpkg_script_t");
166 #else
167 return 0;
168 #endif
171 static int
172 maintscript_exec(struct pkginfo *pkg, struct pkgbin *pkgbin,
173 struct command *cmd, struct stat *stab, int warn)
175 pid_t pid;
176 int rc;
178 setexecute(cmd->filename, stab);
180 push_cleanup(cu_post_script_tasks, ehflag_bombout, 0);
182 pid = subproc_fork();
183 if (pid == 0) {
184 char *pkg_count;
185 const char *maintscript_debug;
187 pkg_count = str_fmt("%d", pkgset_installed_instances(pkg->set));
189 maintscript_debug = debug_has_flag(dbg_scripts) ? "1" : "0";
191 if (setenv("DPKG_MAINTSCRIPT_PACKAGE", pkg->set->name, 1) ||
192 setenv("DPKG_MAINTSCRIPT_PACKAGE_REFCOUNT", pkg_count, 1) ||
193 setenv("DPKG_MAINTSCRIPT_ARCH", pkgbin->arch->name, 1) ||
194 setenv("DPKG_MAINTSCRIPT_NAME", cmd->argv[0], 1) ||
195 setenv("DPKG_MAINTSCRIPT_DEBUG", maintscript_debug, 1) ||
196 setenv("DPKG_RUNNING_VERSION", PACKAGE_VERSION, 1))
197 ohshite(_("unable to setenv for maintainer script"));
199 cmd->filename = cmd->argv[0] = maintscript_pre_exec(cmd);
201 if (maintscript_set_exec_context(cmd) < 0)
202 ohshite(_("cannot set security execution context for "
203 "maintainer script"));
205 command_exec(cmd);
207 subproc_signals_ignore(cmd->name);
208 rc = subproc_reap(pid, cmd->name, warn);
209 subproc_signals_restore();
211 pop_cleanup(ehflag_normaltidy);
213 return rc;
216 static int
217 vmaintscript_installed(struct pkginfo *pkg, const char *scriptname,
218 const char *desc, va_list args)
220 struct command cmd;
221 const char *scriptpath;
222 struct stat stab;
223 char *buf;
225 scriptpath = pkg_infodb_get_file(pkg, &pkg->installed, scriptname);
226 m_asprintf(&buf, _("installed %s package %s script"),
227 pkg_name(pkg, pnaw_nonambig), desc);
229 command_init(&cmd, scriptpath, buf);
230 command_add_arg(&cmd, scriptname);
231 command_add_argv(&cmd, args);
233 if (stat(scriptpath, &stab)) {
234 command_destroy(&cmd);
236 if (errno == ENOENT) {
237 debug(dbg_scripts,
238 "vmaintscript_installed nonexistent %s",
239 scriptname);
240 free(buf);
241 return 0;
243 ohshite(_("unable to stat %s '%.250s'"), buf, scriptpath);
245 maintscript_exec(pkg, &pkg->installed, &cmd, &stab, 0);
247 command_destroy(&cmd);
248 free(buf);
250 return 1;
254 * All ...'s in maintscript_* are const char *'s.
258 maintscript_installed(struct pkginfo *pkg, const char *scriptname,
259 const char *desc, ...)
261 va_list args;
262 int rc;
264 va_start(args, desc);
265 rc = vmaintscript_installed(pkg, scriptname, desc, args);
266 va_end(args);
268 if (rc)
269 post_script_tasks();
271 return rc;
275 maintscript_postinst(struct pkginfo *pkg, ...)
277 va_list args;
278 int rc;
280 va_start(args, pkg);
281 rc = vmaintscript_installed(pkg, POSTINSTFILE, "post-installation", args);
282 va_end(args);
284 if (rc)
285 ensure_diversions();
287 return rc;
291 maintscript_new(struct pkginfo *pkg, const char *scriptname,
292 const char *desc, const char *cidir, char *cidirrest, ...)
294 struct command cmd;
295 struct stat stab;
296 va_list args;
297 char *buf;
299 strcpy(cidirrest, scriptname);
300 m_asprintf(&buf, _("new %s package %s script"),
301 pkg_name(pkg, pnaw_nonambig), desc);
303 va_start(args, cidirrest);
304 command_init(&cmd, cidir, buf);
305 command_add_arg(&cmd, scriptname);
306 command_add_argv(&cmd, args);
307 va_end(args);
309 if (stat(cidir, &stab)) {
310 command_destroy(&cmd);
312 if (errno == ENOENT) {
313 debug(dbg_scripts,
314 "maintscript_new nonexistent %s '%s'",
315 scriptname, cidir);
316 free(buf);
317 return 0;
319 ohshite(_("unable to stat %s '%.250s'"), buf, cidir);
321 maintscript_exec(pkg, &pkg->available, &cmd, &stab, 0);
323 command_destroy(&cmd);
324 free(buf);
325 post_script_tasks();
327 return 1;
331 maintscript_fallback(struct pkginfo *pkg,
332 const char *scriptname, const char *desc,
333 const char *cidir, char *cidirrest,
334 const char *ifok, const char *iffallback)
336 struct command cmd;
337 const char *oldscriptpath;
338 struct stat stab;
339 char *buf;
341 oldscriptpath = pkg_infodb_get_file(pkg, &pkg->installed, scriptname);
342 m_asprintf(&buf, _("old %s package %s script"),
343 pkg_name(pkg, pnaw_nonambig), desc);
345 command_init(&cmd, oldscriptpath, buf);
346 command_add_args(&cmd, scriptname, ifok,
347 versiondescribe(&pkg->available.version, vdew_nonambig),
348 NULL);
350 if (stat(oldscriptpath, &stab)) {
351 if (errno == ENOENT) {
352 debug(dbg_scripts,
353 "maintscript_fallback nonexistent %s '%s'",
354 scriptname, oldscriptpath);
355 command_destroy(&cmd);
356 free(buf);
357 return 0;
359 warning(_("unable to stat %s '%.250s': %s"),
360 cmd.name, oldscriptpath, strerror(errno));
361 } else {
362 if (!maintscript_exec(pkg, &pkg->installed, &cmd, &stab, SUBPROC_WARN)) {
363 command_destroy(&cmd);
364 free(buf);
365 post_script_tasks();
366 return 1;
369 notice(_("trying script from the new package instead ..."));
371 strcpy(cidirrest, scriptname);
372 m_asprintf(&buf, _("new %s package %s script"),
373 pkg_name(pkg, pnaw_nonambig), desc);
375 command_destroy(&cmd);
376 command_init(&cmd, cidir, buf);
377 command_add_args(&cmd, scriptname, iffallback,
378 versiondescribe(&pkg->installed.version, vdew_nonambig),
379 versiondescribe(&pkg->available.version, vdew_nonambig),
380 NULL);
382 if (stat(cidir, &stab)) {
383 command_destroy(&cmd);
385 if (errno == ENOENT)
386 ohshit(_("there is no script in the new version of the package - giving up"));
387 else
388 ohshite(_("unable to stat %s '%.250s'"), buf, cidir);
391 maintscript_exec(pkg, &pkg->available, &cmd, &stab, 0);
392 notice(_("... it looks like that went OK"));
394 command_destroy(&cmd);
395 free(buf);
396 post_script_tasks();
398 return 1;