LCOV - code coverage report
Current view: top level - src/main - main.c (source / functions) Coverage Total Hit
Test: dpkg 1.22.7-3-g89f48 C code coverage Lines: 15.0 % 266 40
Test Date: 2024-07-17 02:53:43 Functions: 23.8 % 21 5
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 9.8 % 143 14

             Branch data     Line data    Source code
       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                 :             : #ifdef 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/subproc.h>
      50                 :             : #include <dpkg/command.h>
      51                 :             : #include <dpkg/pager.h>
      52                 :             : #include <dpkg/options.h>
      53                 :             : #include <dpkg/db-fsys.h>
      54                 :             : 
      55                 :             : #include "main.h"
      56                 :             : #include "filters.h"
      57                 :             : 
      58                 :             : static int
      59                 :          48 : printversion(const char *const *argv)
      60                 :             : {
      61         [ -  + ]:          48 :   if (f_robot) {
      62                 :           0 :     printf("%s", PACKAGE_VERSION);
      63                 :             :   } else {
      64                 :          48 :     printf(_("Debian '%s' package management program version %s.\n"),
      65                 :             :            DPKG, PACKAGE_RELEASE);
      66                 :          48 :     printf(_(
      67                 :             : "This is free software; see the GNU General Public License version 2 or\n"
      68                 :             : "later for copying conditions. There is NO warranty.\n"));
      69                 :             :   }
      70                 :             : 
      71                 :          48 :   m_output(stdout, _("<standard output>"));
      72                 :             : 
      73                 :          48 :   return 0;
      74                 :             : }
      75                 :             : 
      76                 :             : /*
      77                 :             :  * FIXME: Options that need fixing:
      78                 :             :  * dpkg --command-fd
      79                 :             :  */
      80                 :             : 
      81                 :             : static int
      82                 :           0 : usage(const char *const *argv)
      83                 :             : {
      84                 :           0 :   printf(_(
      85                 :             : "Usage: %s [<option>...] <command>\n"
      86                 :             : "\n"), DPKG);
      87                 :             : 
      88                 :           0 :   printf(_(
      89                 :             : "Commands:\n"
      90                 :             : "  -i|--install       <.deb file name>... | -R|--recursive <directory>...\n"
      91                 :             : "  --unpack           <.deb file name>... | -R|--recursive <directory>...\n"
      92                 :             : "  -A|--record-avail  <.deb file name>... | -R|--recursive <directory>...\n"
      93                 :             : "  --configure        <package>... | -a|--pending\n"
      94                 :             : "  --triggers-only    <package>... | -a|--pending\n"
      95                 :             : "  -r|--remove        <package>... | -a|--pending\n"
      96                 :             : "  -P|--purge         <package>... | -a|--pending\n"
      97                 :             : "  -V|--verify [<package>...]       Verify the integrity of package(s).\n"
      98                 :             : "  --get-selections [<pattern>...]  Get list of selections to stdout.\n"
      99                 :             : "  --set-selections                 Set package selections from stdin.\n"
     100                 :             : "  --clear-selections               Deselect every non-essential package.\n"
     101                 :             : "  --update-avail [<Packages-file>] Replace available packages info.\n"
     102                 :             : "  --merge-avail [<Packages-file>]  Merge with info from file.\n"
     103                 :             : "  --clear-avail                    Erase existing available info.\n"
     104                 :             : "  --forget-old-unavail             Forget uninstalled unavailable pkgs.\n"
     105                 :             : "  -s|--status [<package>...]       Display package status details.\n"
     106                 :             : "  -p|--print-avail [<package>...]  Display available version details.\n"
     107                 :             : "  -L|--listfiles <package>...      List files 'owned' by package(s).\n"
     108                 :             : "  -l|--list [<pattern>...]         List packages concisely.\n"
     109                 :             : "  -S|--search <pattern>...         Find package(s) owning file(s).\n"
     110                 :             : "  -C|--audit [<package>...]        Check for broken package(s).\n"
     111                 :             : "  --yet-to-unpack                  Print packages selected for installation.\n"
     112                 :             : "  --predep-package                 Print pre-dependencies to unpack.\n"
     113                 :             : "  --add-architecture <arch>        Add <arch> to the list of architectures.\n"
     114                 :             : "  --remove-architecture <arch>     Remove <arch> from the list of architectures.\n"
     115                 :             : "  --print-architecture             Print dpkg architecture.\n"
     116                 :             : "  --print-foreign-architectures    Print allowed foreign architectures.\n"
     117                 :             : "  --assert-help                    Show help on assertions.\n"
     118                 :             : "  --assert-<feature>               Assert support for the specified feature.\n"
     119                 :             : "  --validate-<thing> <string>      Validate a <thing>'s <string>.\n"
     120                 :             : "  --compare-versions <a> <op> <b>  Compare version numbers - see below.\n"
     121                 :             : "  --force-help                     Show help on forcing.\n"
     122                 :             : "  -Dh|--debug=help                 Show help on debugging.\n"
     123                 :             : "\n"));
     124                 :             : 
     125                 :           0 :   printf(_(
     126                 :             : "  -?, --help                       Show this help message.\n"
     127                 :             : "      --version                    Show the version.\n"
     128                 :             : "\n"));
     129                 :             : 
     130                 :           0 :   printf(_(
     131                 :             : "Validatable things: pkgname, archname, trigname, version.\n"
     132                 :             : "\n"));
     133                 :             : 
     134                 :           0 :   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                 :           0 :   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                 :             : "  --pre-invoke=<command>     Set a pre-invoke hook.\n"
     146                 :             : "  --post-invoke=<command>    Set a post-invoke hook.\n"
     147                 :             : "  --path-exclude=<pattern>   Do not install paths which match a shell pattern.\n"
     148                 :             : "  --path-include=<pattern>   Re-include a pattern after a previous exclusion.\n"
     149                 :             : "  -O|--selected-only         Skip packages not selected for install/upgrade.\n"
     150                 :             : "  -E|--skip-same-version     Skip packages with same installed version/arch.\n"
     151                 :             : "  -G|--refuse-downgrade      Skip packages with earlier version than installed.\n"
     152                 :             : "  -B|--auto-deconfigure      Install even if it would break some other package.\n"
     153                 :             : "  --[no-]triggers            Skip or force consequential trigger processing.\n"
     154                 :             : "  --verify-format=<format>   Verify output format (supported: 'rpm').\n"
     155                 :             : "  --no-pager                 Disables the use of any pager.\n"
     156                 :             : "  --no-debsig                Do not try to verify package signatures.\n"
     157                 :             : "  --no-act|--dry-run|--simulate\n"
     158                 :             : "                             Just say what we would do - don't do it.\n"
     159                 :             : "  -D|--debug=<octal>         Enable debugging (see -Dhelp or --debug=help).\n"
     160                 :             : "  --status-fd <n>            Send status change updates to file descriptor <n>.\n"
     161                 :             : "  --status-logger=<command>  Send status change updates to <command>'s stdin.\n"
     162                 :             : "  --log=<filename>           Log status changes and actions to <filename>.\n"
     163                 :             : "  --ignore-depends=<package>[,...]\n"
     164                 :             : "                             Ignore dependencies involving <package>.\n"
     165                 :             : "  --force-<thing>[,...]      Override problems (see --force-help).\n"
     166                 :             : "  --no-force-<thing>[,...]   Stop when problems encountered.\n"
     167                 :             : "  --refuse-<thing>[,...]     Ditto.\n"
     168                 :             : "  --abort-after <n>          Abort after encountering <n> errors.\n"
     169                 :             : "  --robot                    Use machine-readable output on some commands.\n"
     170                 :             : "\n"), ADMINDIR);
     171                 :             : 
     172                 :           0 :   printf(_(
     173                 :             : "Comparison operators for --compare-versions are:\n"
     174                 :             : "  lt le eq ne ge gt       (treat empty version as earlier than any version);\n"
     175                 :             : "  lt-nl le-nl ge-nl gt-nl (treat empty version as later than any version);\n"
     176                 :             : "  < << <= = >= >> >       (only for compatibility with control file syntax).\n"
     177                 :             : "\n"));
     178                 :             : 
     179                 :           0 :   printf(_(
     180                 :             : "Use 'apt' or 'aptitude' for user-friendly package management.\n"));
     181                 :             : 
     182                 :           0 :   m_output(stdout, _("<standard output>"));
     183                 :             : 
     184                 :           0 :   return 0;
     185                 :             : }
     186                 :             : 
     187                 :             : static const char printforhelp[] = N_(
     188                 :             : "Type dpkg --help for help about installing and deinstalling packages [*];\n"
     189                 :             : "Use 'apt' or 'aptitude' for user-friendly package management;\n"
     190                 :             : "Type dpkg -Dhelp for a list of dpkg debug flag values;\n"
     191                 :             : "Type dpkg --force-help for a list of forcing options;\n"
     192                 :             : "Type dpkg-deb --help for help about manipulating *.deb files;\n"
     193                 :             : "\n"
     194                 :             : "Options marked [*] produce a lot of output - pipe it through 'less' or 'more' !");
     195                 :             : 
     196                 :             : int f_robot = 0;
     197                 :             : int f_pending=0, f_recursive=0, f_alsoselect=1, f_skipsame=0, f_noact=0;
     198                 :             : int f_autodeconf=0, f_nodebsig=0;
     199                 :             : int f_triggers = 0;
     200                 :             : 
     201                 :             : int errabort = 50;
     202                 :             : struct pkg_list *ignoredependss = NULL;
     203                 :             : 
     204                 :             : #define DBG_DEF(n, d) \
     205                 :             :   { .flag = dbg_##n, .name = #n, .desc = d }
     206                 :             : 
     207                 :             : static const struct debuginfo {
     208                 :             :   int flag;
     209                 :             :   const char *name;
     210                 :             :   const char *desc;
     211                 :             : } debuginfos[] = {
     212                 :             :   DBG_DEF(general,         N_("Generally helpful progress information")),
     213                 :             :   DBG_DEF(scripts,         N_("Invocation and status of maintainer scripts")),
     214                 :             :   DBG_DEF(eachfile,        N_("Output for each file processed")),
     215                 :             :   DBG_DEF(eachfiledetail,  N_("Lots of output for each file processed")),
     216                 :             :   DBG_DEF(conff,           N_("Output for each configuration file")),
     217                 :             :   DBG_DEF(conffdetail,     N_("Lots of output for each configuration file")),
     218                 :             :   DBG_DEF(depcon,          N_("Dependencies and conflicts")),
     219                 :             :   DBG_DEF(depcondetail,    N_("Lots of dependencies/conflicts output")),
     220                 :             :   DBG_DEF(triggers,        N_("Trigger activation and processing")),
     221                 :             :   DBG_DEF(triggersdetail,  N_("Lots of output regarding triggers")),
     222                 :             :   DBG_DEF(triggersstupid,  N_("Silly amounts of output regarding triggers")),
     223                 :             :   DBG_DEF(veryverbose,     N_("Lots of drivel about eg the dpkg/info directory")),
     224                 :             :   DBG_DEF(stupidlyverbose, N_("Insane amounts of drivel")),
     225                 :             :   { 0, NULL, NULL }
     226                 :             : };
     227                 :             : 
     228                 :             : static void
     229                 :           0 : set_debug(const struct cmdinfo *cpi, const char *value)
     230                 :             : {
     231                 :             :   long mask;
     232                 :             : 
     233         [ #  # ]:           0 :   if (*value == 'h') {
     234                 :             :     const struct debuginfo *dip;
     235                 :             : 
     236                 :           0 :     printf(_(
     237                 :             : "%s debugging option, --debug=<octal> or -D<octal>:\n"
     238                 :             : "\n"
     239                 :             : " Number  Ref. in source   Description\n"), DPKG);
     240                 :             : 
     241         [ #  # ]:           0 :     for (dip = debuginfos; dip->name; dip++)
     242                 :           0 :       printf(" %6o  %-16s %s\n", dip->flag, dip->name, gettext(dip->desc));
     243                 :             : 
     244                 :           0 :     printf(_("\n"
     245                 :             : "Debugging options can be mixed using bitwise-or.\n"
     246                 :             : "Note that the meanings and values are subject to change.\n"));
     247                 :           0 :     m_output(stdout, _("<standard output>"));
     248                 :           0 :     exit(0);
     249                 :             :   }
     250                 :             : 
     251                 :           0 :   mask = debug_parse_mask(value);
     252         [ #  # ]:           0 :   if (mask < 0)
     253                 :           0 :     badusage(_("--%s requires a positive octal argument"), cpi->olong);
     254                 :           0 : }
     255                 :             : 
     256                 :             : static void
     257                 :           0 : set_no_pager(const struct cmdinfo *ci, const char *value)
     258                 :             : {
     259                 :           0 :   pager_enable(false);
     260                 :             : 
     261                 :             :   /* Let's communicate this to our backends. */
     262                 :           0 :   setenv("DPKG_PAGER", "cat", 1);
     263                 :           0 : }
     264                 :             : 
     265                 :             : static void
     266                 :           0 : set_filter(const struct cmdinfo *cip, const char *value)
     267                 :             : {
     268                 :           0 :   filter_add(value, cip->arg_int);
     269                 :           0 : }
     270                 :             : 
     271                 :             : static void
     272                 :           0 : set_verify_format(const struct cmdinfo *cip, const char *value)
     273                 :             : {
     274         [ #  # ]:           0 :   if (!verify_set_output(value))
     275                 :           0 :     badusage(_("unknown verify output format '%s'"), value);
     276                 :           0 : }
     277                 :             : 
     278                 :             : static void
     279                 :           0 : set_ignore_depends(const struct cmdinfo *cip, const char *value)
     280                 :             : {
     281                 :             :   char *copy, *p;
     282                 :             : 
     283                 :           0 :   copy= m_malloc(strlen(value)+2);
     284                 :           0 :   strcpy(copy,value);
     285                 :           0 :   copy[strlen(value) + 1] = '\0';
     286         [ #  # ]:           0 :   for (p=copy; *p; p++) {
     287         [ #  # ]:           0 :     if (*p != ',') continue;
     288                 :           0 :     *p++ = '\0';
     289   [ #  #  #  #  :           0 :     if (!*p || *p==',' || p==copy+1)
                   #  # ]
     290                 :           0 :       badusage(_("null package name in --%s comma-separated list '%.250s'"),
     291                 :           0 :                cip->olong, value);
     292                 :             :   }
     293                 :           0 :   p= copy;
     294         [ #  # ]:           0 :   while (*p) {
     295                 :             :     struct pkginfo *pkg;
     296                 :             : 
     297                 :           0 :     pkg = dpkg_options_parse_pkgname(cip, p);
     298                 :           0 :     pkg_list_prepend(&ignoredependss, pkg);
     299                 :             : 
     300                 :           0 :     p+= strlen(p)+1;
     301                 :             :   }
     302                 :             : 
     303                 :           0 :   free(copy);
     304                 :           0 : }
     305                 :             : 
     306                 :             : static void
     307                 :           0 : set_integer(const struct cmdinfo *cip, const char *value)
     308                 :             : {
     309                 :           0 :   *cip->iassignto = dpkg_options_parse_arg_int(cip, value);
     310                 :           0 : }
     311                 :             : 
     312                 :             : static void
     313                 :           0 : set_pipe(const struct cmdinfo *cip, const char *value)
     314                 :             : {
     315                 :             :   long v;
     316                 :             : 
     317                 :           0 :   v = dpkg_options_parse_arg_int(cip, value);
     318                 :             : 
     319                 :           0 :   statusfd_add(v);
     320                 :           0 : }
     321                 :             : 
     322                 :             : static bool
     323                 :          96 : is_invoke_action(enum action action)
     324                 :             : {
     325         [ -  + ]:          96 :   switch (action) {
     326                 :           0 :   case act_unpack:
     327                 :             :   case act_configure:
     328                 :             :   case act_install:
     329                 :             :   case act_triggers:
     330                 :             :   case act_remove:
     331                 :             :   case act_purge:
     332                 :             :   case act_arch_add:
     333                 :             :   case act_arch_remove:
     334                 :           0 :     return true;
     335                 :          96 :   default:
     336                 :          96 :     return false;
     337                 :             :   }
     338                 :             : }
     339                 :             : 
     340                 :             : static bool
     341                 :          96 : can_invoke_hooks(enum action action)
     342                 :             : {
     343         [ +  - ]:          96 :   if (!is_invoke_action(action))
     344                 :          96 :     return false;
     345                 :             : 
     346         [ #  # ]:           0 :   if (f_noact)
     347                 :           0 :     return false;
     348                 :             : 
     349         [ #  # ]:           0 :   if (in_force(FORCE_NON_ROOT))
     350                 :           0 :     return true;
     351                 :             : 
     352   [ #  #  #  # ]:           0 :   if (getuid() || geteuid())
     353                 :           0 :     return false;
     354                 :             : 
     355                 :           0 :   return true;
     356                 :             : }
     357                 :             : 
     358                 :             : static struct invoke_list pre_invoke_hooks = {
     359                 :             :   .head = NULL,
     360                 :             :   .tail = &pre_invoke_hooks.head,
     361                 :             : };
     362                 :             : static struct invoke_list post_invoke_hooks = {
     363                 :             :   .head = NULL,
     364                 :             :   .tail = &post_invoke_hooks.head,
     365                 :             : };
     366                 :             : static struct invoke_list status_loggers = {
     367                 :             :   .head = NULL,
     368                 :             :   .tail = &status_loggers.head,
     369                 :             : };
     370                 :             : 
     371                 :             : static void
     372                 :           0 : set_invoke_hook(const struct cmdinfo *cip, const char *value)
     373                 :             : {
     374                 :           0 :   struct invoke_list *hook_list = cip->arg_ptr;
     375                 :             :   struct invoke_hook *hook_new;
     376                 :             : 
     377                 :           0 :   hook_new = m_malloc(sizeof(*hook_new));
     378                 :           0 :   hook_new->command = m_strdup(value);
     379                 :           0 :   hook_new->next = NULL;
     380                 :             : 
     381                 :             :   /* Add the new hook at the tail of the list to preserve the order. */
     382                 :           0 :   *hook_list->tail = hook_new;
     383                 :           0 :   hook_list->tail = &hook_new->next;
     384                 :           0 : }
     385                 :             : 
     386                 :             : static void
     387                 :           0 : run_invoke_hooks(const char *action, struct invoke_list *hook_list)
     388                 :             : {
     389                 :             :   struct invoke_hook *hook;
     390                 :             : 
     391                 :           0 :   setenv("DPKG_HOOK_ACTION", action, 1);
     392                 :             : 
     393         [ #  # ]:           0 :   for (hook = hook_list->head; hook; hook = hook->next) {
     394                 :             :     int status;
     395                 :             : 
     396                 :             :     /* XXX: As an optimization, use exec instead if no shell metachar are
     397                 :             :      * used “!$=&|\\`'"^~;<>{}[]()?*#”. */
     398                 :           0 :     status = system(hook->command);
     399         [ #  # ]:           0 :     if (status != 0)
     400                 :           0 :       ohshit(_("error executing hook '%s', exit code %d"), hook->command,
     401                 :             :              status);
     402                 :             :   }
     403                 :             : 
     404                 :           0 :   unsetenv("DPKG_HOOK_ACTION");
     405                 :           0 : }
     406                 :             : 
     407                 :             : static void
     408                 :          96 : free_invoke_hooks(struct invoke_list *hook_list)
     409                 :             : {
     410                 :             :   struct invoke_hook *hook, *hook_next;
     411                 :             : 
     412         [ -  + ]:          96 :   for (hook = hook_list->head; hook; hook = hook_next) {
     413                 :           0 :     hook_next = hook->next;
     414                 :           0 :     free(hook->command);
     415                 :           0 :     free(hook);
     416                 :             :   }
     417                 :          96 : }
     418                 :             : 
     419                 :             : static int
     420                 :           0 : run_logger(struct invoke_hook *hook, const char *name)
     421                 :             : {
     422                 :             :   pid_t pid;
     423                 :             :   int p[2];
     424                 :             : 
     425                 :           0 :   m_pipe(p);
     426                 :             : 
     427                 :           0 :   pid = subproc_fork();
     428         [ #  # ]:           0 :   if (pid == 0) {
     429                 :             :     /* Setup stdin and stdout. */
     430                 :           0 :     m_dup2(p[0], 0);
     431                 :           0 :     close(1);
     432                 :             : 
     433                 :           0 :     close(p[0]);
     434                 :           0 :     close(p[1]);
     435                 :             : 
     436                 :           0 :     command_shell(hook->command, name);
     437                 :             :   }
     438                 :           0 :   close(p[0]);
     439                 :             : 
     440                 :           0 :   return p[1];
     441                 :             : }
     442                 :             : 
     443                 :             : static void
     444                 :           0 : run_status_loggers(struct invoke_list *hook_list)
     445                 :             : {
     446                 :             :   struct invoke_hook *hook;
     447                 :             : 
     448         [ #  # ]:           0 :   for (hook = hook_list->head; hook; hook = hook->next) {
     449                 :             :     int fd;
     450                 :             : 
     451                 :           0 :     fd = run_logger(hook, _("status logger"));
     452                 :           0 :     statusfd_add(fd);
     453                 :             :   }
     454                 :           0 : }
     455                 :             : 
     456                 :             : static int
     457                 :           0 : arch_add(const char *const *argv)
     458                 :             : {
     459                 :             :   struct dpkg_arch *arch;
     460                 :           0 :   const char *archname = *argv++;
     461                 :             : 
     462   [ #  #  #  # ]:           0 :   if (archname == NULL || *argv)
     463                 :           0 :     badusage(_("--%s takes exactly one argument"), cipaction->olong);
     464                 :             : 
     465                 :           0 :   dpkg_arch_load_list();
     466                 :             : 
     467                 :           0 :   arch = dpkg_arch_add(archname);
     468      [ #  #  # ]:           0 :   switch (arch->type) {
     469                 :           0 :   case DPKG_ARCH_NATIVE:
     470                 :             :   case DPKG_ARCH_FOREIGN:
     471                 :           0 :     break;
     472                 :           0 :   case DPKG_ARCH_ILLEGAL:
     473                 :           0 :     ohshit(_("architecture '%s' is illegal: %s"), archname,
     474                 :             :            dpkg_arch_name_is_illegal(archname));
     475                 :           0 :   default:
     476                 :           0 :     ohshit(_("architecture '%s' is reserved and cannot be added"), archname);
     477                 :             :   }
     478                 :             : 
     479                 :           0 :   dpkg_arch_save_list();
     480                 :             : 
     481                 :           0 :   return 0;
     482                 :             : }
     483                 :             : 
     484                 :             : static int
     485                 :           0 : arch_remove(const char *const *argv)
     486                 :             : {
     487                 :           0 :   const char *archname = *argv++;
     488                 :             :   struct dpkg_arch *arch;
     489                 :             :   struct pkg_hash_iter *iter;
     490                 :             :   struct pkginfo *pkg;
     491                 :             : 
     492   [ #  #  #  # ]:           0 :   if (archname == NULL || *argv)
     493                 :           0 :     badusage(_("--%s takes exactly one argument"), cipaction->olong);
     494                 :             : 
     495                 :           0 :   modstatdb_open(msdbrw_readonly);
     496                 :             : 
     497                 :           0 :   arch = dpkg_arch_find(archname);
     498         [ #  # ]:           0 :   if (arch->type != DPKG_ARCH_FOREIGN) {
     499                 :           0 :     warning(_("cannot remove non-foreign architecture '%s'"), arch->name);
     500                 :           0 :     return 0;
     501                 :             :   }
     502                 :             : 
     503                 :             :   /* Check if it's safe to remove the architecture from the db. */
     504                 :           0 :   iter = pkg_hash_iter_new();
     505         [ #  # ]:           0 :   while ((pkg = pkg_hash_iter_next_pkg(iter))) {
     506         [ #  # ]:           0 :     if (pkg->status < PKG_STAT_HALFINSTALLED)
     507                 :           0 :       continue;
     508         [ #  # ]:           0 :     if (pkg->installed.arch == arch) {
     509         [ #  # ]:           0 :       if (in_force(FORCE_ARCHITECTURE))
     510                 :           0 :         warning(_("removing architecture '%s' currently in use by database"),
     511                 :             :                 arch->name);
     512                 :             :       else
     513                 :           0 :         ohshit(_("cannot remove architecture '%s' currently in use by the database"),
     514                 :             :                arch->name);
     515                 :           0 :       break;
     516                 :             :     }
     517                 :             :   }
     518                 :           0 :   pkg_hash_iter_free(iter);
     519                 :             : 
     520                 :           0 :   dpkg_arch_unmark(arch);
     521                 :           0 :   dpkg_arch_save_list();
     522                 :             : 
     523                 :           0 :   modstatdb_shutdown();
     524                 :             : 
     525                 :           0 :   return 0;
     526                 :             : }
     527                 :             : 
     528                 :             : int execbackend(const char *const *argv) DPKG_ATTR_NORET;
     529                 :             : int commandfd(const char *const *argv);
     530                 :             : 
     531                 :             : /* This table has both the action entries in it and the normal options.
     532                 :             :  * The action entries are made with the ACTION macro, as they all
     533                 :             :  * have a very similar structure. */
     534                 :             : static const struct cmdinfo cmdinfos[]= {
     535                 :             : #define ACTIONBACKEND(longopt, shortopt, backend) \
     536                 :             :  { longopt, shortopt, 0, NULL, NULL, setaction, 0, (void *)backend, execbackend }
     537                 :             : 
     538                 :             :   ACTION( "install",                        'i', act_install,              archivefiles    ),
     539                 :             :   ACTION( "unpack",                          0,  act_unpack,               archivefiles    ),
     540                 :             :   ACTION( "record-avail",                   'A', act_avail,                archivefiles    ),
     541                 :             :   ACTION( "configure",                       0,  act_configure,            packages        ),
     542                 :             :   ACTION( "remove",                         'r', act_remove,               packages        ),
     543                 :             :   ACTION( "purge",                          'P', act_purge,                packages        ),
     544                 :             :   ACTION( "triggers-only",                   0,  act_triggers,             packages        ),
     545                 :             :   ACTION( "verify",                         'V', act_verify,               verify          ),
     546                 :             :   ACTIONBACKEND( "listfiles",               'L', DPKGQUERY),
     547                 :             :   ACTIONBACKEND( "status",                  's', DPKGQUERY),
     548                 :             :   ACTION( "get-selections",                  0,  act_getselections,        getselections   ),
     549                 :             :   ACTION( "set-selections",                  0,  act_setselections,        setselections   ),
     550                 :             :   ACTION( "clear-selections",                0,  act_clearselections,      clearselections ),
     551                 :             :   ACTIONBACKEND( "print-avail",             'p', DPKGQUERY),
     552                 :             :   ACTION( "update-avail",                    0,  act_avreplace,            updateavailable ),
     553                 :             :   ACTION( "merge-avail",                     0,  act_avmerge,              updateavailable ),
     554                 :             :   ACTION( "clear-avail",                     0,  act_avclear,              updateavailable ),
     555                 :             :   ACTION( "forget-old-unavail",              0,  act_forgetold,            forgetold       ),
     556                 :             :   ACTION( "audit",                          'C', act_audit,                audit           ),
     557                 :             :   ACTION( "yet-to-unpack",                   0,  act_unpackchk,            unpackchk       ),
     558                 :             :   ACTIONBACKEND( "list",                    'l', DPKGQUERY),
     559                 :             :   ACTIONBACKEND( "search",                  'S', DPKGQUERY),
     560                 :             :   ACTION_MUX( "assert",                      0,  act_assert_feature,       assert_feature, &assert_feature_name),
     561                 :             :   ACTION( "add-architecture",                0,  act_arch_add,             arch_add        ),
     562                 :             :   ACTION( "remove-architecture",             0,  act_arch_remove,          arch_remove     ),
     563                 :             :   ACTION( "print-architecture",              0,  act_printarch,            printarch   ),
     564                 :             :   ACTION( "print-foreign-architectures",     0,  act_printforeignarches,   print_foreign_arches ),
     565                 :             :   ACTION( "predep-package",                  0,  act_predeppackage,        predeppackage   ),
     566                 :             :   ACTION( "validate-pkgname",                0,  act_validate_pkgname,     validate_pkgname ),
     567                 :             :   ACTION( "validate-trigname",               0,  act_validate_trigname,    validate_trigname ),
     568                 :             :   ACTION( "validate-archname",               0,  act_validate_archname,    validate_archname ),
     569                 :             :   ACTION( "validate-version",                0,  act_validate_version,     validate_version ),
     570                 :             :   ACTION( "compare-versions",                0,  act_cmpversions,          cmpversions     ),
     571                 :             : /*
     572                 :             :   ACTION( "command-fd",                   'c', act_commandfd,   commandfd     ),
     573                 :             : */
     574                 :             :   ACTION( "help",                           '?', act_help,                 usage),
     575                 :             :   ACTION( "version",                         0,  act_version,              printversion),
     576                 :             : 
     577                 :             :   { "pre-invoke",        0,   1, NULL,          NULL,      set_invoke_hook, 0, &pre_invoke_hooks },
     578                 :             :   { "post-invoke",       0,   1, NULL,          NULL,      set_invoke_hook, 0, &post_invoke_hooks },
     579                 :             :   { "path-exclude",      0,   1, NULL,          NULL,      set_filter,     0 },
     580                 :             :   { "path-include",      0,   1, NULL,          NULL,      set_filter,     1 },
     581                 :             :   { "verify-format",     0,   1, NULL,          NULL,      set_verify_format },
     582                 :             :   { "status-logger",     0,   1, NULL,          NULL,      set_invoke_hook, 0, &status_loggers },
     583                 :             :   { "status-fd",         0,   1, NULL,          NULL,      set_pipe, 0 },
     584                 :             :   { "log",               0,   1, NULL,          &log_file, NULL,    0 },
     585                 :             :   { "pending",           'a', 0, &f_pending,    NULL,      NULL,    1 },
     586                 :             :   { "recursive",         'R', 0, &f_recursive,  NULL,      NULL,    1 },
     587                 :             :   { "no-act",            0,   0, &f_noact,      NULL,      NULL,    1 },
     588                 :             :   { "dry-run",           0,   0, &f_noact,      NULL,      NULL,    1 },
     589                 :             :   { "simulate",          0,   0, &f_noact,      NULL,      NULL,    1 },
     590                 :             :   { "no-pager",          0,   0, NULL,          NULL,      set_no_pager,  0 },
     591                 :             :   { "no-debsig",         0,   0, &f_nodebsig,   NULL,      NULL,    1 },
     592                 :             :   /* Alias ('G') for --refuse. */
     593                 :             :   {  NULL,               'G', 0, NULL,          NULL,      reset_force_option, FORCE_DOWNGRADE },
     594                 :             :   { "selected-only",     'O', 0, &f_alsoselect, NULL,      NULL,    0 },
     595                 :             :   { "triggers",           0,  0, &f_triggers,   NULL,      NULL,    1 },
     596                 :             :   { "no-triggers",        0,  0, &f_triggers,   NULL,      NULL,   -1 },
     597                 :             :   /* TODO: Remove ('N') sometime. */
     598                 :             :   { "no-also-select",    'N', 0, &f_alsoselect, NULL,      NULL,    0 },
     599                 :             :   { "skip-same-version", 'E', 0, &f_skipsame,   NULL,      NULL,    1 },
     600                 :             :   { "auto-deconfigure",  'B', 0, &f_autodeconf, NULL,      NULL,    1 },
     601                 :             :   { "robot",             0,   0, &f_robot,      NULL,      NULL,    1 },
     602                 :             :   { "root",              0,   1, NULL,          NULL,      set_root,      0 },
     603                 :             :   { "abort-after",       0,   1, &errabort,     NULL,      set_integer,   0 },
     604                 :             :   { "admindir",          0,   1, NULL,          NULL,      set_admindir,  0 },
     605                 :             :   { "instdir",           0,   1, NULL,          NULL,      set_instdir,   0 },
     606                 :             :   { "ignore-depends",    0,   1, NULL,          NULL,      set_ignore_depends, 0 },
     607                 :             :   { "force",             0,   2, NULL,          NULL,      set_force_option,   1 },
     608                 :             :   { "refuse",            0,   2, NULL,          NULL,      set_force_option,   0 },
     609                 :             :   { "no-force",          0,   2, NULL,          NULL,      set_force_option,   0 },
     610                 :             :   { "debug",             'D', 1, NULL,          NULL,      set_debug,     0 },
     611                 :             :   ACTIONBACKEND( "build",             'b', BACKEND),
     612                 :             :   ACTIONBACKEND( "contents",          'c', BACKEND),
     613                 :             :   ACTIONBACKEND( "control",           'e', BACKEND),
     614                 :             :   ACTIONBACKEND( "info",              'I', BACKEND),
     615                 :             :   ACTIONBACKEND( "field",             'f', BACKEND),
     616                 :             :   ACTIONBACKEND( "extract",           'x', BACKEND),
     617                 :             :   ACTIONBACKEND( "vextract",          'X', BACKEND),
     618                 :             :   ACTIONBACKEND( "ctrl-tarfile",      0,   BACKEND),
     619                 :             :   ACTIONBACKEND( "fsys-tarfile",      0,   BACKEND),
     620                 :             :   { NULL,                0,   0, NULL,          NULL,      NULL,          0 }
     621                 :             : };
     622                 :             : 
     623                 :             : int
     624                 :           0 : execbackend(const char *const *argv)
     625                 :             : {
     626                 :             :   struct command cmd;
     627                 :             : 
     628                 :           0 :   command_init(&cmd, cipaction->arg_ptr, NULL);
     629                 :           0 :   command_add_arg(&cmd, cipaction->arg_ptr);
     630                 :           0 :   command_add_arg(&cmd, str_fmt("--%s", cipaction->olong));
     631                 :             : 
     632                 :             :   /* Explicitly separate arguments from options as any user-supplied
     633                 :             :    * separator got stripped by the option parser */
     634                 :           0 :   command_add_arg(&cmd, "--");
     635                 :           0 :   command_add_argl(&cmd, (const char **)argv);
     636                 :             : 
     637                 :           0 :   command_exec(&cmd);
     638                 :             : }
     639                 :             : 
     640                 :             : int
     641                 :           0 : commandfd(const char *const *argv)
     642                 :             : {
     643                 :           0 :   struct varbuf linevb = VARBUF_INIT;
     644                 :             :   const char * pipein;
     645                 :           0 :   const char **newargs = NULL, **endargs;
     646                 :             :   char *ptr, *endptr;
     647                 :             :   FILE *in;
     648                 :             :   long infd;
     649                 :           0 :   int ret = 0;
     650                 :             :   int c, lno, i;
     651                 :             :   bool skipchar;
     652                 :             : 
     653                 :           0 :   pipein = *argv++;
     654   [ #  #  #  # ]:           0 :   if (pipein == NULL || *argv)
     655                 :           0 :     badusage(_("--%s takes exactly one argument"), cipaction->olong);
     656                 :             : 
     657                 :           0 :   infd = dpkg_options_parse_arg_int(cipaction, pipein);
     658                 :           0 :   in = fdopen(infd, "r");
     659         [ #  # ]:           0 :   if (in == NULL)
     660                 :           0 :     ohshite(_("couldn't open '%i' for stream"), (int)infd);
     661                 :             : 
     662                 :           0 :   lno = 0;
     663                 :             : 
     664                 :           0 :   for (;;) {
     665                 :           0 :     bool mode = false;
     666                 :           0 :     int argc= 1;
     667                 :             : 
     668                 :           0 :     push_error_context();
     669                 :             : 
     670                 :             :     do {
     671                 :           0 :       c = getc(in);
     672         [ #  # ]:           0 :       if (c == '\n')
     673                 :           0 :         lno++;
     674   [ #  #  #  # ]:           0 :     } while (c != EOF && c_isspace(c));
     675         [ #  # ]:           0 :     if (c == EOF) break;
     676         [ #  # ]:           0 :     if (c == '#') {
     677   [ #  #  #  #  :           0 :       do { c= getc(in); if (c == '\n') lno++; } while (c != EOF && c != '\n');
                   #  # ]
     678                 :           0 :       continue;
     679                 :             :     }
     680                 :           0 :     varbuf_reset(&linevb);
     681                 :             :     do {
     682                 :           0 :       varbuf_add_char(&linevb, c);
     683                 :           0 :       c= getc(in);
     684         [ #  # ]:           0 :       if (c == '\n') lno++;
     685                 :             : 
     686                 :             :       /* This isn't fully accurate, but overestimating can't hurt. */
     687         [ #  # ]:           0 :       if (c_isspace(c))
     688                 :           0 :         argc++;
     689   [ #  #  #  # ]:           0 :     } while (c != EOF && c != '\n');
     690         [ #  # ]:           0 :     if (c == EOF)
     691                 :           0 :       ohshit(_("unexpected end of file before end of line %d"), lno);
     692         [ #  # ]:           0 :     if (!argc) continue;
     693                 :           0 :     newargs = m_realloc(newargs, sizeof(const char *) * (argc + 1));
     694                 :           0 :     argc= 1;
     695                 :           0 :     ptr= linevb.buf;
     696                 :           0 :     endptr = ptr + linevb.used + 1;
     697                 :           0 :     skipchar = false;
     698         [ #  # ]:           0 :     while(ptr < endptr) {
     699         [ #  # ]:           0 :       if (skipchar) {
     700                 :           0 :         skipchar = false;
     701         [ #  # ]:           0 :       } else if (*ptr == '\\') {
     702                 :           0 :         memmove(ptr, (ptr+1), (linevb.used-(linevb.buf - ptr)-1));
     703                 :           0 :         endptr--;
     704                 :           0 :         skipchar = true;
     705                 :           0 :         continue;
     706         [ #  # ]:           0 :       } else if (c_isspace(*ptr)) {
     707         [ #  # ]:           0 :         if (mode == true) {
     708                 :           0 :           *ptr = '\0';
     709                 :           0 :           mode = false;
     710                 :             :         }
     711                 :             :       } else {
     712         [ #  # ]:           0 :         if (mode == false) {
     713                 :           0 :           newargs[argc]= ptr;
     714                 :           0 :           argc++;
     715                 :           0 :           mode = true;
     716                 :             :         }
     717                 :             :       }
     718                 :           0 :       ptr++;
     719                 :             :     }
     720                 :           0 :     *ptr = '\0';
     721                 :           0 :     newargs[argc++] = NULL;
     722                 :             : 
     723                 :             :     /* We strdup() each argument, but never free it, because the
     724                 :             :      * error messages contain references back to these strings.
     725                 :             :      * Freeing them, and reusing the memory, would make those
     726                 :             :      * error messages confusing, to say the least. */
     727         [ #  # ]:           0 :     for(i=1;i<argc;i++)
     728         [ #  # ]:           0 :       if (newargs[i])
     729                 :           0 :         newargs[i] = m_strdup(newargs[i]);
     730                 :           0 :     endargs = newargs;
     731                 :             : 
     732                 :           0 :     setaction(NULL, NULL);
     733                 :           0 :     dpkg_options_parse((const char *const **)&endargs, cmdinfos, printforhelp);
     734         [ #  # ]:           0 :     if (!cipaction) badusage(_("need an action option"));
     735                 :             : 
     736                 :           0 :     ret |= cipaction->action(endargs);
     737                 :             : 
     738                 :           0 :     fsys_hash_reset();
     739                 :             : 
     740                 :           0 :     pop_error_context(ehflag_normaltidy);
     741                 :             :   }
     742                 :             : 
     743                 :           0 :   fclose(in);
     744                 :             : 
     745                 :           0 :   return ret;
     746                 :             : }
     747                 :             : 
     748                 :          48 : int main(int argc, const char *const *argv) {
     749                 :             :   char *force_string;
     750                 :             :   int ret;
     751                 :             : 
     752                 :          48 :   dpkg_locales_init(PACKAGE);
     753                 :          48 :   dpkg_program_init("dpkg");
     754                 :          48 :   set_force_default(FORCE_ALL);
     755                 :          48 :   dpkg_options_load(DPKG, cmdinfos);
     756                 :          48 :   dpkg_options_parse(&argv, cmdinfos, printforhelp);
     757                 :             : 
     758                 :          48 :   debug(dbg_general, "root=%s admindir=%s", dpkg_fsys_get_dir(), dpkg_db_get_dir());
     759                 :             : 
     760                 :             :   /* When running as root, make sure our primary group is also root, so
     761                 :             :    * that files created by maintainer scripts have correct ownership. */
     762   [ +  -  -  +  :          48 :   if (!in_force(FORCE_NON_ROOT) && getuid() == 0 && getgid() != 0)
                   -  - ]
     763         [ #  # ]:           0 :     if (setgid(0) < 0)
     764                 :           0 :       ohshite(_("cannot set primary group ID to root"));
     765                 :             : 
     766         [ -  + ]:          48 :   if (!cipaction) badusage(_("need an action option"));
     767                 :             : 
     768                 :             :   /* Always set environment, to avoid possible security risks. */
     769         [ -  + ]:          48 :   if (setenv("DPKG_ADMINDIR", dpkg_db_get_dir(), 1) < 0)
     770                 :           0 :     ohshite(_("unable to setenv for subprocesses"));
     771         [ -  + ]:          48 :   if (setenv("DPKG_ROOT", dpkg_fsys_get_dir(), 1) < 0)
     772                 :           0 :     ohshite(_("unable to setenv for subprocesses"));
     773                 :          48 :   force_string = get_force_string();
     774         [ -  + ]:          48 :   if (setenv("DPKG_FORCE", force_string, 1) < 0)
     775                 :           0 :     ohshite(_("unable to setenv for subprocesses"));
     776                 :          48 :   free(force_string);
     777                 :             : 
     778         [ +  - ]:          48 :   if (!f_triggers)
     779   [ -  +  -  - ]:          48 :     f_triggers = (cipaction->arg_int == act_triggers && *argv) ? -1 : 1;
     780                 :             : 
     781         [ -  + ]:          48 :   if (can_invoke_hooks(cipaction->arg_int)) {
     782                 :           0 :     run_invoke_hooks(cipaction->olong, &pre_invoke_hooks);
     783                 :           0 :     run_status_loggers(&status_loggers);
     784                 :             :   }
     785                 :             : 
     786                 :          48 :   ret = cipaction->action(argv);
     787                 :             : 
     788         [ -  + ]:          48 :   if (can_invoke_hooks(cipaction->arg_int))
     789                 :           0 :     run_invoke_hooks(cipaction->olong, &post_invoke_hooks);
     790                 :             : 
     791                 :          48 :   free_invoke_hooks(&pre_invoke_hooks);
     792                 :          48 :   free_invoke_hooks(&post_invoke_hooks);
     793                 :             : 
     794                 :          48 :   dpkg_program_done();
     795                 :          48 :   dpkg_locales_done();
     796                 :             : 
     797                 :          48 :   return reportbroken_retexitstatus(ret);
     798                 :             : }
        

Generated by: LCOV version 2.0-1