dpkg (1.18.25) stretch; urgency=medium
[dpkg] / src / main.c
CommitLineData
1479465f
GJ
1/*
2 * dpkg - main program for package management
3 * main.c - main program
4 *
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>
9 *
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.
14 *
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.
19 *
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/>.
22 */
23
24#include <config.h>
25#include <compat.h>
26
27#include <sys/types.h>
28#include <sys/wait.h>
29
30#include <errno.h>
31#include <limits.h>
32#if HAVE_LOCALE_H
33#include <locale.h>
34#endif
35#include <string.h>
36#include <fcntl.h>
37#include <dirent.h>
38#include <unistd.h>
39#include <stdbool.h>
40#include <stdlib.h>
41#include <stdio.h>
42
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>
53
54#include "main.h"
55#include "filesdb.h"
56#include "filters.h"
57
58static void DPKG_ATTR_NORET
59printversion(const struct cmdinfo *ci, const char *value)
60{
61 printf(_("Debian '%s' package management program version %s.\n"),
62 DPKG, PACKAGE_RELEASE);
63 printf(_(
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"));
66
67 m_output(stdout, _("<standard output>"));
68
69 exit(0);
70}
71
72/*
73 * FIXME: Options that need fixing:
74 * dpkg --command-fd
75 */
76
77static void DPKG_ATTR_NORET
78usage(const struct cmdinfo *ci, const char *value)
79{
80 printf(_(
81"Usage: %s [<option> ...] <command>\n"
82"\n"), DPKG);
83
84 printf(_(
85"Commands:\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"
118"\n"));
119
120 printf(_(
121" -?, --help Show this help message.\n"
122" --version Show the version.\n"
123"\n"));
124
125 printf(_(
126"Assertable features: support-predepends, working-epoch, long-filenames,\n"
127" multi-conrep, multi-arch, versioned-provides.\n"
128"\n"));
129
130 printf(_(
131"Validatable things: pkgname, archname, trigname, version.\n"
132"\n"));
133
134 printf(_(
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"
138"\n"), BACKEND);
139
140 printf(_(
141"Options:\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"
166"\n"), ADMINDIR);
167
168 printf(_(
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"
173"\n"));
174
175 printf(_(
176"Use 'apt' or 'aptitude' for user-friendly package management.\n"));
177
178 m_output(stdout, _("<standard output>"));
179
180 exit(0);
181}
182
183static 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"
189"\n"
190"Options marked [*] produce a lot of output - pipe it through 'less' or 'more' !");
191
192int f_pending=0, f_recursive=0, f_alsoselect=1, f_skipsame=0, f_noact=0;
193int f_autodeconf=0, f_nodebsig=0;
194int f_triggers = 0;
195int fc_downgrade=1, fc_configureany=0, fc_hold=0, fc_removereinstreq=0, fc_overwrite=0;
196int fc_removeessential=0, fc_conflicts=0, fc_depends=0, fc_dependsversion=0;
197int fc_breaks=0, fc_badpath=0, fc_overwritediverted=0, fc_architecture=0;
198int fc_nonroot=0, fc_overwritedir=0, fc_conff_new=0, fc_conff_miss=0;
199int fc_conff_old=0, fc_conff_def=0;
200int fc_conff_ask = 0;
201int fc_unsafe_io = 0;
202int fc_badverify = 0;
203int fc_badversion = 0;
204int fc_script_chrootless = 0;
205
206int errabort = 50;
207static const char *admindir = ADMINDIR;
208const char *instdir= "";
209struct pkg_list *ignoredependss = NULL;
210
211static const char *
212forcetype_str(char type)
213{
214 switch (type) {
215 case '\0':
216 case ' ':
217 return " ";
218 case '*':
219 return "[*]";
220 case '!':
221 return "[!]";
222 default:
223 internerr("unknown force type '%c'", type);
224 }
225}
226
227static const struct forceinfo {
228 const char *name;
229 int *opt;
230 char type;
231 const char *desc;
232} forceinfos[]= {
233 { "all", NULL,
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") },
239 { "hold", &fc_hold,
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") },
286 { NULL }
287};
288
289#define DBG_DEF(n, d) \
290 { .flag = dbg_##n, .name = #n, .desc = d }
291
292static const struct debuginfo {
293 int flag;
294 const char *name;
295 const char *desc;
296} debuginfos[] = {
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")),
310 { 0, NULL, NULL }
311};
312
313static void
314set_debug(const struct cmdinfo *cpi, const char *value)
315{
316 char *endp;
317 long mask;
318 const struct debuginfo *dip;
319
320 if (*value == 'h') {
321 printf(_(
322"%s debugging option, --debug=<octal> or -D<octal>:\n"
323"\n"
324" Number Ref. in source Description\n"), DPKG);
325
326 for (dip = debuginfos; dip->name; dip++)
327 printf(" %6o %-16s %s\n", dip->flag, dip->name, gettext(dip->desc));
328
329 printf(_("\n"
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>"));
333 exit(0);
334 }
335
336 errno = 0;
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);
340
341 debug_set_mask(mask);
342}
343
344static void
345set_filter(const struct cmdinfo *cip, const char *value)
346{
347 filter_add(value, cip->arg_int);
348}
349
350static void
351set_verify_format(const struct cmdinfo *cip, const char *value)
352{
353 if (!verify_set_output(value))
354 badusage(_("unknown verify output format '%s'"), value);
355}
356
357static void
358set_instdir(const struct cmdinfo *cip, const char *value)
359{
360 char *new_instdir;
361
362 new_instdir = m_strdup(value);
363 path_trim_slash_slashdot(new_instdir);
364
365 instdir = new_instdir;
366}
367
368static void
369set_root(const struct cmdinfo *cip, const char *value)
370{
371 set_instdir(cip, value);
372 admindir = str_fmt("%s%s", instdir, ADMINDIR);
373}
374
375static void
376set_ignore_depends(const struct cmdinfo *cip, const char *value)
377{
378 char *copy, *p;
379
380 copy= m_malloc(strlen(value)+2);
381 strcpy(copy,value);
382 copy[strlen(value) + 1] = '\0';
383 for (p=copy; *p; p++) {
384 if (*p != ',') continue;
385 *p++ = '\0';
386 if (!*p || *p==',' || p==copy+1)
387 badusage(_("null package name in --%s comma-separated list '%.250s'"),
388 cip->olong, value);
389 }
390 p= copy;
391 while (*p) {
392 struct pkginfo *pkg;
393
394 pkg = dpkg_options_parse_pkgname(cip, p);
395 pkg_list_prepend(&ignoredependss, pkg);
396
397 p+= strlen(p)+1;
398 }
399
400 free(copy);
401}
402
403static void
404set_integer(const struct cmdinfo *cip, const char *value)
405{
406 *cip->iassignto = dpkg_options_parse_arg_int(cip, value);
407}
408
409static void
410set_pipe(const struct cmdinfo *cip, const char *value)
411{
412 long v;
413
414 v = dpkg_options_parse_arg_int(cip, value);
415
416 statusfd_add(v);
417}
418
419static bool
420is_invoke_action(enum action action)
421{
422 switch (action) {
423 case act_unpack:
424 case act_configure:
425 case act_install:
426 case act_triggers:
427 case act_remove:
428 case act_purge:
429 case act_arch_add:
430 case act_arch_remove:
431 return true;
432 default:
433 return false;
434 }
435}
436
437struct invoke_list pre_invoke_hooks = { .head = NULL, .tail = &pre_invoke_hooks.head };
438struct invoke_list post_invoke_hooks = { .head = NULL, .tail = &post_invoke_hooks.head };
439struct invoke_list status_loggers = { .head = NULL, .tail = &status_loggers.head };
440
441static void
442set_invoke_hook(const struct cmdinfo *cip, const char *value)
443{
444 struct invoke_list *hook_list = cip->arg_ptr;
445 struct invoke_hook *hook_new;
446
447 hook_new = m_malloc(sizeof(struct invoke_hook));
448 hook_new->command = m_strdup(value);
449 hook_new->next = NULL;
450
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;
454}
455
456static void
457run_invoke_hooks(const char *action, struct invoke_list *hook_list)
458{
459 struct invoke_hook *hook;
460
461 setenv("DPKG_HOOK_ACTION", action, 1);
462
463 for (hook = hook_list->head; hook; hook = hook->next) {
464 int status;
465
466 /* XXX: As an optimization, use exec instead if no shell metachar are
467 * used “!$=&|\\`'"^~;<>{}[]()?*#”. */
468 status = system(hook->command);
469 if (status != 0)
470 ohshit(_("error executing hook '%s', exit code %d"), hook->command,
471 status);
472 }
473
474 unsetenv("DPKG_HOOK_ACTION");
475}
476
477static void
478free_invoke_hooks(struct invoke_list *hook_list)
479{
480 struct invoke_hook *hook, *hook_next;
481
482 for (hook = hook_list->head; hook; hook = hook_next) {
483 hook_next = hook->next;
484 free(hook->command);
485 free(hook);
486 }
487}
488
489static int
490run_logger(struct invoke_hook *hook, const char *name)
491{
492 pid_t pid;
493 int p[2];
494
495 m_pipe(p);
496
497 pid = subproc_fork();
498 if (pid == 0) {
499 /* Setup stdin and stdout. */
500 m_dup2(p[0], 0);
501 close(1);
502
503 close(p[0]);
504 close(p[1]);
505
506 command_shell(hook->command, name);
507 }
508 close(p[0]);
509
510 return p[1];
511}
512
513static void
514run_status_loggers(struct invoke_list *hook_list)
515{
516 struct invoke_hook *hook;
517
518 for (hook = hook_list->head; hook; hook = hook->next) {
519 int fd;
520
521 fd = run_logger(hook, _("status logger"));
522 statusfd_add(fd);
523 }
524}
525
526static int
527arch_add(const char *const *argv)
528{
529 struct dpkg_arch *arch;
530 const char *archname = *argv++;
531
532 if (archname == NULL || *argv)
533 badusage(_("--%s takes exactly one argument"), cipaction->olong);
534
535 dpkg_arch_load_list();
536
537 arch = dpkg_arch_add(archname);
538 switch (arch->type) {
539 case DPKG_ARCH_NATIVE:
540 case DPKG_ARCH_FOREIGN:
541 break;
542 case DPKG_ARCH_ILLEGAL:
543 ohshit(_("architecture '%s' is illegal: %s"), archname,
544 dpkg_arch_name_is_illegal(archname));
545 default:
546 ohshit(_("architecture '%s' is reserved and cannot be added"), archname);
547 }
548
549 dpkg_arch_save_list();
550
551 return 0;
552}
553
554static int
555arch_remove(const char *const *argv)
556{
557 const char *archname = *argv++;
558 struct dpkg_arch *arch;
559 struct pkgiterator *iter;
560 struct pkginfo *pkg;
561
562 if (archname == NULL || *argv)
563 badusage(_("--%s takes exactly one argument"), cipaction->olong);
564
565 modstatdb_open(msdbrw_readonly);
566
567 arch = dpkg_arch_find(archname);
568 if (arch->type != DPKG_ARCH_FOREIGN) {
569 warning(_("cannot remove non-foreign architecture '%s'"), arch->name);
570 return 0;
571 }
572
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)
577 continue;
578 if (pkg->installed.arch == arch) {
579 if (fc_architecture)
580 warning(_("removing architecture '%s' currently in use by database"),
581 arch->name);
582 else
583 ohshit(_("cannot remove architecture '%s' currently in use by the database"),
584 arch->name);
585 break;
586 }
587 }
588 pkg_db_iter_free(iter);
589
590 dpkg_arch_unmark(arch);
591 dpkg_arch_save_list();
592
593 modstatdb_shutdown();
594
595 return 0;
596}
597
598static inline void
599print_forceinfo_line(int type, const char *name, const char *desc)
600{
601 printf(" %s %-18s %s\n", forcetype_str(type), name, desc);
602}
603
604static void
605print_forceinfo(const struct forceinfo *fi)
606{
607 char *desc, *line;
608
609 desc = m_strdup(gettext(fi->desc));
610
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);
615
616 free(desc);
617}
618
619static void
620set_force(const struct cmdinfo *cip, const char *value)
621{
622 const char *comma;
623 size_t l;
624 const struct forceinfo *fip;
625
626 if (strcmp(value, "help") == 0) {
627 printf(_(
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);
632
633 for (fip = forceinfos; fip->name; fip++)
634 print_forceinfo(fip);
635
636 printf(_(
637"\n"
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>"));
641 exit(0);
642 }
643
644 for (;;) {
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)
649 break;
650
651 if (!fip->name) {
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++)
656 if (fip->opt)
657 *fip->opt = cip->arg_int;
658 } else if (fip->opt) {
659 *fip->opt = cip->arg_int;
660 } else {
661 warning(_("obsolete force/refuse option '%s'"), fip->name);
662 }
663
664 if (!comma) break;
665 value= ++comma;
666 }
667}
668
669int execbackend(const char *const *argv) DPKG_ATTR_NORET;
670int commandfd(const char *const *argv);
671
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. */
675static const struct cmdinfo cmdinfos[]= {
676#define ACTIONBACKEND(longopt, shortopt, backend) \
677 { longopt, shortopt, 0, NULL, NULL, setaction, 0, (void *)backend, execbackend }
678
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 ),
717/*
718 ACTION( "command-fd", 'c', act_commandfd, commandfd ),
719*/
720
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 }
765};
766
767int
768execbackend(const char *const *argv)
769{
770 struct command cmd;
771
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));
775
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);
780
781 command_exec(&cmd);
782}
783
784int
785commandfd(const char *const *argv)
786{
787 struct varbuf linevb = VARBUF_INIT;
788 const char * pipein;
789 const char **newargs = NULL, **endargs;
790 char *ptr, *endptr;
791 FILE *in;
792 long infd;
793 int ret = 0;
794 int c, lno, i;
795 bool skipchar;
796
797 pipein = *argv++;
798 if (pipein == NULL || *argv)
799 badusage(_("--%s takes exactly one argument"), cipaction->olong);
800
801 infd = dpkg_options_parse_arg_int(cipaction, pipein);
802 in = fdopen(infd, "r");
803 if (in == NULL)
804 ohshite(_("couldn't open '%i' for stream"), (int)infd);
805
806 for (;;) {
807 bool mode = false;
808 int argc= 1;
809 lno= 0;
810
811 push_error_context();
812
813 do {
814 c = getc(in);
815 if (c == '\n')
816 lno++;
817 } while (c != EOF && c_isspace(c));
818 if (c == EOF) break;
819 if (c == '#') {
820 do { c= getc(in); if (c == '\n') lno++; } while (c != EOF && c != '\n');
821 continue;
822 }
823 varbuf_reset(&linevb);
824 do {
825 varbuf_add_char(&linevb, c);
826 c= getc(in);
827 if (c == '\n') lno++;
828
829 /* This isn't fully accurate, but overestimating can't hurt. */
830 if (c_isspace(c))
831 argc++;
832 } while (c != EOF && c != '\n');
833 if (c == EOF)
834 ohshit(_("unexpected end of file before end of line %d"), lno);
835 if (!argc) continue;
836 varbuf_end_str(&linevb);
837 newargs = m_realloc(newargs, sizeof(const char *) * (argc + 1));
838 argc= 1;
839 ptr= linevb.buf;
840 endptr = ptr + linevb.used + 1;
841 skipchar = false;
842 while(ptr < endptr) {
843 if (skipchar) {
844 skipchar = false;
845 } else if (*ptr == '\\') {
846 memmove(ptr, (ptr+1), (linevb.used-(linevb.buf - ptr)-1));
847 endptr--;
848 skipchar = true;
849 continue;
850 } else if (c_isspace(*ptr)) {
851 if (mode == true) {
852 *ptr = '\0';
853 mode = false;
854 }
855 } else {
856 if (mode == false) {
857 newargs[argc]= ptr;
858 argc++;
859 mode = true;
860 }
861 }
862 ptr++;
863 }
864 *ptr = '\0';
865 newargs[argc++] = NULL;
866
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. */
871 for(i=1;i<argc;i++)
872 if (newargs[i])
873 newargs[i] = m_strdup(newargs[i]);
874 endargs = newargs;
875
876 setaction(NULL, NULL);
877 dpkg_options_parse((const char *const **)&endargs, cmdinfos, printforhelp);
878 if (!cipaction) badusage(_("need an action option"));
879
880 filesdbinit();
881
882 ret |= cipaction->action(endargs);
883
884 files_db_reset();
885
886 pop_error_context(ehflag_normaltidy);
887 }
888
889 return ret;
890}
891
892int main(int argc, const char *const *argv) {
893 int ret;
894
895 dpkg_locales_init(PACKAGE);
896 dpkg_program_init("dpkg");
897 dpkg_options_load(DPKG, cmdinfos);
898 dpkg_options_parse(&argv, cmdinfos, printforhelp);
899
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)
903 if (setgid(0) < 0)
904 ohshite(_("cannot set primary group ID to root"));
905
906 if (!cipaction) badusage(_("need an action option"));
907
908 admindir = dpkg_db_set_dir(admindir);
909
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"));
915
916 if (!f_triggers)
917 f_triggers = (cipaction->arg_int == act_triggers && *argv) ? -1 : 1;
918
919 if (is_invoke_action(cipaction->arg_int)) {
920 run_invoke_hooks(cipaction->olong, &pre_invoke_hooks);
921 run_status_loggers(&status_loggers);
922 }
923
924 filesdbinit();
925
926 ret = cipaction->action(argv);
927
928 if (is_invoke_action(cipaction->arg_int))
929 run_invoke_hooks(cipaction->olong, &post_invoke_hooks);
930
931 free_invoke_hooks(&pre_invoke_hooks);
932 free_invoke_hooks(&post_invoke_hooks);
933
934 dpkg_program_done();
935
936 return reportbroken_retexitstatus(ret);
937}