LCOV - code coverage report
Current view: top level - src - main.c (source / functions) Hit Total Coverage
Test: rapport Lines: 195 416 46.9 %
Date: 2021-12-10 16:22:55 Functions: 9 13 69.2 %
Branches: 41 133 30.8 %

           Branch data     Line data    Source code
       1                 :            : /*-
       2                 :            :  * Copyright (c) 2011-2013 Baptiste Daroussin <bapt@FreeBSD.org>
       3                 :            :  * Copyright (c) 2011-2012 Julien Laffaye <jlaffaye@FreeBSD.org>
       4                 :            :  * Copyright (c) 2011 Will Andrews <will@FreeBSD.org>
       5                 :            :  * Copyright (c) 2011-2012 Marin Atanasov Nikolov <dnaeon@gmail.com>
       6                 :            :  * Copyright (c) 2014-2015 Matthew Seaman <matthew@FreeBSD.org>
       7                 :            :  * Copyright (c) 2014 Vsevolod Stakhov <vsevolod@FreeBSD.org>
       8                 :            :  * All rights reserved.
       9                 :            :  *
      10                 :            :  * Redistribution and use in source and binary forms, with or without
      11                 :            :  * modification, are permitted provided that the following conditions
      12                 :            :  * are met:
      13                 :            :  * 1. Redistributions of source code must retain the above copyright
      14                 :            :  *    notice, this list of conditions and the following disclaimer
      15                 :            :  *    in this position and unchanged.
      16                 :            :  * 2. Redistributions in binary form must reproduce the above copyright
      17                 :            :  *    notice, this list of conditions and the following disclaimer in the
      18                 :            :  *    documentation and/or other materials provided with the distribution.
      19                 :            :  *
      20                 :            :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
      21                 :            :  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
      22                 :            :  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
      23                 :            :  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
      24                 :            :  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
      25                 :            :  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      26                 :            :  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      27                 :            :  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      28                 :            :  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
      29                 :            :  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      30                 :            :  */
      31                 :            : 
      32                 :            : #ifdef HAVE_CONFIG_H
      33                 :            : #include "pkg_config.h"
      34                 :            : #endif
      35                 :            : 
      36                 :            : #include <sys/param.h>
      37                 :            : 
      38                 :            : #include <sys/stat.h>
      39                 :            : #include <sys/queue.h>
      40                 :            : #include <sys/types.h>
      41                 :            : #include <sys/wait.h>
      42                 :            : #ifdef __FreeBSD__
      43                 :            : #include <sys/sysctl.h>
      44                 :            : #include <sys/user.h>
      45                 :            : #include <sys/proc.h>
      46                 :            : #endif
      47                 :            : 
      48                 :            : #include <assert.h>
      49                 :            : #include <ctype.h>
      50                 :            : #include <err.h>
      51                 :            : #include <errno.h>
      52                 :            : #include <getopt.h>
      53                 :            : #include <inttypes.h>
      54                 :            : #include <stdio.h>
      55                 :            : #include <stdlib.h>
      56                 :            : #include <string.h>
      57                 :            : #include <utlist.h>
      58                 :            : #include <unistd.h>
      59                 :            : #ifdef HAVE_LIBJAIL
      60                 :            : #include <jail.h>
      61                 :            : #include <sys/jail.h>
      62                 :            : #endif
      63                 :            : #include <signal.h>
      64                 :            : 
      65                 :            : #include <pkg.h>
      66                 :            : 
      67                 :            : #include "pkgcli.h"
      68                 :            : 
      69                 :            : /* Used to define why do we show usage message to a user */
      70                 :            : enum pkg_usage_reason {
      71                 :            :         PKG_USAGE_ERROR,
      72                 :            :         PKG_USAGE_UNKNOWN_COMMAND,
      73                 :            :         PKG_USAGE_INVALID_ARGUMENTS,
      74                 :            :         PKG_USAGE_HELP
      75                 :            : };
      76                 :            : 
      77                 :            : static void usage(const char *, const char *, FILE *, enum pkg_usage_reason, ...);
      78                 :            : static void usage_help(void);
      79                 :            : static int exec_help(int, char **);
      80                 :            : 
      81                 :            : static struct commands {
      82                 :            :         const char * const name;
      83                 :            :         const char * const desc;
      84                 :            :         int (*exec)(int argc, char **argv);
      85                 :            :         void (* const usage)(void);
      86                 :            : } cmd[] = {
      87                 :            :         { "add", "Compatibility interface to install a package", exec_add, usage_add},
      88                 :            :         { "alias", "List the command line aliases", exec_alias, usage_alias},
      89                 :            :         { "annotate", "Add, modify or delete tag-value style annotations on packages", exec_annotate, usage_annotate},
      90                 :            :         { "audit", "Reports vulnerable packages", exec_audit, usage_audit},
      91                 :            :         { "autoremove", "Removes orphan packages", exec_autoremove, usage_autoremove},
      92                 :            :         { "backup", "Backs-up and restores the local package database", exec_backup, usage_backup},
      93                 :            :         { "check", "Checks for missing dependencies and database consistency", exec_check, usage_check},
      94                 :            :         { "clean", "Cleans old packages from the cache", exec_clean, usage_clean},
      95                 :            :         { "config", "Display the value of the configuration options", exec_config, usage_config},
      96                 :            :         { "create", "Creates software package distributions", exec_create, usage_create},
      97                 :            :         { "delete", "Deletes packages from the database and the system", exec_delete, usage_delete},
      98                 :            :         { "fetch", "Fetches packages from a remote repository", exec_fetch, usage_fetch},
      99                 :            :         { "help", "Displays help information", exec_help, usage_help},
     100                 :            :         { "info", "Displays information about installed packages", exec_info, usage_info},
     101                 :            :         { "install", "Installs packages from remote package repositories and local archives", exec_install, usage_install},
     102                 :            :         { "lock", "Locks package against modifications or deletion", exec_lock, usage_lock},
     103                 :            :         { "plugins", "Manages plugins and displays information about plugins", exec_plugins, usage_plugins},
     104                 :            :         { "query", "Queries information about installed packages", exec_query, usage_query},
     105                 :            :         { "register", "Registers a package into the local database", exec_register, usage_register},
     106                 :            :         { "remove", "Deletes packages from the database and the system", exec_delete, usage_delete},
     107                 :            :         { "repo", "Creates a package repository catalogue", exec_repo, usage_repo},
     108                 :            :         { "rquery", "Queries information in repository catalogues", exec_rquery, usage_rquery},
     109                 :            :         { "search", "Performs a search of package repository catalogues", exec_search, usage_search},
     110                 :            :         { "set", "Modifies information about packages in the local database", exec_set, usage_set},
     111                 :            :         { "ssh", "Package server (to be used via ssh)", exec_ssh, usage_ssh},
     112                 :            :         { "shell", "Opens a debug shell", exec_shell, usage_shell},
     113                 :            :         { "shlib", "Displays which packages link against a specific shared library", exec_shlib, usage_shlib},
     114                 :            :         { "stats", "Displays package database statistics", exec_stats, usage_stats},
     115                 :            :         { "triggers", "Execute deferred triggers", exec_triggers, usage_triggers},
     116                 :            :         { "unlock", "Unlocks a package, allowing modification or deletion", exec_unlock, usage_lock},
     117                 :            :         { "update", "Updates package repository catalogues", exec_update, usage_update},
     118                 :            :         { "updating", "Displays UPDATING information for a package", exec_updating, usage_updating},
     119                 :            :         { "upgrade", "Performs upgrades of packaged software distributions", exec_upgrade, usage_upgrade},
     120                 :            :         { "version", "Displays the versions of installed packages", exec_version, usage_version},
     121                 :            :         { "which", "Displays which package installed a specific file", exec_which, usage_which},
     122                 :            : };
     123                 :            : 
     124                 :            : static const unsigned int cmd_len = NELEM(cmd);
     125                 :            : 
     126                 :            : struct plugcmd {
     127                 :            :         const char *name;
     128                 :            :         const char *desc;
     129                 :            :         int (*exec)(int argc, char **argv);
     130                 :            :         struct plugcmd *next;
     131                 :            :         struct plugcmd *prev;
     132                 :            : };
     133                 :            : static struct plugcmd *plugins = NULL;
     134                 :            : 
     135                 :            : typedef int (register_cmd)(int idx, const char **name, const char **desc, int (**exec)(int argc, char **argv));
     136                 :            : typedef int (nb_cmd)(void);
     137                 :            : 
     138                 :            : static void
     139                 :          0 : show_command_names(void)
     140                 :            : {
     141                 :            :         unsigned        i;
     142                 :            : 
     143         [ #  # ]:          0 :         for(i = 0; i < cmd_len; i++)
     144                 :          0 :                 printf("%s\n", cmd[i].name);
     145                 :            : 
     146                 :          0 :         return;
     147                 :            : }
     148                 :            : 
     149                 :            : static void
     150                 :          0 : usage(const char *conffile, const char *reposdir, FILE *out, enum pkg_usage_reason reason, ...)
     151                 :            : {
     152                 :            :         struct plugcmd *c;
     153                 :          0 :         bool plugins_enabled = false;
     154                 :            :         unsigned int i;
     155                 :            :         const char *arg;
     156                 :            :         va_list vp;
     157                 :            : 
     158         [ #  # ]:          0 :         if (reason == PKG_USAGE_UNKNOWN_COMMAND) {
     159                 :          0 :                 va_start(vp, reason);
     160         [ #  # ]:          0 :                 arg = va_arg(vp, const char *);
     161                 :          0 :                 va_end(vp);
     162                 :          0 :                 fprintf(out, "pkg: unknown command: %s\n", arg);
     163                 :          0 :                 goto out;
     164                 :            :         }
     165                 :          0 :         else if (reason == PKG_USAGE_INVALID_ARGUMENTS) {
     166                 :          0 :                 va_start(vp, reason);
     167         [ #  # ]:          0 :                 arg = va_arg(vp, const char *);
     168                 :          0 :                 va_end(vp);
     169                 :          0 :                 fprintf(out, "pkg: %s\n", arg);
     170                 :          0 :         }
     171                 :            : 
     172                 :            : #ifdef HAVE_LIBJAIL
     173                 :            : #define JAIL_ARG        "-j <jail name or id>|"
     174                 :            : #else
     175                 :            : #define JAIL_ARG
     176                 :            : #endif
     177                 :          0 :         fprintf(out, "Usage: pkg [-v] [-d] [-l] [-N] ["JAIL_ARG"-c <chroot path>|-r <rootdir>] [-C <configuration file>] [-R <repo config dir>] [-o var=value] [-4|-6] <command> [<args>]\n");
     178         [ #  # ]:          0 :         if (reason == PKG_USAGE_HELP) {
     179                 :          0 :                 fprintf(out, "Global options supported:\n");
     180                 :          0 :                 fprintf(out, "\t%-15s%s\n", "-d", "Increment debug level");
     181                 :            : #ifdef HAVE_LIBJAIL
     182                 :          0 :                 fprintf(out, "\t%-15s%s\n", "-j", "Execute pkg(8) inside a jail(8)");
     183                 :            : #endif
     184                 :          0 :                 fprintf(out, "\t%-15s%s\n", "-r", "Execute pkg(8) using relocating installation to <rootdir>");
     185                 :          0 :                 fprintf(out, "\t%-15s%s\n", "-c", "Execute pkg(8) inside a chroot(8)");
     186                 :          0 :                 fprintf(out, "\t%-15s%s\n", "-C", "Use the specified configuration file");
     187                 :          0 :                 fprintf(out, "\t%-15s%s\n", "-R", "Directory to search for individual repository configurations");
     188                 :          0 :                 fprintf(out, "\t%-15s%s\n", "-l", "List available commands and exit");
     189                 :          0 :                 fprintf(out, "\t%-15s%s\n", "-v", "Display pkg(8) version");
     190                 :          0 :                 fprintf(out, "\t%-15s%s\n", "-N", "Test if pkg(8) is activated and avoid auto-activation");
     191                 :          0 :                 fprintf(out, "\t%-15s%s\n", "-o", "Override configuration option from the command line");
     192                 :          0 :                 fprintf(out, "\t%-15s%s\n", "-4", "Only use IPv4");
     193                 :          0 :                 fprintf(out, "\t%-15s%s\n", "-6", "Only use IPv6");
     194                 :          0 :                 fprintf(out, "\nCommands supported:\n");
     195                 :            : 
     196         [ #  # ]:          0 :                 for (i = 0; i < cmd_len; i++)
     197                 :          0 :                         fprintf(out, "\t%-15s%s\n", cmd[i].name, cmd[i].desc);
     198                 :            : 
     199                 :          0 :                 if (!pkg_initialized() && pkg_ini(conffile, reposdir, 0) != EPKG_OK)
     200                 :          0 :                         errx(EXIT_FAILURE, "Cannot parse configuration file!");
     201                 :            : 
     202                 :          0 :                 plugins_enabled = pkg_object_bool(pkg_config_get("PKG_ENABLE_PLUGINS"));
     203                 :            : 
     204                 :          0 :                 if (plugins_enabled) {
     205         [ #  # ]:          0 :                         if (pkg_plugins_init() != EPKG_OK)
     206                 :          0 :                                 errx(EXIT_FAILURE, "Plugins cannot be loaded");
     207                 :            : 
     208                 :          0 :                         fprintf(out, "\nCommands provided by plugins:\n");
     209                 :            : 
     210         [ #  # ]:          0 :                         DL_FOREACH(plugins, c) {
     211                 :          0 :                                 fprintf(out, "\t%-15s%s\n", c->name, c->desc);
     212                 :          0 :                         }
     213                 :          0 :                 }
     214                 :          0 :                 fprintf(out, "\nFor more information on the different commands"
     215                 :            :                                         " see 'pkg help <command>'.\n");
     216                 :          0 :                 exit(EXIT_SUCCESS);
     217                 :            :         }
     218                 :            : 
     219                 :            : out:
     220                 :          0 :         fprintf(out, "\nFor more information on available commands and options see 'pkg help'.\n");
     221                 :          0 :         exit(EXIT_FAILURE);
     222                 :            : }
     223                 :            : 
     224                 :            : static void
     225                 :          0 : usage_help(void)
     226                 :            : {
     227                 :          0 :         usage(NULL, NULL, stdout, PKG_USAGE_HELP);
     228                 :          0 : }
     229                 :            : 
     230                 :            : static int
     231                 :          0 : exec_help(int argc, char **argv)
     232                 :            : {
     233                 :            :         char *manpage;
     234                 :          0 :         bool plugins_enabled = false;
     235                 :            :         struct plugcmd *c;
     236                 :            :         unsigned int i;
     237                 :            :         const pkg_object *all_aliases;
     238                 :            :         const pkg_object *alias;
     239                 :          0 :         pkg_iter it = NULL;
     240                 :            : 
     241                 :          0 :         if ((argc != 2) || (strcmp("help", argv[1]) == 0)) {
     242                 :          0 :                 usage_help();
     243                 :          0 :                 return(EXIT_FAILURE);
     244                 :            :         }
     245                 :            : 
     246         [ #  # ]:          0 :         for (i = 0; i < cmd_len; i++) {
     247         [ #  # ]:          0 :                 if (strcmp(cmd[i].name, argv[1]) == 0) {
     248         [ #  # ]:          0 :                         if (asprintf(&manpage, "/usr/bin/man pkg-%s", cmd[i].name) == -1)
     249                 :          0 :                                 errx(EXIT_FAILURE, "cannot allocate memory");
     250                 :            : 
     251                 :          0 :                         system(manpage);
     252                 :          0 :                         free(manpage);
     253                 :            : 
     254                 :          0 :                         return (0);
     255                 :            :                 }
     256                 :          0 :         }
     257                 :            : 
     258                 :          0 :         plugins_enabled = pkg_object_bool(pkg_config_get("PKG_ENABLE_PLUGINS"));
     259                 :            : 
     260                 :          0 :         if (plugins_enabled) {
     261         [ #  # ]:          0 :                 DL_FOREACH(plugins, c) {
     262         [ #  # ]:          0 :                         if (strcmp(c->name, argv[1]) == 0) {
     263         [ #  # ]:          0 :                                 if (asprintf(&manpage, "/usr/bin/man pkg-%s", c->name) == -1)
     264                 :          0 :                                         errx(EXIT_FAILURE, "cannot allocate memory");
     265                 :            : 
     266                 :          0 :                                 system(manpage);
     267                 :          0 :                                 free(manpage);
     268                 :            : 
     269                 :          0 :                                 return (0);
     270                 :            :                         }
     271                 :          0 :                 }
     272                 :          0 :         }
     273                 :            : 
     274         [ #  # ]:          0 :         if (strcmp(argv[1], "pkg") == 0) {
     275                 :          0 :                 system("/usr/bin/man 8 pkg");
     276                 :          0 :                 return (0);
     277         [ #  # ]:          0 :         } else if (strcmp(argv[1], "pkg.conf") == 0) {
     278                 :          0 :                 system("/usr/bin/man 5 pkg.conf");
     279                 :          0 :                 return (0);
     280                 :            :         }
     281                 :            : 
     282                 :            :         /* Try aliases */
     283                 :          0 :         all_aliases = pkg_config_get("ALIAS");
     284         [ #  # ]:          0 :         while ((alias = pkg_object_iterate(all_aliases, &it))) {
     285         [ #  # ]:          0 :                 if (strcmp(argv[1], pkg_object_key(alias)) == 0) {
     286                 :          0 :                         printf("`%s` is an alias to `%s`\n", argv[1], pkg_object_string(alias));
     287                 :          0 :                         return (0);
     288                 :            :                 }
     289                 :            :         }
     290                 :            : 
     291                 :            :         /* Command name not found */
     292                 :          0 :         warnx("'%s' is not a valid command.\n", argv[1]);
     293                 :            : 
     294                 :          0 :         fprintf(stderr, "See 'pkg help' for more information on the commands.\n");
     295                 :            : 
     296                 :          0 :         return (EXIT_FAILURE);
     297                 :          0 : }
     298                 :            : 
     299                 :            : static void
     300                 :         34 : show_plugin_info(void)
     301                 :            : {
     302                 :            :         const pkg_object        *conf;
     303                 :         34 :         struct pkg_plugin       *p = NULL;
     304                 :            : 
     305         [ -  + ]:         34 :         while (pkg_plugins(&p) == EPKG_OK) {
     306                 :          0 :                 conf = pkg_plugin_conf(p);
     307                 :          0 :                 printf("Configuration for plugin: %s\n",
     308                 :          0 :                     pkg_plugin_get(p, PKG_PLUGIN_NAME));
     309                 :            : 
     310                 :          0 :                 printf("%s\n", pkg_object_dump(conf));
     311                 :            :         }
     312                 :         34 : }
     313                 :            : 
     314                 :            : static void
     315                 :         34 : show_repository_info(void)
     316                 :            : {
     317                 :            :         const char      *mirror, *sig;
     318                 :         34 :         struct pkg_repo *repo = NULL;
     319                 :            : 
     320                 :         34 :         printf("\nRepositories:\n");
     321         [ +  + ]:         89 :         while (pkg_repos(&repo) == EPKG_OK) {
     322   [ -  -  +  - ]:         55 :                 switch (pkg_repo_mirror_type(repo)) {
     323                 :            :                 case SRV:
     324                 :          0 :                         mirror = "SRV";
     325                 :          0 :                         break;
     326                 :            :                 case HTTP:
     327                 :          0 :                         mirror = "HTTP";
     328                 :          0 :                         break;
     329                 :            :                 case NOMIRROR:
     330                 :         55 :                         mirror = "NONE";
     331                 :         55 :                         break;
     332                 :            :                 default:
     333                 :          0 :                         mirror = "-unknown-";
     334                 :          0 :                         break;
     335                 :            :                 }
     336   [ -  -  +  - ]:         55 :                 switch (pkg_repo_signature_type(repo)) {
     337                 :            :                 case SIG_PUBKEY:
     338                 :          0 :                         sig = "PUBKEY";
     339                 :          0 :                         break;
     340                 :            :                 case SIG_FINGERPRINT:
     341                 :          0 :                         sig = "FINGERPRINTS";
     342                 :          0 :                         break;
     343                 :            :                 case SIG_NONE:
     344                 :         55 :                         sig = "NONE";
     345                 :         55 :                         break;
     346                 :            :                 default:
     347                 :          0 :                         sig = "-unknown-";
     348                 :          0 :                         break;
     349                 :            :                 }
     350                 :            : 
     351                 :         55 :                 printf("  %s: { \n    %-16s: \"%s\",\n    %-16s: %s,\n"
     352                 :            :                        "    %-16s: %u",
     353                 :         55 :                     pkg_repo_name(repo),
     354                 :         55 :                     "url", pkg_repo_url(repo),
     355                 :         55 :                     "enabled", pkg_repo_enabled(repo) ? "yes" : "no",
     356                 :         55 :                     "priority", pkg_repo_priority(repo));
     357                 :            : 
     358                 :         55 :                 if (pkg_repo_mirror_type(repo) != NOMIRROR)
     359                 :          0 :                         printf(",\n    %-16s: \"%s\"",
     360                 :          0 :                             "mirror_type", mirror);
     361                 :          0 :                 if (pkg_repo_signature_type(repo) != SIG_NONE)
     362                 :          0 :                         printf(",\n    %-16s: \"%s\"",
     363                 :          0 :                             "signature_type", sig);
     364                 :          0 :                 if (pkg_repo_fingerprints(repo) != NULL)
     365                 :          0 :                         printf(",\n    %-16s: \"%s\"",
     366                 :          0 :                             "fingerprints", pkg_repo_fingerprints(repo));
     367                 :          0 :                 if (pkg_repo_key(repo) != NULL)
     368                 :          0 :                         printf(",\n    %-16s: \"%s\"",
     369                 :          0 :                             "pubkey", pkg_repo_key(repo));
     370                 :          0 :                 if (pkg_repo_ip_version(repo) != 0)
     371                 :          0 :                         printf(",\n    %-16s: %u",
     372                 :          0 :                                 "ip_version", pkg_repo_ip_version(repo));
     373                 :         55 :                 printf("\n  }\n");
     374                 :            :         }
     375                 :         34 : }
     376                 :            : 
     377                 :            : static void
     378                 :         34 : show_version_info(int version)
     379                 :            : {
     380                 :            :         char *config;
     381                 :         34 :         if (version > 1)
     382                 :         34 :                 printf("%-24s: ", "Version");
     383                 :            : 
     384                 :         34 :         printf(PKG_PORTVERSION""GITHASH"\n");
     385                 :            : 
     386         [ -  + ]:         34 :         if (version == 1)
     387                 :          0 :                 exit(EXIT_SUCCESS);
     388                 :            : 
     389                 :         34 :         config = pkg_config_dump();
     390                 :         34 :         printf("%s\n", config);
     391                 :         34 :         free(config);
     392                 :         34 :         show_plugin_info();
     393                 :         34 :         show_repository_info();
     394                 :            : 
     395                 :         34 :         exit(EXIT_SUCCESS);
     396                 :            :         /* NOTREACHED */
     397                 :            : }
     398                 :            : 
     399                 :            : static void
     400                 :         13 : do_activation_test(int argc)
     401                 :            : {
     402                 :            :         int     count;
     403                 :            : 
     404                 :            :         /* Test to see if pkg(8) has been activated.  Exit with an
     405                 :            :            error code if not.  Can be combined with -c and -j to test
     406                 :            :            if pkg is activated in chroot or jail. If there are no
     407                 :            :            other arguments, and pkg(8) has been activated, show how
     408                 :            :            many packages have been installed. */
     409                 :            : 
     410   [ -  +  -  - ]:         13 :         switch (pkg_status(&count)) {
     411                 :            :         case PKG_STATUS_UNINSTALLED: /* This case shouldn't ever happen... */
     412                 :          0 :                 errx(EXIT_FAILURE, "can't execute " PKG_EXEC_NAME
     413                 :            :                     " or " PKG_STATIC_NAME "\n");
     414                 :            :                 /* NOTREACHED */
     415                 :            :         case PKG_STATUS_NODB:
     416                 :         13 :                 errx(EXIT_FAILURE, "package database non-existent");
     417                 :            :                 /* NOTREACHED */
     418                 :            :         case PKG_STATUS_NOPACKAGES:
     419                 :          0 :                 errx(EXIT_FAILURE, "no packages registered");
     420                 :            :                 /* NOTREACHED */
     421                 :            :         case PKG_STATUS_ACTIVE:
     422         [ #  # ]:          0 :                 if (argc == 0) {
     423                 :          0 :                         warnx("%d packages installed", count);
     424                 :          0 :                         exit(EXIT_SUCCESS);
     425                 :            :                 }
     426                 :          0 :                 break;
     427                 :            :         }
     428                 :          0 :         return;
     429                 :            : }
     430                 :            : 
     431                 :            : static void
     432                 :        805 : export_arg_option (char *arg)
     433                 :            : {
     434                 :            :         char *eqp;
     435                 :            :         const char *opt;
     436                 :            : 
     437                 :        805 :         if ((eqp = strchr(arg, '=')) != NULL) {
     438                 :        805 :                 *eqp = '\0';
     439                 :            : 
     440         [ +  + ]:        805 :                 if ((opt = getenv (arg)) != NULL) {
     441                 :         16 :                         warnx("option %s is defined in the environment to '%s' but command line "
     442                 :         16 :                                         "option redefines it", arg, opt);
     443                 :         16 :                         setenv(arg, eqp + 1, 1);
     444                 :         16 :                 }
     445                 :            :                 else {
     446                 :        789 :                         setenv(arg, eqp + 1, 0);
     447                 :            :                 }
     448                 :            : 
     449                 :        805 :                 *eqp = '=';
     450                 :        805 :         }
     451                 :        805 : }
     452                 :            : 
     453                 :            : static void
     454                 :       3452 : start_process_worker(char *const *save_argv)
     455                 :            : {
     456                 :       3452 :         int     ret = EXIT_SUCCESS;
     457                 :            :         int     status;
     458                 :            :         pid_t   child_pid;
     459                 :            : 
     460                 :            :         /* Fork off a child process to do the actual package work.
     461                 :            :          * The child may be jailed or chrooted.  If a restart is required
     462                 :            :          * (eg. pkg(8) inself was upgraded) the child can exit with
     463                 :            :          * 'EX_NEEDRESTART' and the same forking process will be
     464                 :            :          * replayed.  This function returns control in the child
     465                 :            :          * process only. */
     466                 :            : 
     467                 :       3465 :         while (1) {
     468                 :       3465 :                 child_pid = fork();
     469                 :            : 
     470         [ +  + ]:       3465 :                 if (child_pid == 0) {
     471                 :            :                         /* Load the new Pkg image */
     472                 :       3477 :                         if (ret == EX_NEEDRESTART)
     473                 :         13 :                                 execvp(getprogname(), save_argv);
     474                 :       3464 :                         return;
     475                 :            :                 } else {
     476         [ -  + ]:       3465 :                         if (child_pid == -1)
     477                 :          0 :                                 err(EXIT_FAILURE, "Failed to fork worker process");
     478                 :            : 
     479         [ -  + ]:       3465 :                         while (waitpid(child_pid, &status, 0) == -1) {
     480         [ #  # ]:          0 :                                 if (errno != EINTR)
     481                 :          0 :                                         err(EXIT_FAILURE, "Child process pid=%d", (int)child_pid);
     482                 :            :                         }
     483                 :            : 
     484                 :       3465 :                         ret = WEXITSTATUS(status);
     485                 :            : 
     486                 :       3465 :                         if (WIFEXITED(status) && ret != EX_NEEDRESTART)
     487                 :       3452 :                                 break;
     488                 :         13 :                         if (WIFSIGNALED(status)) {
     489                 :            :                                 /* Process got some terminating signal, hence stop the loop */
     490                 :          0 :                                 fprintf(stderr, "Child process pid=%d terminated abnormally: %s\n",
     491                 :          0 :                                                 (int)child_pid, strsignal (WTERMSIG(status)));
     492                 :          0 :                                 ret = 128 + WTERMSIG(status);
     493                 :          0 :                                 break;
     494                 :            :                         }
     495                 :            :                 }
     496                 :            :         }
     497                 :            : 
     498                 :       3452 :         exit(ret);
     499                 :            :         /* NOTREACHED */
     500                 :            : }
     501                 :            : 
     502                 :            : static int
     503                 :       3459 : expand_aliases(int argc, char ***argv)
     504                 :            : {
     505                 :       3459 :         pkg_iter                  it = NULL;
     506                 :            :         const pkg_object         *all_aliases;
     507                 :            :         const pkg_object         *alias;
     508                 :            :         const char               *alias_value;
     509                 :            :         void                     *buf;
     510                 :       3459 :         char                    **oldargv = *argv;
     511                 :            :         char                    **newargv;
     512                 :            :         char                     *args;
     513                 :            :         int                       newargc;
     514                 :            :         int                       spaces;
     515                 :            :         int                       i;
     516                 :            :         size_t                    veclen;
     517                 :            :         size_t                    arglen;
     518                 :       3459 :         bool                      matched = false;
     519                 :            : 
     520                 :       3459 :         all_aliases = pkg_config_get("ALIAS");
     521                 :            : 
     522                 :      86445 :         while ((alias = pkg_object_iterate(all_aliases, &it))) {
     523         [ +  + ]:      83012 :                 if (strcmp(oldargv[0], pkg_object_key(alias)) == 0) {
     524                 :         26 :                         matched = true;
     525                 :         26 :                         break;
     526                 :            :                 }
     527                 :            :         }
     528                 :            : 
     529                 :         26 :         if (!matched || (alias_value = pkg_object_string(alias)) == NULL)
     530                 :       3433 :                 return (argc);  /* Nothing to do */
     531                 :            : 
     532                 :            :         /* Estimate how many args alias_value will split into by
     533                 :            :          * counting the number of whitespace characters in it. This
     534                 :            :          * will be at minimum one less than the final argc. We'll be
     535                 :            :          * consuming one of the orginal argv, so that balances
     536                 :            :          * out. */
     537                 :            : 
     538                 :         26 :         spaces = pkg_utils_count_spaces(alias_value);
     539                 :         26 :         arglen = strlen(alias_value) + 1;
     540                 :         26 :         veclen = sizeof(char *) * (spaces + argc + 1);
     541                 :         26 :         buf = malloc(veclen + arglen);
     542         [ -  + ]:         26 :         if (buf == NULL)
     543                 :          0 :                 err(EXIT_FAILURE, "expanding aliases");
     544                 :            : 
     545                 :         26 :         newargv = (char **) buf;
     546                 :         26 :         args = (char *) (buf + veclen);
     547                 :         26 :         strlcpy(args, alias_value, arglen);
     548                 :            : 
     549                 :         26 :         newargc = 0;
     550         [ +  + ]:         78 :         while(args != NULL) {
     551                 :         52 :                 newargv[newargc++] = pkg_utils_tokenize(&args);
     552                 :            :         }
     553         [ -  + ]:         26 :         for (i = 1; i < argc; i++) {
     554                 :          0 :                 newargv[newargc++] = oldargv[i];
     555                 :          0 :         }
     556                 :         26 :         newargv[newargc] = NULL;
     557                 :            : 
     558                 :         26 :         *argv = newargv;
     559                 :         26 :         return (newargc);
     560                 :       3459 : }
     561                 :            : 
     562                 :            : static
     563                 :       3452 : bool ptraced(void)
     564                 :            : {
     565                 :            : #if defined(__FreeBSD__)
     566                 :            :         int                 mib[4];
     567                 :            :         struct kinfo_proc   info;
     568                 :            :         size_t              size;
     569                 :            : 
     570                 :       3452 :         info.ki_flag = 0;
     571                 :            : 
     572                 :       3452 :         mib[0] = CTL_KERN;
     573                 :       3452 :         mib[1] = KERN_PROC;
     574                 :       3452 :         mib[2] = KERN_PROC_PID;
     575                 :       3452 :         mib[3] = getpid();
     576                 :            : 
     577                 :       3452 :         size = sizeof(info);
     578                 :       3452 :         sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0);
     579                 :            : 
     580                 :       3452 :         return ((info.ki_flag & P_TRACED) != 0 );
     581                 :            : #else
     582                 :            :         return (false);
     583                 :            : #endif
     584                 :            : }
     585                 :            : 
     586                 :            : int
     587                 :       3494 : main(int argc, char **argv)
     588                 :            : {
     589                 :            :         unsigned int      i;
     590                 :       3494 :         struct commands  *command = NULL;
     591                 :       3494 :         unsigned int      ambiguous = 0;
     592                 :       3494 :         const char       *chroot_path = NULL;
     593                 :       3494 :         const char       *rootdir = NULL;
     594                 :            : #ifdef HAVE_LIBJAIL
     595                 :            :         int               jid;
     596                 :            : #endif
     597                 :       3494 :         const char       *jail_str = NULL;
     598                 :            :         size_t            len;
     599                 :            :         signed char       ch;
     600                 :       3494 :         int64_t           debug = 0;
     601                 :       3494 :         int               version = 0;
     602                 :       3494 :         int               ret = EXIT_SUCCESS;
     603                 :       3494 :         bool              plugins_enabled = false;
     604                 :       3494 :         bool              plugin_found = false;
     605                 :       3494 :         bool              show_commands = false;
     606                 :       3494 :         bool              activation_test = false;
     607                 :       3494 :         pkg_init_flags    init_flags = 0;
     608                 :            :         struct plugcmd   *c;
     609                 :       3494 :         const char       *conffile = NULL;
     610                 :       3494 :         const char       *reposdir = NULL;
     611                 :            :         char            **save_argv;
     612                 :            :         char              realrootdir[MAXPATHLEN];
     613                 :            :         int               j;
     614                 :            : 
     615                 :       3494 :         struct option longopts[] = {
     616                 :            :                 { "debug",            no_argument,            NULL,   'd' },
     617                 :            : #ifdef HAVE_LIBJAIL
     618                 :            :                 { "jail",             required_argument,      NULL,   'j' },
     619                 :            : #endif
     620                 :            :                 { "chroot",           required_argument,      NULL,   'c' },
     621                 :            :                 { "config",           required_argument,      NULL,   'C' },
     622                 :            :                 { "repo-conf-dir",    required_argument,      NULL,   'R' },
     623                 :            :                 { "rootdir",          required_argument,      NULL,   'r' },
     624                 :            :                 { "list",             no_argument,            NULL,   'l' },
     625                 :            :                 { "version",          no_argument,            NULL,   'v' },
     626                 :            :                 { "option",           required_argument,      NULL,   'o' },
     627                 :            :                 { "only-ipv4",                no_argument,            NULL,   '4' },
     628                 :            :                 { "only-ipv6",                no_argument,            NULL,   '6' },
     629                 :            :                 { NULL,                 0,                      NULL,   0   },
     630                 :            :         };
     631                 :            : 
     632                 :            :         /* Set stdout unbuffered */
     633                 :       3494 :         setvbuf(stdout, NULL, _IONBF, 0);
     634                 :            : 
     635                 :            :         /* Ignore SIGPIPE */
     636                 :       3494 :         signal(SIGPIPE, SIG_IGN);
     637                 :            : 
     638                 :       3494 :         if (argc < 2)
     639                 :          0 :                 usage(NULL, NULL, stderr, PKG_USAGE_INVALID_ARGUMENTS, "not enough arguments");
     640                 :            : 
     641                 :            :         /* getopt_long() will permute the arg-list unless
     642                 :            :          * POSIXLY_CORRECT is set in the environment.  This is a
     643                 :            :          * difference to the original getopt() we were using, and
     644                 :            :          * screws up our 'pkg {pkg-opts} verb {verb-opts}' command
     645                 :            :          * line concept. */
     646                 :            : 
     647         [ -  + ]:       3494 :         if (setenv("POSIXLY_CORRECT", "1",  1) == -1)
     648                 :          0 :                 err(EXIT_FAILURE, "setenv() failed");
     649                 :            : 
     650                 :       3494 :         save_argv = argv;
     651                 :            : 
     652                 :            : #ifdef HAVE_LIBJAIL
     653                 :            : #define JAIL_OPT        "j:"
     654                 :            : #else
     655                 :            : #define JAIL_OPT
     656                 :            : #endif
     657         [ +  + ]:       5133 :         while ((ch = getopt_long(argc, argv, "+d"JAIL_OPT"c:C:R:r:lNvo:46", longopts, NULL)) != -1) {
     658   [ +  -  +  +  :       1639 :                 switch (ch) {
          +  -  -  +  +  
             +  -  -  - ]
     659                 :            :                 case 'd':
     660                 :         16 :                         debug++;
     661                 :         16 :                         break;
     662                 :            :                 case 'c':
     663                 :          0 :                         chroot_path = optarg;
     664                 :          0 :                         break;
     665                 :            :                 case 'C':
     666                 :        414 :                         conffile = optarg;
     667                 :        414 :                         break;
     668                 :            :                 case 'R':
     669                 :         21 :                         reposdir = optarg;
     670                 :         21 :                         break;
     671                 :            :                 case 'r':
     672                 :        302 :                         rootdir = optarg;
     673                 :        302 :                         break;
     674                 :            : #ifdef HAVE_LIBJAIL
     675                 :            :                 case 'j':
     676                 :          0 :                         jail_str = optarg;
     677                 :          0 :                         break;
     678                 :            : #endif
     679                 :            :                 case 'l':
     680                 :          0 :                         show_commands = true;
     681                 :          0 :                         break;
     682                 :            :                 case 'N':
     683                 :         13 :                         activation_test = true;
     684                 :         13 :                         break;
     685                 :            :                 case 'v':
     686                 :         68 :                         version++;
     687                 :         68 :                         break;
     688                 :            :                 case 'o':
     689                 :        805 :                         export_arg_option (optarg);
     690                 :        805 :                         break;
     691                 :            :                 case '4':
     692                 :          0 :                         init_flags = PKG_INIT_FLAG_USE_IPV4;
     693                 :          0 :                         break;
     694                 :            :                 case '6':
     695                 :          0 :                         init_flags = PKG_INIT_FLAG_USE_IPV6;
     696                 :          0 :                         break;
     697                 :            :                 default:
     698                 :          0 :                         errx(EXIT_FAILURE, "Invalid argument provided");
     699                 :            :                         break;
     700                 :            :                 }
     701                 :            :         }
     702                 :       3494 :         argc -= optind;
     703                 :       3494 :         argv += optind;
     704                 :            : 
     705                 :       3494 :         pkg_set_debug_level(debug);
     706                 :            : 
     707                 :       3494 :         if (version == 1)
     708                 :          0 :                 show_version_info(version);
     709                 :            : 
     710                 :          0 :         if (show_commands && version == 0) {
     711                 :          0 :                 show_command_names();
     712                 :          0 :                 exit(EXIT_SUCCESS);
     713                 :            :         }
     714                 :            : 
     715                 :         47 :         if (argc == 0 && version == 0 && !activation_test)
     716                 :          0 :                 usage(conffile, reposdir, stderr, PKG_USAGE_INVALID_ARGUMENTS, "no commands specified");
     717                 :            : 
     718                 :       3486 :         umask(022);
     719                 :       3486 :         pkg_event_register(&event_callback, &debug);
     720                 :            : 
     721                 :            :         /* reset getopt for the next call */
     722                 :       3486 :         optreset = 1;
     723                 :       3486 :         optind = 1;
     724                 :            : 
     725                 :       3486 :         if (debug == 0 && version == 0 && !ptraced())
     726                 :       3452 :                 start_process_worker(save_argv);
     727                 :            : 
     728                 :            : #ifdef HAVE_ARC4RANDOM_STIR
     729                 :            :         /* Ensure that random is stirred after a possible fork */
     730                 :            :         arc4random_stir();
     731                 :            : #endif
     732                 :            : 
     733                 :       7208 :         if ((jail_str != NULL && (chroot_path != NULL || rootdir != NULL)) ||
     734                 :          0 :             (chroot_path != NULL && (jail_str != NULL || rootdir != NULL)) ||
     735                 :        304 :             (rootdir != NULL && (jail_str != NULL || chroot_path != NULL)))  {
     736                 :          0 :                 usage(conffile, reposdir, stderr, PKG_USAGE_INVALID_ARGUMENTS,
     737                 :            :                     "-j, -c and/or -r cannot be used at the same time!\n");
     738                 :          0 :         }
     739                 :            : 
     740                 :          0 :         if (chroot_path != NULL) {
     741         [ #  # ]:          0 :                 if (chroot(chroot_path) == -1) {
     742                 :          0 :                         err(EXIT_FAILURE, "chroot failed");
     743                 :            :                 }
     744                 :          0 :         }
     745                 :            : 
     746                 :            : #ifdef HAVE_LIBJAIL
     747                 :          0 :         if (jail_str != NULL) {
     748                 :          0 :                 jid = jail_getid(jail_str);
     749         [ #  # ]:          0 :                 if (jid < 0)
     750                 :          0 :                         errx(1, "%s", jail_errmsg);
     751                 :            : 
     752         [ #  # ]:          0 :                 if (jail_attach(jid) == -1)
     753                 :          0 :                         err(1, "jail_attach(%s)", jail_str);
     754                 :          0 :         }
     755                 :            : 
     756                 :       3506 :         if (jail_str != NULL || chroot_path != NULL)
     757         [ #  # ]:          0 :                 if (chdir("/") == -1)
     758                 :          0 :                         errx(EXIT_FAILURE, "chdir() failed");
     759                 :            : #endif
     760                 :            : 
     761                 :        304 :         if (rootdir != NULL) {
     762         [ -  + ]:        304 :                 if (realpath(rootdir, realrootdir) == NULL)
     763                 :          0 :                         err(EXIT_FAILURE, "Invalid rootdir");
     764         [ -  + ]:        304 :                 if (chdir(rootdir) == -1)
     765                 :          0 :                         errx(EXIT_FAILURE, "chdir() failed");
     766         [ -  + ]:        304 :                 if (pkg_set_rootdir(realrootdir) != EPKG_OK)
     767                 :          0 :                         exit(EXIT_FAILURE);
     768                 :        304 :         }
     769                 :            : 
     770         [ -  + ]:       3506 :         if (pkg_ini(conffile, reposdir, init_flags) != EPKG_OK)
     771                 :          0 :                 errx(EXIT_FAILURE, "Cannot parse configuration file!");
     772                 :            : 
     773                 :       3506 :         if (debug > 0)
     774                 :          8 :                 pkg_set_debug_level(debug);
     775                 :            : 
     776         [ -  + ]:       3506 :         if (atexit(&pkg_shutdown) != 0)
     777                 :          0 :                 errx(EXIT_FAILURE, "register pkg_shutdown() to run at exit");
     778                 :            : 
     779                 :       3506 :         if (jail_str == NULL && !pkg_compiled_for_same_os_major())
     780                 :          0 :                 warnx("Warning: Major OS version upgrade detected.  Running "
     781                 :            :                     "\"pkg bootstrap -f\" recommended");
     782                 :            : 
     783                 :            : 
     784                 :         26 :         plugins_enabled = pkg_object_bool(pkg_config_get("PKG_ENABLE_PLUGINS"));
     785                 :            : 
     786                 :         26 :         if (plugins_enabled) {
     787                 :         26 :                 struct pkg_plugin       *p = NULL;
     788                 :            : 
     789         [ -  + ]:         26 :                 if (pkg_plugins_init() != EPKG_OK)
     790                 :          0 :                         errx(EXIT_FAILURE, "Plugins cannot be loaded");
     791                 :            : 
     792         [ -  + ]:         26 :                 if (atexit(&pkg_plugins_shutdown) != 0)
     793                 :          0 :                         errx(EXIT_FAILURE,
     794                 :            :                             "register pkg_plugins_shutdown() to run at exit");
     795                 :            : 
     796                 :            :                 /* load commands plugins */
     797         [ -  + ]:         26 :                 while (pkg_plugins(&p) != EPKG_END) {
     798                 :            :                         int n;
     799                 :            : 
     800                 :          0 :                         nb_cmd *ncmd = pkg_plugin_func(p, "pkg_register_cmd_count");
     801                 :          0 :                         register_cmd *reg = pkg_plugin_func(p, "pkg_register_cmd");
     802                 :          0 :                         if (reg != NULL && ncmd != NULL) {
     803                 :          0 :                                 n = ncmd();
     804         [ #  # ]:          0 :                                 for (j = 0; j < n ; j++) {
     805                 :          0 :                                         c = malloc(sizeof(struct plugcmd));
     806                 :          0 :                                         reg(j, &c->name, &c->desc, &c->exec);
     807         [ #  # ]:          0 :                                         DL_APPEND(plugins, c);
     808                 :          0 :                                 }
     809                 :          0 :                         }
     810                 :            :                 }
     811                 :         26 :         }
     812                 :            : 
     813                 :         34 :         if (version > 1)
     814                 :         34 :                 show_version_info(version);
     815                 :            : 
     816                 :         55 :         if (activation_test)
     817                 :         13 :                 do_activation_test(argc);
     818                 :            : 
     819                 :       3459 :         if (argc >= 1 && strcmp(argv[0], "bootstrap") == 0) {
     820         [ #  # ]:          0 :                 if (argc == 1) {
     821                 :          0 :                         printf("pkg(8) already installed, use -f to force.\n");
     822                 :          0 :                         exit(EXIT_SUCCESS);
     823                 :          0 :                 } else if (argc == 2 && strcmp(argv[1], "-f") == 0) {
     824         [ #  # ]:          0 :                         if (access("/usr/sbin/pkg", R_OK) == 0) {
     825                 :            :                                 /* Only 10.0+ supported 'bootstrap -f' */
     826                 :            : #if __FreeBSD_version < 1000502
     827                 :            :                                 printf("Execute these steps to rebootstrap"
     828                 :            :                                      " pkg(8):\n");
     829                 :            :                                 printf("# pkg delete -f pkg\n");
     830                 :            :                                 printf("# /usr/sbin/pkg -v\n");
     831                 :            :                                 exit(EXIT_SUCCESS);
     832                 :            : #endif
     833                 :          0 :                                 printf("pkg(8) is already installed. Forcing "
     834                 :            :                                     "reinstallation through pkg(7).\n");
     835                 :          0 :                                 execl("/usr/sbin/pkg", "pkg", "bootstrap",
     836                 :            :                                     "-f", NULL);
     837                 :            :                                 /* NOTREACHED */
     838                 :          0 :                         } else
     839                 :          0 :                                 errx(EXIT_FAILURE, "pkg(7) bootstrapper not"
     840                 :            :                                     " found at /usr/sbin/pkg.");
     841                 :          0 :                 }
     842                 :          0 :         }
     843                 :            : 
     844                 :       3459 :         save_argv = argv;
     845                 :       3459 :         argc = expand_aliases(argc, &argv);
     846                 :            : 
     847                 :       3459 :         len = strlen(argv[0]);
     848                 :      49592 :         for (i = 0; i < cmd_len; i++) {
     849                 :      49592 :                 if (strncmp(argv[0], cmd[i].name, len) == 0) {
     850                 :            :                         /* if we have the exact cmd */
     851         [ +  - ]:       3459 :                         if (len == strlen(cmd[i].name)) {
     852                 :       3459 :                                 command = &cmd[i];
     853                 :       3459 :                                 ambiguous = 0;
     854                 :       3459 :                                 break;
     855                 :            :                         }
     856                 :            : 
     857                 :            :                         /*
     858                 :            :                          * we already found a partial match so `argv[0]' is
     859                 :            :                          * an ambiguous shortcut
     860                 :            :                          */
     861                 :          0 :                         ambiguous++;
     862                 :            : 
     863                 :          0 :                         command = &cmd[i];
     864                 :          0 :                 }
     865                 :      46133 :         }
     866                 :            : 
     867                 :       3459 :         set_globals();
     868                 :            : 
     869         [ -  + ]:       3459 :         if (command == NULL) {
     870                 :            :                 /* Check if a plugin provides the requested command */
     871                 :          0 :                 ret = EPKG_FATAL;
     872                 :          0 :                 if (plugins_enabled) {
     873                 :          0 :                         DL_FOREACH(plugins, c) {
     874         [ #  # ]:          0 :                                 if (strcmp(c->name, argv[0]) == 0) {
     875                 :          0 :                                         plugin_found = true;
     876                 :          0 :                                         ret = c->exec(argc, argv);
     877                 :          0 :                                         break;
     878                 :            :                                 }
     879                 :          0 :                         }
     880                 :          0 :                 }
     881                 :            : 
     882                 :          0 :                 if (!plugin_found)
     883                 :          0 :                         usage(conffile, reposdir, stderr, PKG_USAGE_UNKNOWN_COMMAND, argv[0]);
     884                 :            : 
     885                 :          0 :                 return (ret);
     886                 :            :         }
     887                 :            : 
     888         [ +  - ]:       3459 :         if (ambiguous <= 1) {
     889         [ +  - ]:       3459 :                 assert(command->exec != NULL);
     890                 :       3459 :                 ret = command->exec(argc, argv);
     891                 :       3459 :         } else {
     892                 :          0 :                 usage(conffile, reposdir, stderr, PKG_USAGE_UNKNOWN_COMMAND, argv[0]);
     893                 :            :         }
     894                 :            : 
     895                 :       3459 :         if (save_argv != argv)
     896                 :         26 :                 free(argv);
     897                 :            : 
     898                 :       3204 :         if (ret == EXIT_SUCCESS && newpkgversion)
     899                 :         13 :                 return (EX_NEEDRESTART);
     900                 :            : 
     901                 :       3446 :         return (ret);
     902                 :       3459 : }
     903                 :            : 

Generated by: LCOV version 1.15