2 * dpkg - main program for package management
3 * main.c - main program
5 * Copyright © 1994,1995 Ian Jackson <ijackson@chiark.greenend.org.uk>
6 * Copyright © 2006-2016 Guillem Jover <guillem@debian.org>
7 * Copyright © 2010 Canonical Ltd.
8 * written by Martin Pitt <martin.pitt@canonical.com>
10 * This is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program. If not, see <https://www.gnu.org/licenses/>.
27 #include <sys/types.h>
43 #include <dpkg/macros.h>
44 #include <dpkg/i18n.h>
45 #include <dpkg/c-ctype.h>
46 #include <dpkg/dpkg.h>
47 #include <dpkg/dpkg-db.h>
48 #include <dpkg/arch.h>
49 #include <dpkg/path.h>
50 #include <dpkg/subproc.h>
51 #include <dpkg/command.h>
52 #include <dpkg/options.h>
58 static void DPKG_ATTR_NORET
59 printversion(const struct cmdinfo *ci, const char *value)
61 printf(_("Debian '%s' package management program version %s.\n"),
62 DPKG, PACKAGE_RELEASE);
64 "This is free software; see the GNU General Public License version 2 or\n"
65 "later for copying conditions. There is NO warranty.\n"));
67 m_output(stdout, _("<standard output>"));
73 * FIXME: Options that need fixing:
77 static void DPKG_ATTR_NORET
78 usage(const struct cmdinfo *ci, const char *value)
81 "Usage: %s [<option> ...] <command>\n"
86 " -i|--install <.deb file name> ... | -R|--recursive <directory> ...\n"
87 " --unpack <.deb file name> ... | -R|--recursive <directory> ...\n"
88 " -A|--record-avail <.deb file name> ... | -R|--recursive <directory> ...\n"
89 " --configure <package> ... | -a|--pending\n"
90 " --triggers-only <package> ... | -a|--pending\n"
91 " -r|--remove <package> ... | -a|--pending\n"
92 " -P|--purge <package> ... | -a|--pending\n"
93 " -V|--verify <package> ... Verify the integrity of package(s).\n"
94 " --get-selections [<pattern> ...] Get list of selections to stdout.\n"
95 " --set-selections Set package selections from stdin.\n"
96 " --clear-selections Deselect every non-essential package.\n"
97 " --update-avail [<Packages-file>] Replace available packages info.\n"
98 " --merge-avail [<Packages-file>] Merge with info from file.\n"
99 " --clear-avail Erase existing available info.\n"
100 " --forget-old-unavail Forget uninstalled unavailable pkgs.\n"
101 " -s|--status <package> ... Display package status details.\n"
102 " -p|--print-avail <package> ... Display available version details.\n"
103 " -L|--listfiles <package> ... List files 'owned' by package(s).\n"
104 " -l|--list [<pattern> ...] List packages concisely.\n"
105 " -S|--search <pattern> ... Find package(s) owning file(s).\n"
106 " -C|--audit [<package> ...] Check for broken package(s).\n"
107 " --yet-to-unpack Print packages selected for installation.\n"
108 " --predep-package Print pre-dependencies to unpack.\n"
109 " --add-architecture <arch> Add <arch> to the list of architectures.\n"
110 " --remove-architecture <arch> Remove <arch> from the list of architectures.\n"
111 " --print-architecture Print dpkg architecture.\n"
112 " --print-foreign-architectures Print allowed foreign architectures.\n"
113 " --assert-<feature> Assert support for the specified feature.\n"
114 " --validate-<thing> <string> Validate a <thing>'s <string>.\n"
115 " --compare-versions <a> <op> <b> Compare version numbers - see below.\n"
116 " --force-help Show help on forcing.\n"
117 " -Dh|--debug=help Show help on debugging.\n"
121 " -?, --help Show this help message.\n"
122 " --version Show the version.\n"
126 "Assertable features: support-predepends, working-epoch, long-filenames,\n"
127 " multi-conrep, multi-arch, versioned-provides.\n"
131 "Validatable things: pkgname, archname, trigname, version.\n"
135 "Use dpkg with -b, --build, -c, --contents, -e, --control, -I, --info,\n"
136 " -f, --field, -x, --extract, -X, --vextract, --ctrl-tarfile, --fsys-tarfile\n"
137 "on archives (type %s --help).\n"
142 " --admindir=<directory> Use <directory> instead of %s.\n"
143 " --root=<directory> Install on a different root directory.\n"
144 " --instdir=<directory> Change installation dir without changing admin dir.\n"
145 " --path-exclude=<pattern> Do not install paths which match a shell pattern.\n"
146 " --path-include=<pattern> Re-include a pattern after a previous exclusion.\n"
147 " -O|--selected-only Skip packages not selected for install/upgrade.\n"
148 " -E|--skip-same-version Skip packages whose same version is installed.\n"
149 " -G|--refuse-downgrade Skip packages with earlier version than installed.\n"
150 " -B|--auto-deconfigure Install even if it would break some other package.\n"
151 " --[no-]triggers Skip or force consequential trigger processing.\n"
152 " --verify-format=<format> Verify output format (supported: 'rpm').\n"
153 " --no-debsig Do not try to verify package signatures.\n"
154 " --no-act|--dry-run|--simulate\n"
155 " Just say what we would do - don't do it.\n"
156 " -D|--debug=<octal> Enable debugging (see -Dhelp or --debug=help).\n"
157 " --status-fd <n> Send status change updates to file descriptor <n>.\n"
158 " --status-logger=<command> Send status change updates to <command>'s stdin.\n"
159 " --log=<filename> Log status changes and actions to <filename>.\n"
160 " --ignore-depends=<package>,...\n"
161 " Ignore dependencies involving <package>.\n"
162 " --force-... Override problems (see --force-help).\n"
163 " --no-force-...|--refuse-...\n"
164 " Stop when problems encountered.\n"
165 " --abort-after <n> Abort after encountering <n> errors.\n"
169 "Comparison operators for --compare-versions are:\n"
170 " lt le eq ne ge gt (treat empty version as earlier than any version);\n"
171 " lt-nl le-nl ge-nl gt-nl (treat empty version as later than any version);\n"
172 " < << <= = >= >> > (only for compatibility with control file syntax).\n"
176 "Use 'apt' or 'aptitude' for user-friendly package management.\n"));
178 m_output(stdout, _("<standard output>"));
183 static const char printforhelp[] = N_(
184 "Type dpkg --help for help about installing and deinstalling packages [*];\n"
185 "Use 'apt' or 'aptitude' for user-friendly package management;\n"
186 "Type dpkg -Dhelp for a list of dpkg debug flag values;\n"
187 "Type dpkg --force-help for a list of forcing options;\n"
188 "Type dpkg-deb --help for help about manipulating *.deb files;\n"
190 "Options marked [*] produce a lot of output - pipe it through 'less' or 'more' !");
192 int f_pending=0, f_recursive=0, f_alsoselect=1, f_skipsame=0, f_noact=0;
193 int f_autodeconf=0, f_nodebsig=0;
195 int fc_downgrade=1, fc_configureany=0, fc_hold=0, fc_removereinstreq=0, fc_overwrite=0;
196 int fc_removeessential=0, fc_conflicts=0, fc_depends=0, fc_dependsversion=0;
197 int fc_breaks=0, fc_badpath=0, fc_overwritediverted=0, fc_architecture=0;
198 int fc_nonroot=0, fc_overwritedir=0, fc_conff_new=0, fc_conff_miss=0;
199 int fc_conff_old=0, fc_conff_def=0;
200 int fc_conff_ask = 0;
201 int fc_unsafe_io = 0;
202 int fc_badverify = 0;
203 int fc_badversion = 0;
204 int fc_script_chrootless = 0;
207 static const char *admindir = ADMINDIR;
208 const char *instdir= "";
209 struct pkg_list *ignoredependss = NULL;
212 forcetype_str(char type)
223 internerr("unknown force type '%c'", type);
227 static const struct forceinfo {
234 '!', N_("Set all force options")},
235 { "downgrade", &fc_downgrade,
236 '*', N_("Replace a package with a lower version") },
237 { "configure-any", &fc_configureany,
238 ' ', N_("Configure any package which may help this one") },
240 ' ', N_("Process incidental packages even when on hold") },
241 { "not-root", &fc_nonroot,
242 ' ', N_("Try to (de)install things even when not root") },
243 { "bad-path", &fc_badpath,
244 ' ', N_("PATH is missing important programs, problems likely") },
245 { "bad-verify", &fc_badverify,
246 ' ', N_("Install a package even if it fails authenticity check") },
247 { "bad-version", &fc_badversion,
248 ' ', N_("Process even packages with wrong versions") },
249 { "overwrite", &fc_overwrite,
250 ' ', N_("Overwrite a file from one package with another") },
251 { "overwrite-diverted", &fc_overwritediverted,
252 ' ', N_("Overwrite a diverted file with an undiverted version") },
253 { "overwrite-dir", &fc_overwritedir,
254 '!', N_("Overwrite one package's directory with another's file") },
255 { "unsafe-io", &fc_unsafe_io,
256 '!', N_("Do not perform safe I/O operations when unpacking") },
257 { "script-chrootless", &fc_script_chrootless,
258 '!', N_("Do not chroot into maintainer script environment") },
259 { "confnew", &fc_conff_new,
260 '!', N_("Always use the new config files, don't prompt") },
261 { "confold", &fc_conff_old,
262 '!', N_("Always use the old config files, don't prompt") },
263 { "confdef", &fc_conff_def,
264 '!', N_("Use the default option for new config files if one\n"
265 "is available, don't prompt. If no default can be found,\n"
266 "you will be prompted unless one of the confold or\n"
267 "confnew options is also given") },
268 { "confmiss", &fc_conff_miss,
269 '!', N_("Always install missing config files") },
270 { "confask", &fc_conff_ask,
271 '!', N_("Offer to replace config files with no new versions") },
272 { "architecture", &fc_architecture,
273 '!', N_("Process even packages with wrong or no architecture") },
274 { "breaks", &fc_breaks,
275 '!', N_("Install even if it would break another package") },
276 { "conflicts", &fc_conflicts,
277 '!', N_("Allow installation of conflicting packages") },
278 { "depends", &fc_depends,
279 '!', N_("Turn all dependency problems into warnings") },
280 { "depends-version", &fc_dependsversion,
281 '!', N_("Turn dependency version problems into warnings") },
282 { "remove-reinstreq", &fc_removereinstreq,
283 '!', N_("Remove packages which require installation") },
284 { "remove-essential", &fc_removeessential,
285 '!', N_("Remove an essential package") },
289 #define DBG_DEF(n, d) \
290 { .flag = dbg_##n, .name = #n, .desc = d }
292 static const struct debuginfo {
297 DBG_DEF(general, N_("Generally helpful progress information")),
298 DBG_DEF(scripts, N_("Invocation and status of maintainer scripts")),
299 DBG_DEF(eachfile, N_("Output for each file processed")),
300 DBG_DEF(eachfiledetail, N_("Lots of output for each file processed")),
301 DBG_DEF(conff, N_("Output for each configuration file")),
302 DBG_DEF(conffdetail, N_("Lots of output for each configuration file")),
303 DBG_DEF(depcon, N_("Dependencies and conflicts")),
304 DBG_DEF(depcondetail, N_("Lots of dependencies/conflicts output")),
305 DBG_DEF(triggers, N_("Trigger activation and processing")),
306 DBG_DEF(triggersdetail, N_("Lots of output regarding triggers")),
307 DBG_DEF(triggersstupid, N_("Silly amounts of output regarding triggers")),
308 DBG_DEF(veryverbose, N_("Lots of drivel about eg the dpkg/info directory")),
309 DBG_DEF(stupidlyverbose, N_("Insane amounts of drivel")),
314 set_debug(const struct cmdinfo *cpi, const char *value)
318 const struct debuginfo *dip;
322 "%s debugging option, --debug=<octal> or -D<octal>:\n"
324 " Number Ref. in source Description\n"), DPKG);
326 for (dip = debuginfos; dip->name; dip++)
327 printf(" %6o %-16s %s\n", dip->flag, dip->name, gettext(dip->desc));
330 "Debugging options can be mixed using bitwise-or.\n"
331 "Note that the meanings and values are subject to change.\n"));
332 m_output(stdout, _("<standard output>"));
337 mask = strtol(value, &endp, 8);
338 if (value == endp || *endp || mask < 0 || errno == ERANGE)
339 badusage(_("--%s requires a positive octal argument"), cpi->olong);
341 debug_set_mask(mask);
345 set_filter(const struct cmdinfo *cip, const char *value)
347 filter_add(value, cip->arg_int);
351 set_verify_format(const struct cmdinfo *cip, const char *value)
353 if (!verify_set_output(value))
354 badusage(_("unknown verify output format '%s'"), value);
358 set_instdir(const struct cmdinfo *cip, const char *value)
362 new_instdir = m_strdup(value);
363 path_trim_slash_slashdot(new_instdir);
365 instdir = new_instdir;
369 set_root(const struct cmdinfo *cip, const char *value)
371 set_instdir(cip, value);
372 admindir = str_fmt("%s%s", instdir, ADMINDIR);
376 set_ignore_depends(const struct cmdinfo *cip, const char *value)
380 copy= m_malloc(strlen(value)+2);
382 copy[strlen(value) + 1] = '\0';
383 for (p=copy; *p; p++) {
384 if (*p != ',') continue;
386 if (!*p || *p==',' || p==copy+1)
387 badusage(_("null package name in --%s comma-separated list '%.250s'"),
394 pkg = dpkg_options_parse_pkgname(cip, p);
395 pkg_list_prepend(&ignoredependss, pkg);
404 set_integer(const struct cmdinfo *cip, const char *value)
406 *cip->iassignto = dpkg_options_parse_arg_int(cip, value);
410 set_pipe(const struct cmdinfo *cip, const char *value)
414 v = dpkg_options_parse_arg_int(cip, value);
420 is_invoke_action(enum action action)
430 case act_arch_remove:
437 struct invoke_list pre_invoke_hooks = { .head = NULL, .tail = &pre_invoke_hooks.head };
438 struct invoke_list post_invoke_hooks = { .head = NULL, .tail = &post_invoke_hooks.head };
439 struct invoke_list status_loggers = { .head = NULL, .tail = &status_loggers.head };
442 set_invoke_hook(const struct cmdinfo *cip, const char *value)
444 struct invoke_list *hook_list = cip->arg_ptr;
445 struct invoke_hook *hook_new;
447 hook_new = m_malloc(sizeof(struct invoke_hook));
448 hook_new->command = m_strdup(value);
449 hook_new->next = NULL;
451 /* Add the new hook at the tail of the list to preserve the order. */
452 *hook_list->tail = hook_new;
453 hook_list->tail = &hook_new->next;
457 run_invoke_hooks(const char *action, struct invoke_list *hook_list)
459 struct invoke_hook *hook;
461 setenv("DPKG_HOOK_ACTION", action, 1);
463 for (hook = hook_list->head; hook; hook = hook->next) {
466 /* XXX: As an optimization, use exec instead if no shell metachar are
467 * used “!$=&|\\`'"^~;<>{}[]()?*#”. */
468 status = system(hook->command);
470 ohshit(_("error executing hook '%s', exit code %d"), hook->command,
474 unsetenv("DPKG_HOOK_ACTION");
478 free_invoke_hooks(struct invoke_list *hook_list)
480 struct invoke_hook *hook, *hook_next;
482 for (hook = hook_list->head; hook; hook = hook_next) {
483 hook_next = hook->next;
490 run_logger(struct invoke_hook *hook, const char *name)
497 pid = subproc_fork();
499 /* Setup stdin and stdout. */
506 command_shell(hook->command, name);
514 run_status_loggers(struct invoke_list *hook_list)
516 struct invoke_hook *hook;
518 for (hook = hook_list->head; hook; hook = hook->next) {
521 fd = run_logger(hook, _("status logger"));
527 arch_add(const char *const *argv)
529 struct dpkg_arch *arch;
530 const char *archname = *argv++;
532 if (archname == NULL || *argv)
533 badusage(_("--%s takes exactly one argument"), cipaction->olong);
535 dpkg_arch_load_list();
537 arch = dpkg_arch_add(archname);
538 switch (arch->type) {
539 case DPKG_ARCH_NATIVE:
540 case DPKG_ARCH_FOREIGN:
542 case DPKG_ARCH_ILLEGAL:
543 ohshit(_("architecture '%s' is illegal: %s"), archname,
544 dpkg_arch_name_is_illegal(archname));
546 ohshit(_("architecture '%s' is reserved and cannot be added"), archname);
549 dpkg_arch_save_list();
555 arch_remove(const char *const *argv)
557 const char *archname = *argv++;
558 struct dpkg_arch *arch;
559 struct pkgiterator *iter;
562 if (archname == NULL || *argv)
563 badusage(_("--%s takes exactly one argument"), cipaction->olong);
565 modstatdb_open(msdbrw_readonly);
567 arch = dpkg_arch_find(archname);
568 if (arch->type != DPKG_ARCH_FOREIGN) {
569 warning(_("cannot remove non-foreign architecture '%s'"), arch->name);
573 /* Check if it's safe to remove the architecture from the db. */
574 iter = pkg_db_iter_new();
575 while ((pkg = pkg_db_iter_next_pkg(iter))) {
576 if (pkg->status < PKG_STAT_HALFINSTALLED)
578 if (pkg->installed.arch == arch) {
580 warning(_("removing architecture '%s' currently in use by database"),
583 ohshit(_("cannot remove architecture '%s' currently in use by the database"),
588 pkg_db_iter_free(iter);
590 dpkg_arch_unmark(arch);
591 dpkg_arch_save_list();
593 modstatdb_shutdown();
599 print_forceinfo_line(int type, const char *name, const char *desc)
601 printf(" %s %-18s %s\n", forcetype_str(type), name, desc);
605 print_forceinfo(const struct forceinfo *fi)
609 desc = m_strdup(gettext(fi->desc));
611 line = strtok(desc, "\n");
612 print_forceinfo_line(fi->type, fi->name, line);
613 while ((line = strtok(NULL, "\n")))
614 print_forceinfo_line(' ', "", line);
620 set_force(const struct cmdinfo *cip, const char *value)
624 const struct forceinfo *fip;
626 if (strcmp(value, "help") == 0) {
628 "%s forcing options - control behaviour when problems found:\n"
629 " warn but continue: --force-<thing>,<thing>,...\n"
630 " stop with error: --refuse-<thing>,<thing>,... | --no-force-<thing>,...\n"
631 " Forcing things:\n"), DPKG);
633 for (fip = forceinfos; fip->name; fip++)
634 print_forceinfo(fip);
638 "WARNING - use of options marked [!] can seriously damage your installation.\n"
639 "Forcing options marked [*] are enabled by default.\n"));
640 m_output(stdout, _("<standard output>"));
645 comma= strchr(value,',');
646 l = comma ? (size_t)(comma - value) : strlen(value);
647 for (fip=forceinfos; fip->name; fip++)
648 if (strncmp(fip->name, value, l) == 0 && strlen(fip->name) == l)
652 badusage(_("unknown force/refuse option '%.*s'"),
653 (int)min(l, 250), value);
654 } else if (strcmp(fip->name, "all") == 0) {
655 for (fip = forceinfos; fip->name; fip++)
657 *fip->opt = cip->arg_int;
658 } else if (fip->opt) {
659 *fip->opt = cip->arg_int;
661 warning(_("obsolete force/refuse option '%s'"), fip->name);
669 int execbackend(const char *const *argv) DPKG_ATTR_NORET;
670 int commandfd(const char *const *argv);
672 /* This table has both the action entries in it and the normal options.
673 * The action entries are made with the ACTION macro, as they all
674 * have a very similar structure. */
675 static const struct cmdinfo cmdinfos[]= {
676 #define ACTIONBACKEND(longopt, shortopt, backend) \
677 { longopt, shortopt, 0, NULL, NULL, setaction, 0, (void *)backend, execbackend }
679 ACTION( "install", 'i', act_install, archivefiles ),
680 ACTION( "unpack", 0, act_unpack, archivefiles ),
681 ACTION( "record-avail", 'A', act_avail, archivefiles ),
682 ACTION( "configure", 0, act_configure, packages ),
683 ACTION( "remove", 'r', act_remove, packages ),
684 ACTION( "purge", 'P', act_purge, packages ),
685 ACTION( "triggers-only", 0, act_triggers, packages ),
686 ACTION( "verify", 'V', act_verify, verify ),
687 ACTIONBACKEND( "listfiles", 'L', DPKGQUERY),
688 ACTIONBACKEND( "status", 's', DPKGQUERY),
689 ACTION( "get-selections", 0, act_getselections, getselections ),
690 ACTION( "set-selections", 0, act_setselections, setselections ),
691 ACTION( "clear-selections", 0, act_clearselections, clearselections ),
692 ACTIONBACKEND( "print-avail", 'p', DPKGQUERY),
693 ACTION( "update-avail", 0, act_avreplace, updateavailable ),
694 ACTION( "merge-avail", 0, act_avmerge, updateavailable ),
695 ACTION( "clear-avail", 0, act_avclear, updateavailable ),
696 ACTION( "forget-old-unavail", 0, act_forgetold, forgetold ),
697 ACTION( "audit", 'C', act_audit, audit ),
698 ACTION( "yet-to-unpack", 0, act_unpackchk, unpackchk ),
699 ACTIONBACKEND( "list", 'l', DPKGQUERY),
700 ACTIONBACKEND( "search", 'S', DPKGQUERY),
701 ACTION( "assert-support-predepends", 0, act_assertpredep, assertpredep ),
702 ACTION( "assert-working-epoch", 0, act_assertepoch, assertepoch ),
703 ACTION( "assert-long-filenames", 0, act_assertlongfilenames, assertlongfilenames ),
704 ACTION( "assert-multi-conrep", 0, act_assertmulticonrep, assertmulticonrep ),
705 ACTION( "assert-multi-arch", 0, act_assertmultiarch, assertmultiarch ),
706 ACTION( "assert-versioned-provides", 0, act_assertverprovides, assertverprovides ),
707 ACTION( "add-architecture", 0, act_arch_add, arch_add ),
708 ACTION( "remove-architecture", 0, act_arch_remove, arch_remove ),
709 ACTION( "print-architecture", 0, act_printarch, printarch ),
710 ACTION( "print-foreign-architectures", 0, act_printforeignarches, print_foreign_arches ),
711 ACTION( "predep-package", 0, act_predeppackage, predeppackage ),
712 ACTION( "validate-pkgname", 0, act_validate_pkgname, validate_pkgname ),
713 ACTION( "validate-trigname", 0, act_validate_trigname, validate_trigname ),
714 ACTION( "validate-archname", 0, act_validate_archname, validate_archname ),
715 ACTION( "validate-version", 0, act_validate_version, validate_version ),
716 ACTION( "compare-versions", 0, act_cmpversions, cmpversions ),
718 ACTION( "command-fd", 'c', act_commandfd, commandfd ),
721 { "pre-invoke", 0, 1, NULL, NULL, set_invoke_hook, 0, &pre_invoke_hooks },
722 { "post-invoke", 0, 1, NULL, NULL, set_invoke_hook, 0, &post_invoke_hooks },
723 { "path-exclude", 0, 1, NULL, NULL, set_filter, 0 },
724 { "path-include", 0, 1, NULL, NULL, set_filter, 1 },
725 { "verify-format", 0, 1, NULL, NULL, set_verify_format },
726 { "status-logger", 0, 1, NULL, NULL, set_invoke_hook, 0, &status_loggers },
727 { "status-fd", 0, 1, NULL, NULL, set_pipe, 0 },
728 { "log", 0, 1, NULL, &log_file, NULL, 0 },
729 { "pending", 'a', 0, &f_pending, NULL, NULL, 1 },
730 { "recursive", 'R', 0, &f_recursive, NULL, NULL, 1 },
731 { "no-act", 0, 0, &f_noact, NULL, NULL, 1 },
732 { "dry-run", 0, 0, &f_noact, NULL, NULL, 1 },
733 { "simulate", 0, 0, &f_noact, NULL, NULL, 1 },
734 { "no-debsig", 0, 0, &f_nodebsig, NULL, NULL, 1 },
735 /* Alias ('G') for --refuse. */
736 { NULL, 'G', 0, &fc_downgrade, NULL, NULL, 0 },
737 { "selected-only", 'O', 0, &f_alsoselect, NULL, NULL, 0 },
738 { "triggers", 0, 0, &f_triggers, NULL, NULL, 1 },
739 { "no-triggers", 0, 0, &f_triggers, NULL, NULL, -1 },
740 /* FIXME: Remove ('N') sometime. */
741 { "no-also-select", 'N', 0, &f_alsoselect, NULL, NULL, 0 },
742 { "skip-same-version", 'E', 0, &f_skipsame, NULL, NULL, 1 },
743 { "auto-deconfigure", 'B', 0, &f_autodeconf, NULL, NULL, 1 },
744 { "root", 0, 1, NULL, NULL, set_root, 0 },
745 { "abort-after", 0, 1, &errabort, NULL, set_integer, 0 },
746 { "admindir", 0, 1, NULL, &admindir, NULL, 0 },
747 { "instdir", 0, 1, NULL, NULL, set_instdir, 0 },
748 { "ignore-depends", 0, 1, NULL, NULL, set_ignore_depends, 0 },
749 { "force", 0, 2, NULL, NULL, set_force, 1 },
750 { "refuse", 0, 2, NULL, NULL, set_force, 0 },
751 { "no-force", 0, 2, NULL, NULL, set_force, 0 },
752 { "debug", 'D', 1, NULL, NULL, set_debug, 0 },
753 { "help", '?', 0, NULL, NULL, usage, 0 },
754 { "version", 0, 0, NULL, NULL, printversion, 0 },
755 ACTIONBACKEND( "build", 'b', BACKEND),
756 ACTIONBACKEND( "contents", 'c', BACKEND),
757 ACTIONBACKEND( "control", 'e', BACKEND),
758 ACTIONBACKEND( "info", 'I', BACKEND),
759 ACTIONBACKEND( "field", 'f', BACKEND),
760 ACTIONBACKEND( "extract", 'x', BACKEND),
761 ACTIONBACKEND( "vextract", 'X', BACKEND),
762 ACTIONBACKEND( "ctrl-tarfile", 0, BACKEND),
763 ACTIONBACKEND( "fsys-tarfile", 0, BACKEND),
764 { NULL, 0, 0, NULL, NULL, NULL, 0 }
768 execbackend(const char *const *argv)
772 command_init(&cmd, cipaction->arg_ptr, NULL);
773 command_add_arg(&cmd, cipaction->arg_ptr);
774 command_add_arg(&cmd, str_fmt("--%s", cipaction->olong));
776 /* Explicitly separate arguments from options as any user-supplied
777 * separator got stripped by the option parser */
778 command_add_arg(&cmd, "--");
779 command_add_argl(&cmd, (const char **)argv);
785 commandfd(const char *const *argv)
787 struct varbuf linevb = VARBUF_INIT;
789 const char **newargs = NULL, **endargs;
798 if (pipein == NULL || *argv)
799 badusage(_("--%s takes exactly one argument"), cipaction->olong);
801 infd = dpkg_options_parse_arg_int(cipaction, pipein);
802 in = fdopen(infd, "r");
804 ohshite(_("couldn't open '%i' for stream"), (int)infd);
811 push_error_context();
817 } while (c != EOF && c_isspace(c));
820 do { c= getc(in); if (c == '\n') lno++; } while (c != EOF && c != '\n');
823 varbuf_reset(&linevb);
825 varbuf_add_char(&linevb, c);
827 if (c == '\n') lno++;
829 /* This isn't fully accurate, but overestimating can't hurt. */
832 } while (c != EOF && c != '\n');
834 ohshit(_("unexpected end of file before end of line %d"), lno);
836 varbuf_end_str(&linevb);
837 newargs = m_realloc(newargs, sizeof(const char *) * (argc + 1));
840 endptr = ptr + linevb.used + 1;
842 while(ptr < endptr) {
845 } else if (*ptr == '\\') {
846 memmove(ptr, (ptr+1), (linevb.used-(linevb.buf - ptr)-1));
850 } else if (c_isspace(*ptr)) {
865 newargs[argc++] = NULL;
867 /* We strdup() each argument, but never free it, because the
868 * error messages contain references back to these strings.
869 * Freeing them, and reusing the memory, would make those
870 * error messages confusing, to say the least. */
873 newargs[i] = m_strdup(newargs[i]);
876 setaction(NULL, NULL);
877 dpkg_options_parse((const char *const **)&endargs, cmdinfos, printforhelp);
878 if (!cipaction) badusage(_("need an action option"));
882 ret |= cipaction->action(endargs);
886 pop_error_context(ehflag_normaltidy);
892 int main(int argc, const char *const *argv) {
895 dpkg_locales_init(PACKAGE);
896 dpkg_program_init("dpkg");
897 dpkg_options_load(DPKG, cmdinfos);
898 dpkg_options_parse(&argv, cmdinfos, printforhelp);
900 /* When running as root, make sure our primary group is also root, so
901 * that files created by maintainer scripts have correct ownership. */
902 if (!fc_nonroot && getuid() == 0)
904 ohshite(_("cannot set primary group ID to root"));
906 if (!cipaction) badusage(_("need an action option"));
908 admindir = dpkg_db_set_dir(admindir);
910 /* Always set environment, to avoid possible security risks. */
911 if (setenv("DPKG_ADMINDIR", admindir, 1) < 0)
912 ohshite(_("unable to setenv for subprocesses"));
913 if (setenv("DPKG_ROOT", instdir, 1) < 0)
914 ohshite(_("unable to setenv for subprocesses"));
917 f_triggers = (cipaction->arg_int == act_triggers && *argv) ? -1 : 1;
919 if (is_invoke_action(cipaction->arg_int)) {
920 run_invoke_hooks(cipaction->olong, &pre_invoke_hooks);
921 run_status_loggers(&status_loggers);
926 ret = cipaction->action(argv);
928 if (is_invoke_action(cipaction->arg_int))
929 run_invoke_hooks(cipaction->olong, &post_invoke_hooks);
931 free_invoke_hooks(&pre_invoke_hooks);
932 free_invoke_hooks(&post_invoke_hooks);
936 return reportbroken_retexitstatus(ret);