• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/opkg-lede/libopkg/opkg_cmd.c

  1 /* opkg_cmd.c - the opkg package management system
  2 
  3    Carl D. Worth
  4 
  5    Copyright (C) 2001 University of Southern California
  6 
  7    This program is free software; you can redistribute it and/or
  8    modify it under the terms of the GNU General Public License as
  9    published by the Free Software Foundation; either version 2, or (at
 10    your option) any later version.
 11 
 12    This program is distributed in the hope that it will be useful, but
 13    WITHOUT ANY WARRANTY; without even the implied warranty of
 14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 15    General Public License for more details.
 16 */
 17 
 18 #include <stdio.h>
 19 #include <dirent.h>
 20 #include <glob.h>
 21 #include <fnmatch.h>
 22 #include <signal.h>
 23 #include <unistd.h>
 24 
 25 #include "opkg_conf.h"
 26 #include "opkg_cmd.h"
 27 #include "opkg_message.h"
 28 #include "pkg.h"
 29 #include "pkg_dest.h"
 30 #include "pkg_parse.h"
 31 #include "sprintf_alloc.h"
 32 #include "pkg.h"
 33 #include "file_util.h"
 34 #include "libbb/libbb.h"
 35 #include "opkg_utils.h"
 36 #include "opkg_defines.h"
 37 #include "opkg_download.h"
 38 #include "opkg_install.h"
 39 #include "opkg_upgrade.h"
 40 #include "opkg_remove.h"
 41 #include "opkg_configure.h"
 42 #include "xsystem.h"
 43 
 44 int opkg_cli_argc = 0;
 45 const char **opkg_cli_argv = NULL;
 46 
 47 static void print_pkg(pkg_t * pkg)
 48 {
 49         char *version = pkg_version_str_alloc(pkg);
 50         char *description = pkg_get_string(pkg, PKG_DESCRIPTION);
 51         const char *abiver;
 52         char *tmp, *tmpname = NULL;
 53 
 54         if (conf->strip_abi &&
 55             (abiver = pkg_get_string(pkg, PKG_ABIVERSION)) &&
 56             (strlen(pkg->name) > strlen(abiver))) {
 57                 tmpname = strdup(pkg->name);
 58                 tmp = &tmpname[strlen(tmpname) - strlen(abiver)];
 59                 if (!strncmp(abiver, tmp, strlen(abiver)))
 60                         *tmp = '\0';
 61         };
 62 
 63         printf("%s - %s", tmpname?tmpname:pkg->name, version);
 64 
 65         if (tmpname)
 66                 free(tmpname);
 67 
 68         if (conf->size)
 69                 printf(" - %lu", (unsigned long) pkg_get_int(pkg, PKG_SIZE));
 70         if (description)
 71                 printf(" - %s", description);
 72         printf("\n");
 73         free(version);
 74 }
 75 
 76 int opkg_state_changed;
 77 
 78 static void write_status_files_if_changed(void)
 79 {
 80         if (opkg_state_changed && !conf->noaction) {
 81                 opkg_msg(INFO, "Writing status file.\n");
 82                 opkg_conf_write_status_files();
 83                 pkg_write_changed_filelists();
 84         } else {
 85                 opkg_msg(DEBUG, "Nothing to be done.\n");
 86         }
 87 }
 88 
 89 static void sigint_handler(int sig)
 90 {
 91         signal(sig, SIG_DFL);
 92         opkg_msg(NOTICE, "Interrupted. Writing out status database.\n");
 93         write_status_files_if_changed();
 94         exit(128 + sig);
 95 }
 96 
 97 static int opkg_update_cmd(int argc, char **argv)
 98 {
 99         char *tmp;
100         int err;
101         int failures;
102         int pkglist_dl_error;
103         char *lists_dir;
104         pkg_src_list_elt_t *iter;
105         pkg_src_t *src;
106 
107         sprintf_alloc(&lists_dir, "%s",
108                       conf->restrict_to_default_dest ? conf->default_dest->
109                       lists_dir : conf->lists_dir);
110 
111         if (!file_is_dir(lists_dir)) {
112                 if (file_exists(lists_dir)) {
113                         opkg_msg(ERROR, "%s exists, but is not a directory.\n",
114                                  lists_dir);
115                         free(lists_dir);
116                         return -1;
117                 }
118                 err = file_mkdir_hier(lists_dir, 0755);
119                 if (err) {
120                         free(lists_dir);
121                         return -1;
122                 }
123         }
124 
125         failures = 0;
126 
127         sprintf_alloc(&tmp, "%s/update-XXXXXX", conf->tmp_dir);
128         if (mkdtemp(tmp) == NULL) {
129                 opkg_perror(ERROR, "Failed to make temp dir %s", conf->tmp_dir);
130                 return -1;
131         }
132 
133         for (iter = void_list_first(&conf->pkg_src_list); iter;
134              iter = void_list_next(&conf->pkg_src_list, iter)) {
135                 char *url, *list_file_name;
136 
137                 src = (pkg_src_t *) iter->data;
138 
139                 sprintf_alloc(&url, "%s/%s", src->value,
140                               src->gzip ? "Packages.gz" : "Packages");
141 
142                 sprintf_alloc(&list_file_name, "%s/%s", lists_dir, src->name);
143                 pkglist_dl_error = 0;
144                 if (opkg_download(url, list_file_name, 0)) {
145                         failures++;
146                         pkglist_dl_error = 1;
147                         opkg_msg(NOTICE,
148                                  "*** Failed to download the package list from %s\n\n",
149                                  url);
150                 } else {
151                         opkg_msg(NOTICE,
152                                  "Updated list of available packages in %s\n",
153                                  list_file_name);
154                 }
155                 free(url);
156 #if defined(HAVE_USIGN)
157                 if (pkglist_dl_error == 0 && conf->check_signature) {
158                         /* download detached signitures to verify the package lists */
159                         /* get the url for the sig file */
160                         sprintf_alloc(&url, "%s/%s", src->value,
161                                       "Packages.sig");
162 
163                         /* create temporary file for it */
164                         char *tmp_file_name;
165 
166                         /* Put the signature in the right place */
167                         sprintf_alloc(&tmp_file_name, "%s/%s.sig", lists_dir,
168                                       src->name);
169 
170                         err = opkg_download(url, tmp_file_name, 0);
171                         if (err) {
172                                 failures++;
173                                 opkg_msg(NOTICE,
174                                          "Signature file download failed.\n");
175                         } else {
176                                 err =
177                                     opkg_verify_file(list_file_name,
178                                                      tmp_file_name);
179                                 if (err == 0)
180                                         opkg_msg(NOTICE,
181                                                  "Signature check passed.\n");
182                                 else
183                                         opkg_msg(NOTICE,
184                                                  "Signature check failed.\n");
185                         }
186                         if (err && !conf->force_signature) {
187                                 /* The signature was wrong so delete it */
188                                 opkg_msg(NOTICE,
189                                          "Remove wrong Signature file.\n");
190                                 unlink(tmp_file_name);
191                                 unlink(list_file_name);
192                         }
193                         /* We shouldn't unlink the signature ! */
194                         // unlink (tmp_file_name);
195                         free(tmp_file_name);
196                         free(url);
197                 }
198 #else
199                 // Do nothing
200 #endif
201                 free(list_file_name);
202         }
203         rmdir(tmp);
204         free(tmp);
205         free(lists_dir);
206 
207         return failures;
208 }
209 
210 struct opkg_intercept {
211         char *oldpath;
212         char *statedir;
213 };
214 
215 typedef struct opkg_intercept *opkg_intercept_t;
216 
217 static opkg_intercept_t opkg_prep_intercepts(void)
218 {
219         opkg_intercept_t ctx;
220         char *newpath;
221 
222         ctx = xcalloc(1, sizeof(*ctx));
223         ctx->oldpath = xstrdup(getenv("PATH"));
224 
225         sprintf_alloc(&newpath, "%s/opkg/intercept:%s", DATADIR,
226                       ctx->oldpath ? ctx->oldpath : PATH_SPEC);
227 
228         sprintf_alloc(&ctx->statedir, "%s/opkg-intercept-XXXXXX",
229                       conf->tmp_dir);
230 
231         if (mkdtemp(ctx->statedir) == NULL) {
232                 opkg_perror(ERROR, "Failed to make temp dir %s", ctx->statedir);
233 
234                 if (ctx->oldpath)
235                         free(ctx->oldpath);
236 
237                 free(ctx->statedir);
238                 free(newpath);
239                 free(ctx);
240                 return NULL;
241         }
242 
243         setenv("OPKG_INTERCEPT_DIR", ctx->statedir, 1);
244         setenv("PATH", newpath, 1);
245         free(newpath);
246 
247         return ctx;
248 }
249 
250 static int opkg_finalize_intercepts(opkg_intercept_t ctx)
251 {
252         DIR *dir;
253         int err = 0;
254 
255         if (ctx->oldpath) {
256                 setenv("PATH", ctx->oldpath, 1);
257                 free(ctx->oldpath);
258         }
259         else {
260                 unsetenv("PATH");
261         }
262 
263         dir = opendir(ctx->statedir);
264         if (dir) {
265                 struct dirent *de;
266                 while (de = readdir(dir), de != NULL) {
267                         char *path;
268 
269                         if (de->d_name[0] == '.')
270                                 continue;
271 
272                         sprintf_alloc(&path, "%s/%s", ctx->statedir,
273                                       de->d_name);
274                         if (access(path, X_OK) == 0) {
275                                 const char *argv[] = { "/bin/sh", "-c", path, NULL };
276                                 xsystem(argv);
277                         }
278                         free(path);
279                 }
280                 closedir(dir);
281         } else
282                 opkg_perror(ERROR, "Failed to open dir %s", ctx->statedir);
283 
284         rm_r(ctx->statedir);
285         free(ctx->statedir);
286         free(ctx);
287 
288         return err;
289 }
290 
291 /* For package pkg do the following: If it is already visited, return. If not,
292    add it in visited list and recurse to its deps. Finally, add it to ordered
293    list.
294    pkg_vec all contains all available packages in repos.
295    pkg_vec visited contains packages already visited by this function, and is
296    used to end recursion and avoid an infinite loop on graph cycles.
297    pkg_vec ordered will finally contain the ordered set of packages.
298 */
299 static int
300 opkg_recurse_pkgs_in_order(pkg_t * pkg, pkg_vec_t * all,
301                            pkg_vec_t * visited, pkg_vec_t * ordered)
302 {
303         int j, k, l, m;
304         pkg_t *dep;
305         compound_depend_t *compound_depend;
306         depend_t **possible_satisfiers;
307         abstract_pkg_t *abpkg;
308         abstract_pkg_t **dependents;
309 
310         /* If it's just an available package, that is, not installed and not even
311            unpacked, skip it */
312         /* XXX: This is probably an overkill, since a state_status != SS_UNPACKED
313            would do here. However, if there is an intermediate node (pkg) that is
314            configured and installed between two unpacked packages, the latter
315            won't be properly reordered, unless all installed/unpacked pkgs are
316            checked */
317         if (pkg->state_status == SS_NOT_INSTALLED)
318                 return 0;
319 
320         /* If the  package has already been visited (by this function), skip it */
321         for (j = 0; j < visited->len; j++)
322                 if (!strcmp(visited->pkgs[j]->name, pkg->name)) {
323                         opkg_msg(DEBUG, "pkg %s already visited, skipping.\n",
324                                  pkg->name);
325                         return 0;
326                 }
327 
328         pkg_vec_insert(visited, pkg);
329 
330         opkg_msg(DEBUG, "pkg %s.\n", pkg->name);
331 
332         /* Iterate over all the dependencies of pkg. For each one, find a package
333            that is either installed or unpacked and satisfies this dependency.
334            (there should only be one such package per dependency installed or
335            unpacked). Then recurse to the dependency package */
336         for (compound_depend = pkg_get_ptr(pkg, PKG_DEPENDS); compound_depend && compound_depend->type; compound_depend++) {
337                 possible_satisfiers = compound_depend->possibilities;
338                 for (k = 0; k < compound_depend->possibility_count; k++) {
339                         abpkg = possible_satisfiers[k]->pkg;
340                         dependents = abpkg->provided_by->pkgs;
341                         l = 0;
342                         if (dependents != NULL)
343                                 while (l < abpkg->provided_by->len
344                                        && dependents[l] != NULL) {
345                                         opkg_msg(DEBUG,
346                                                  "Descending on pkg %s.\n",
347                                                  dependents[l]->name);
348 
349                                         /* find whether dependent l is installed or unpacked,
350                                          * and then find which package in the list satisfies it */
351                                         for (m = 0; m < all->len; m++) {
352                                                 dep = all->pkgs[m];
353                                                 if (dep->state_status !=
354                                                     SS_NOT_INSTALLED)
355                                                         if (!strcmp
356                                                             (dep->name,
357                                                              dependents[l]->
358                                                              name)) {
359                                                                 opkg_recurse_pkgs_in_order
360                                                                     (dep, all,
361                                                                      visited,
362                                                                      ordered);
363                                                                 /* Stop the outer loop */
364                                                                 l = abpkg->
365                                                                     provided_by->
366                                                                     len;
367                                                                 /* break from the inner loop */
368                                                                 break;
369                                                         }
370                                         }
371                                         l++;
372                                 }
373                 }
374         }
375 
376         /* When all recursions from this node down, are over, and all
377            dependencies have been added in proper order in the ordered array, add
378            also the package pkg to ordered array */
379         pkg_vec_insert(ordered, pkg);
380 
381         return 0;
382 
383 }
384 
385 static int opkg_configure_packages(char *pkg_name)
386 {
387         pkg_vec_t *all, *ordered, *visited;
388         int i;
389         pkg_t *pkg;
390         opkg_intercept_t ic;
391         int r, err = 0;
392 
393         opkg_msg(INFO, "Configuring unpacked packages.\n");
394 
395         all = pkg_vec_alloc();
396 
397         pkg_hash_fetch_available(all);
398 
399         /* Reorder pkgs in order to be configured according to the Depends: tag
400            order */
401         opkg_msg(INFO, "Reordering packages before configuring them...\n");
402         ordered = pkg_vec_alloc();
403         visited = pkg_vec_alloc();
404         for (i = 0; i < all->len; i++) {
405                 pkg = all->pkgs[i];
406                 opkg_recurse_pkgs_in_order(pkg, all, visited, ordered);
407         }
408 
409         ic = opkg_prep_intercepts();
410         if (ic == NULL) {
411                 err = -1;
412                 goto error;
413         }
414 
415         for (i = 0; i < ordered->len; i++) {
416                 pkg = ordered->pkgs[i];
417 
418                 if (pkg_name && fnmatch(pkg_name, pkg->name, conf->nocase))
419                         continue;
420 
421                 if (pkg->state_status == SS_UNPACKED) {
422                         opkg_msg(NOTICE, "Configuring %s.\n", pkg->name);
423                         r = opkg_configure(pkg);
424                         if (r == 0) {
425                                 pkg->state_status = SS_INSTALLED;
426                                 pkg->parent->state_status = SS_INSTALLED;
427                                 pkg->state_flag &= ~SF_PREFER;
428                                 opkg_state_changed++;
429                         } else {
430                                 err = -1;
431                         }
432                 }
433         }
434 
435         if (opkg_finalize_intercepts(ic))
436                 err = -1;
437 
438 error:
439         pkg_vec_free(all);
440         pkg_vec_free(ordered);
441         pkg_vec_free(visited);
442 
443         return err;
444 }
445 
446 static int opkg_remove_cmd(int argc, char **argv);
447 
448 static int opkg_install_cmd(int argc, char **argv)
449 {
450         int i;
451         char *arg;
452         int err = 0;
453 
454         signal(SIGINT, sigint_handler);
455 
456         /*
457          * Now scan through package names and install
458          */
459         for (i = 0; i < argc; i++) {
460                 arg = argv[i];
461 
462                 opkg_msg(DEBUG2, "%s\n", arg);
463                 if (opkg_prepare_url_for_install(arg, &argv[i]))
464                         return -1;
465         }
466 
467         pkg_hash_load_package_details();
468         pkg_hash_load_status_files(NULL, NULL);
469 
470         if (conf->force_reinstall) {
471                 int saved_force_depends = conf->force_depends;
472                 conf->force_depends = 1;
473                 (void)opkg_remove_cmd(argc, argv);
474                 conf->force_depends = saved_force_depends;
475                 conf->force_reinstall = 0;
476         }
477 
478         pkg_info_preinstall_check();
479 
480         for (i = 0; i < argc; i++) {
481                 arg = argv[i];
482                 if (opkg_install_by_name(arg)) {
483                         opkg_msg(ERROR, "Cannot install package %s.\n", arg);
484                         err = -1;
485                 }
486         }
487 
488         if (opkg_configure_packages(NULL))
489                 err = -1;
490 
491         write_status_files_if_changed();
492 
493         return err;
494 }
495 
496 static int opkg_upgrade_cmd(int argc, char **argv)
497 {
498         int i;
499         pkg_t *pkg;
500         int err = 0;
501 
502         signal(SIGINT, sigint_handler);
503 
504         if (argc) {
505                 for (i = 0; i < argc; i++) {
506                         char *arg = argv[i];
507 
508                         if (opkg_prepare_url_for_install(arg, &arg))
509                                 return -1;
510                 }
511                 pkg_info_preinstall_check();
512 
513                 for (i = 0; i < argc; i++) {
514                         char *arg = argv[i];
515                         if (conf->restrict_to_default_dest) {
516                                 pkg =
517                                     pkg_hash_fetch_installed_by_name_dest(argv
518                                                                           [i],
519                                                                           conf->
520                                                                           default_dest);
521                                 if (pkg == NULL) {
522                                         opkg_msg(NOTICE,
523                                                  "Package %s not installed in %s.\n",
524                                                  argv[i],
525                                                  conf->default_dest->name);
526                                         continue;
527                                 }
528                         } else {
529                                 pkg = pkg_hash_fetch_installed_by_name(argv[i]);
530                         }
531                         if (pkg) {
532                                 if (opkg_upgrade_pkg(pkg))
533                                         err = -1;
534                         } else {
535                                 if (opkg_install_by_name(arg))
536                                         err = -1;
537                         }
538                 }
539         }
540 
541         if (opkg_configure_packages(NULL))
542                 err = -1;
543 
544         write_status_files_if_changed();
545 
546         return err;
547 }
548 
549 static int opkg_download_cmd(int argc, char **argv)
550 {
551         int i, err = 0;
552         char *arg;
553         pkg_t *pkg;
554 
555         pkg_info_preinstall_check();
556         for (i = 0; i < argc; i++) {
557                 arg = argv[i];
558 
559                 pkg = pkg_hash_fetch_best_installation_candidate_by_name(arg);
560                 if (pkg == NULL) {
561                         opkg_msg(ERROR, "Cannot find package %s.\n", arg);
562                         continue;
563                 }
564 
565                 if (opkg_download_pkg(pkg, "."))
566                         err = -1;
567 
568                 if (err) {
569                         opkg_msg(ERROR, "Failed to download %s.\n", pkg->name);
570                 } else {
571                         opkg_msg(NOTICE, "Downloaded %s as %s.\n",
572                                  pkg->name, pkg_get_string(pkg, PKG_LOCAL_FILENAME));
573                 }
574         }
575 
576         return err;
577 }
578 
579 struct opkg_list_find_cmd_item {
580         int size;
581         char *name;
582         char *version;
583         char *description;
584 };
585 
586 struct opkg_list_find_cmd_args {
587         int use_desc;
588         int set_status;
589         char *pkg_name;
590         struct opkg_list_find_cmd_item **items;
591         size_t n_items;
592 };
593 
594 static void opkg_list_find_cmd_cb(pkg_t *pkg, void *priv)
595 {
596         struct opkg_list_find_cmd_args *args = priv;
597         char *description = pkg_get_string(pkg, PKG_DESCRIPTION);
598         char *version = pkg_version_str_alloc(pkg);
599         struct opkg_list_find_cmd_item *item;
600         char *nameptr, *versionptr, *descriptionptr, *tmp;
601         const char *abiver;
602         int i, found = 0;
603 
604         /* if we have package name or pattern and pkg does not match, then skip it */
605         if (args->pkg_name && fnmatch(args->pkg_name, pkg->name, conf->nocase) &&
606             (!args->use_desc || !description
607              || fnmatch(args->pkg_name, description, conf->nocase)))
608                 goto out;
609 
610         if (args->set_status) {
611                 for (i = 0; i < args->n_items; i++) {
612                         if (!strcmp(args->items[i]->name, pkg->name)) {
613                                 found = 1;
614                                 break;
615                         }
616                 }
617         }
618 
619         if (!found) {
620                 item = calloc_a(sizeof(*item),
621                                 &nameptr, strlen(pkg->name) + 1,
622                                 &versionptr, strlen(version) + 1,
623                                 &descriptionptr, description ? strlen(description) + 1 : 0);
624 
625                 item->name = strcpy(nameptr, pkg->name);
626 
627                 if (conf->strip_abi &&
628                     (abiver = pkg_get_string(pkg, PKG_ABIVERSION)) &&
629                     (strlen(item->name) > strlen(abiver))) {
630                         tmp = &item->name[strlen(item->name) - strlen(abiver)];
631                         if (!strncmp(abiver, tmp, strlen(abiver)))
632                                 *tmp = '\0';
633                 };
634 
635                 item->size = pkg_get_int(pkg, PKG_SIZE);
636                 item->version = strcpy(versionptr, version);
637                 item->description = description ? strcpy(descriptionptr, description) : NULL;
638 
639                 args->items = xrealloc(args->items, sizeof(item) * (args->n_items + 1));
640                 args->items[args->n_items++] = item;
641         }
642 
643 out:
644         pkg_deinit(pkg);
645         free(pkg);
646         free(version);
647 }
648 
649 static int opkg_list_find_cmd_sort(const void *a, const void *b)
650 {
651         const struct opkg_list_find_cmd_item *pkg_a = *(const struct opkg_list_find_cmd_item **)a;
652         const struct opkg_list_find_cmd_item *pkg_b = *(const struct opkg_list_find_cmd_item **)b;
653         return strcmp(pkg_a->name, pkg_b->name);
654 }
655 
656 static int opkg_list_find_cmd(int argc, char **argv, int use_desc)
657 {
658         int i;
659         struct opkg_list_find_cmd_args args = {
660                 .use_desc = use_desc,
661                 .pkg_name = (argc > 0) ? argv[0] : NULL
662         };
663 
664         args.set_status = 0;
665         pkg_hash_load_feeds(SF_NEED_DETAIL, opkg_list_find_cmd_cb, &args);
666 
667         args.set_status = 1;
668         pkg_hash_load_status_files(opkg_list_find_cmd_cb, &args);
669 
670         if (args.n_items > 1)
671                 qsort(args.items, args.n_items, sizeof(args.items[0]),
672                       opkg_list_find_cmd_sort);
673 
674         for (i = 0; i < args.n_items; i++) {
675                 printf("%s - %s",
676                        args.items[i]->name,
677                        args.items[i]->version);
678 
679                 if (conf->size)
680                         printf(" - %lu", (unsigned long) args.items[i]->size);
681 
682                 if (args.items[i]->description)
683                         printf(" - %s", args.items[i]->description);
684 
685                 printf("\n");
686 
687                 free(args.items[i]);
688         }
689 
690         free(args.items);
691 
692         return 0;
693 }
694 
695 static int opkg_list_cmd(int argc, char **argv)
696 {
697         return opkg_list_find_cmd(argc, argv, 0);
698 }
699 
700 static int opkg_find_cmd(int argc, char **argv)
701 {
702         return opkg_list_find_cmd(argc, argv, 1);
703 }
704 
705 static int opkg_list_installed_cmd(int argc, char **argv)
706 {
707         int i;
708         pkg_vec_t *available;
709         pkg_t *pkg;
710         char *pkg_name = NULL;
711 
712         if (argc > 0) {
713                 pkg_name = argv[0];
714         }
715         available = pkg_vec_alloc();
716         pkg_hash_fetch_all_installed(available);
717         pkg_vec_sort(available, pkg_compare_names);
718         for (i = 0; i < available->len; i++) {
719                 pkg = available->pkgs[i];
720                 /* if we have package name or pattern and pkg does not match, then skip it */
721                 if (pkg_name && fnmatch(pkg_name, pkg->name, conf->nocase))
722                         continue;
723                 print_pkg(pkg);
724         }
725 
726         pkg_vec_free(available);
727 
728         return 0;
729 }
730 
731 static int opkg_list_changed_conffiles_cmd(int argc, char **argv)
732 {
733         int i;
734         pkg_vec_t *available;
735         pkg_t *pkg;
736         char *pkg_name = NULL;
737         conffile_list_elt_t *iter;
738         conffile_list_t *cl;
739         conffile_t *cf;
740 
741         if (argc > 0) {
742                 pkg_name = argv[0];
743         }
744         available = pkg_vec_alloc();
745         pkg_hash_fetch_all_installed(available);
746         pkg_vec_sort(available, pkg_compare_names);
747         for (i = 0; i < available->len; i++) {
748                 pkg = available->pkgs[i];
749                 cl = pkg_get_ptr(pkg, PKG_CONFFILES);
750                 /* if we have package name or pattern and pkg does not match, then skip it */
751                 if (pkg_name && fnmatch(pkg_name, pkg->name, conf->nocase))
752                         continue;
753                 if (!cl || nv_pair_list_empty(cl))
754                         continue;
755                 for (iter = nv_pair_list_first(cl); iter;
756                      iter = nv_pair_list_next(cl, iter)) {
757                         cf = (conffile_t *) iter->data;
758                         if (cf->name && cf->value
759                             && conffile_has_been_modified(cf))
760                                 printf("%s\n", cf->name);
761                 }
762         }
763         pkg_vec_free(available);
764         return 0;
765 }
766 
767 static int opkg_list_upgradable_cmd(int argc, char **argv)
768 {
769         struct active_list *head = prepare_upgrade_list();
770         struct active_list *node = NULL;
771         pkg_t *_old_pkg, *_new_pkg;
772         char *old_v, *new_v;
773         for (node = active_list_next(head, head); node;
774              node = active_list_next(head, node)) {
775                 _old_pkg = node->pkg;
776                 _new_pkg =
777                     pkg_hash_fetch_best_installation_candidate_by_name
778                     (_old_pkg->name);
779                 if (_new_pkg == NULL)
780                         continue;
781                 old_v = pkg_version_str_alloc(_old_pkg);
782                 new_v = pkg_version_str_alloc(_new_pkg);
783                 printf("%s - %s - %s\n", _old_pkg->name, old_v, new_v);
784                 free(old_v);
785                 free(new_v);
786         }
787         active_list_head_delete(head);
788         return 0;
789 }
790 
791 static int opkg_info_status_cmd(int argc, char **argv, int installed_only)
792 {
793         int i;
794         pkg_vec_t *available;
795         pkg_t *pkg;
796         char *pkg_name = NULL;
797         conffile_list_t *cl;
798 
799         if (argc > 0) {
800                 pkg_name = argv[0];
801         }
802 
803         available = pkg_vec_alloc();
804         if (installed_only)
805                 pkg_hash_fetch_all_installed(available);
806         else
807                 pkg_hash_fetch_available(available);
808 
809         for (i = 0; i < available->len; i++) {
810                 pkg = available->pkgs[i];
811                 if (pkg_name && fnmatch(pkg_name, pkg->name, conf->nocase)) {
812                         continue;
813                 }
814 
815                 pkg_formatted_info(stdout, pkg);
816 
817                 cl = pkg_get_ptr(pkg, PKG_CONFFILES);
818 
819                 if (conf->verbosity >= NOTICE && cl) {
820                         conffile_list_elt_t *iter;
821                         for (iter = nv_pair_list_first(cl); iter;
822                              iter = nv_pair_list_next(cl, iter)) {
823                                 conffile_t *cf = (conffile_t *) iter->data;
824                                 int modified = conffile_has_been_modified(cf);
825                                 if (cf->value)
826                                         opkg_msg(INFO,
827                                                  "conffile=%s md5sum=%s modified=%d.\n",
828                                                  cf->name, cf->value, modified);
829                         }
830                 }
831         }
832         pkg_vec_free(available);
833 
834         return 0;
835 }
836 
837 static int opkg_info_cmd(int argc, char **argv)
838 {
839         return opkg_info_status_cmd(argc, argv, 0);
840 }
841 
842 static int opkg_status_cmd(int argc, char **argv)
843 {
844         return opkg_info_status_cmd(argc, argv, 1);
845 }
846 
847 static int opkg_configure_cmd(int argc, char **argv)
848 {
849         int err;
850         char *pkg_name = NULL;
851 
852         if (argc > 0)
853                 pkg_name = argv[0];
854 
855         err = opkg_configure_packages(pkg_name);
856 
857         write_status_files_if_changed();
858 
859         return err;
860 }
861 
862 static int opkg_remove_cmd(int argc, char **argv)
863 {
864         int i, a, done, err = 0;
865         pkg_t *pkg;
866         pkg_t *pkg_to_remove;
867         pkg_vec_t *available;
868 
869         done = 0;
870 
871         signal(SIGINT, sigint_handler);
872 
873         pkg_info_preinstall_check();
874 
875         available = pkg_vec_alloc();
876         pkg_hash_fetch_all_installed(available);
877 
878         for (i = 0; i < argc; i++) {
879                 for (a = 0; a < available->len; a++) {
880                         pkg = available->pkgs[a];
881                         if (fnmatch(argv[i], pkg->name, conf->nocase)) {
882                                 continue;
883                         }
884                         if (conf->restrict_to_default_dest) {
885                                 pkg_to_remove =
886                                     pkg_hash_fetch_installed_by_name_dest(pkg->
887                                                                           name,
888                                                                           conf->
889                                                                           default_dest);
890                         } else {
891                                 pkg_to_remove =
892                                     pkg_hash_fetch_installed_by_name(pkg->name);
893                         }
894 
895                         if (pkg_to_remove == NULL) {
896                                 opkg_msg(ERROR,
897                                          "Package %s is not installed.\n",
898                                          pkg->name);
899                                 continue;
900                         }
901                         if (pkg->state_status == SS_NOT_INSTALLED) {
902                                 opkg_msg(ERROR, "Package %s not installed.\n",
903                                          pkg->name);
904                                 continue;
905                         }
906 
907                         if (opkg_remove_pkg(pkg_to_remove, 0))
908                                 err = -1;
909                         else
910                                 done = 1;
911                 }
912         }
913 
914         pkg_vec_free(available);
915 
916         if (done == 0)
917                 opkg_msg(NOTICE, "No packages removed.\n");
918 
919         write_status_files_if_changed();
920         return err;
921 }
922 
923 static int opkg_flag_cmd(int argc, char **argv)
924 {
925         int i;
926         pkg_t *pkg;
927         const char *flags = argv[0];
928 
929         signal(SIGINT, sigint_handler);
930 
931         for (i = 1; i < argc; i++) {
932                 if (conf->restrict_to_default_dest) {
933                         pkg = pkg_hash_fetch_installed_by_name_dest(argv[i],
934                                                                     conf->
935                                                                     default_dest);
936                 } else {
937                         pkg = pkg_hash_fetch_installed_by_name(argv[i]);
938                 }
939 
940                 if (pkg == NULL) {
941                         opkg_msg(ERROR, "Package %s is not installed.\n",
942                                  argv[i]);
943                         continue;
944                 }
945                 if ((strcmp(flags, "hold") == 0)
946                     || (strcmp(flags, "noprune") == 0)
947                     || (strcmp(flags, "user") == 0)
948                     || (strcmp(flags, "ok") == 0)) {
949                         pkg->state_flag = pkg_state_flag_from_str(flags);
950                 }
951 
952                 /*
953                  * Useful if a package is installed in an offline_root, and
954                  * should be configured by opkg-cl configure at a later date.
955                  */
956                 if ((strcmp(flags, "installed") == 0)
957                     || (strcmp(flags, "unpacked") == 0)) {
958                         pkg->state_status = pkg_state_status_from_str(flags);
959                 }
960 
961                 opkg_state_changed++;
962                 opkg_msg(NOTICE, "Setting flags for package %s to %s.\n",
963                          pkg->name, flags);
964         }
965 
966         write_status_files_if_changed();
967         return 0;
968 }
969 
970 static int opkg_files_cmd(int argc, char **argv)
971 {
972         pkg_t *pkg;
973         str_list_t *files;
974         str_list_elt_t *iter;
975         char *pkg_version;
976 
977         if (argc < 1) {
978                 return -1;
979         }
980 
981         pkg = pkg_hash_fetch_installed_by_name(argv[0]);
982         if (pkg == NULL) {
983                 opkg_msg(ERROR, "Package %s not installed.\n", argv[0]);
984                 return 0;
985         }
986 
987         files = pkg_get_installed_files(pkg);
988         pkg_version = pkg_version_str_alloc(pkg);
989 
990         printf
991             ("Package %s (%s) is installed on %s and has the following files:\n",
992              pkg->name, pkg_version, pkg->dest->name);
993 
994         for (iter = str_list_first(files); iter;
995              iter = str_list_next(files, iter))
996                 printf("%s\n", (char *)iter->data);
997 
998         free(pkg_version);
999         pkg_free_installed_files(pkg);
1000 
1001         return 0;
1002 }
1003 
1004 static int opkg_depends_cmd(int argc, char **argv)
1005 {
1006         int i, j, k;
1007         pkg_vec_t *available_pkgs;
1008         compound_depend_t *cdep;
1009         pkg_t *pkg;
1010         char *str;
1011 
1012         pkg_info_preinstall_check();
1013 
1014         available_pkgs = pkg_vec_alloc();
1015         if (conf->query_all)
1016                 pkg_hash_fetch_available(available_pkgs);
1017         else
1018                 pkg_hash_fetch_all_installed(available_pkgs);
1019 
1020         for (i = 0; i < argc; i++) {
1021                 for (j = 0; j < available_pkgs->len; j++) {
1022                         pkg = available_pkgs->pkgs[j];
1023 
1024                         if (fnmatch(argv[i], pkg->name, conf->nocase) != 0)
1025                                 continue;
1026 
1027                         opkg_msg(NOTICE, "%s depends on:\n", pkg->name);
1028 
1029                         for (k = 0, cdep = pkg_get_ptr(pkg, PKG_DEPENDS); cdep && cdep->type; k++, cdep++) {
1030                                 if (cdep->type != DEPEND)
1031                                         continue;
1032 
1033                                 str = pkg_depend_str(pkg, k);
1034                                 opkg_msg(NOTICE, "\t%s\n", str);
1035                                 free(str);
1036                         }
1037 
1038                 }
1039         }
1040 
1041         pkg_vec_free(available_pkgs);
1042         return 0;
1043 }
1044 
1045 static int pkg_mark_provides(pkg_t * pkg)
1046 {
1047         abstract_pkg_t **provider = pkg_get_ptr(pkg, PKG_PROVIDES);
1048 
1049         pkg->parent->state_flag |= SF_MARKED;
1050 
1051         while (provider && *provider) {
1052                 (*provider)->state_flag |= SF_MARKED;
1053                 provider++;
1054         }
1055 
1056         return 0;
1057 }
1058 
1059 enum what_field_type {
1060         WHATDEPENDS,
1061         WHATCONFLICTS,
1062         WHATPROVIDES,
1063         WHATREPLACES,
1064         WHATRECOMMENDS,
1065         WHATSUGGESTS
1066 };
1067 
1068 static int
1069 opkg_what_depends_conflicts_cmd(enum depend_type what_field_type, int recursive,
1070                                 int argc, char **argv)
1071 {
1072         depend_t *possibility;
1073         compound_depend_t *cdep, *deps;
1074         pkg_vec_t *available_pkgs;
1075         pkg_t *pkg;
1076         int i, j, l;
1077         int changed;
1078         const char *rel_str = NULL;
1079         char *ver;
1080 
1081         switch (what_field_type) {
1082         case DEPEND:
1083                 rel_str = "depends on";
1084                 break;
1085         case CONFLICTS:
1086                 rel_str = "conflicts with";
1087                 break;
1088         case SUGGEST:
1089                 rel_str = "suggests";
1090                 break;
1091         case RECOMMEND:
1092                 rel_str = "recommends";
1093                 break;
1094         default:
1095                 return -1;
1096         }
1097 
1098         available_pkgs = pkg_vec_alloc();
1099 
1100         if (conf->query_all)
1101                 pkg_hash_fetch_available(available_pkgs);
1102         else
1103                 pkg_hash_fetch_all_installed(available_pkgs);
1104 
1105         /* mark the root set */
1106         pkg_vec_clear_marks(available_pkgs);
1107         opkg_msg(NOTICE, "Root set:\n");
1108         for (i = 0; i < argc; i++)
1109                 pkg_vec_mark_if_matches(available_pkgs, argv[i]);
1110 
1111         for (i = 0; i < available_pkgs->len; i++) {
1112                 pkg = available_pkgs->pkgs[i];
1113                 if (pkg->state_flag & SF_MARKED) {
1114                         /* mark the parent (abstract) package */
1115                         pkg_mark_provides(pkg);
1116                         opkg_msg(NOTICE, "  %s\n", pkg->name);
1117                 }
1118         }
1119 
1120         opkg_msg(NOTICE, "What %s root set\n", rel_str);
1121         do {
1122                 changed = 0;
1123 
1124                 for (j = 0; j < available_pkgs->len; j++) {
1125 
1126                         pkg = available_pkgs->pkgs[j];
1127                         /*
1128                         count = ((what_field_type == CONFLICTS)
1129                                  ? pkg->conflicts_count
1130                                  : pkg->pre_depends_count +
1131                                  pkg->depends_count +
1132                                  pkg->recommends_count + pkg->suggests_count);
1133                                  */
1134 
1135                         /* skip this package if it is already marked */
1136                         if (pkg->parent->state_flag & SF_MARKED)
1137                                 continue;
1138 
1139                         deps = pkg_get_ptr(pkg, (what_field_type == CONFLICTS) ? PKG_CONFLICTS : PKG_DEPENDS);
1140 
1141                         for (cdep = deps; cdep && cdep->type; cdep++) {
1142                                 if (what_field_type != cdep->type)
1143                                         continue;
1144 
1145                                 for (l = 0; l < cdep->possibility_count; l++) {
1146                                         possibility = cdep->possibilities[l];
1147 
1148                                         if ((possibility->pkg->state_flag
1149                                              & SF_MARKED)
1150                                             != SF_MARKED)
1151                                                 continue;
1152 
1153                                         /* mark the depending package so we
1154                                          * won't visit it again */
1155                                         pkg->state_flag |= SF_MARKED;
1156                                         pkg_mark_provides(pkg);
1157                                         changed++;
1158 
1159                                         ver = pkg_version_str_alloc(pkg);
1160                                         opkg_msg(NOTICE, "\t%s %s\t%s %s",
1161                                                  pkg->name,
1162                                                  ver,
1163                                                  rel_str,
1164                                                  possibility->pkg->name);
1165                                         free(ver);
1166                                         if (possibility->version) {
1167                                                 opkg_msg(NOTICE, " (%s%s)",
1168                                                          constraint_to_str
1169                                                          (possibility->
1170                                                           constraint),
1171                                                          possibility->version);
1172                                         }
1173                                         if (!pkg_dependence_satisfiable
1174                                             (possibility))
1175                                                 opkg_msg(NOTICE,
1176                                                          " unsatisfiable");
1177                                         opkg_message(NOTICE, "\n");
1178                                         goto next_package;
1179                                 }
1180                         }
1181 next_package:
1182                         ;
1183                 }
1184         } while (changed && recursive);
1185 
1186         pkg_vec_free(available_pkgs);
1187 
1188         return 0;
1189 }
1190 
1191 static int opkg_whatdepends_recursively_cmd(int argc, char **argv)
1192 {
1193         return opkg_what_depends_conflicts_cmd(DEPEND, 1, argc, argv);
1194 }
1195 
1196 static int opkg_whatdepends_cmd(int argc, char **argv)
1197 {
1198         return opkg_what_depends_conflicts_cmd(DEPEND, 0, argc, argv);
1199 }
1200 
1201 static int opkg_whatsuggests_cmd(int argc, char **argv)
1202 {
1203         return opkg_what_depends_conflicts_cmd(SUGGEST, 0, argc, argv);
1204 }
1205 
1206 static int opkg_whatrecommends_cmd(int argc, char **argv)
1207 {
1208         return opkg_what_depends_conflicts_cmd(RECOMMEND, 0, argc, argv);
1209 }
1210 
1211 static int opkg_whatconflicts_cmd(int argc, char **argv)
1212 {
1213         return opkg_what_depends_conflicts_cmd(CONFLICTS, 0, argc, argv);
1214 }
1215 
1216 static int
1217 opkg_what_provides_replaces_cmd(enum what_field_type what_field_type, int argc,
1218                                 char **argv)
1219 {
1220         abstract_pkg_t *apkg, **abpkgs;
1221 
1222         if (argc > 0) {
1223                 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1224                 const char *rel_str =
1225                     (what_field_type == WHATPROVIDES ? "provides" : "replaces");
1226                 int i;
1227 
1228                 pkg_info_preinstall_check();
1229 
1230                 if (conf->query_all)
1231                         pkg_hash_fetch_available(available_pkgs);
1232                 else
1233                         pkg_hash_fetch_all_installed(available_pkgs);
1234                 for (i = 0; i < argc; i++) {
1235                         const char *target = argv[i];
1236                         int j;
1237 
1238                         opkg_msg(NOTICE, "What %s %s\n", rel_str, target);
1239                         for (j = 0; j < available_pkgs->len; j++) {
1240                                 pkg_t *pkg = available_pkgs->pkgs[j];
1241                                 abpkgs = pkg_get_ptr(pkg, (what_field_type == WHATPROVIDES) ? PKG_PROVIDES : PKG_REPLACES);
1242 
1243                                 while (abpkgs && *abpkgs) {
1244                                         apkg = *abpkgs++;
1245 
1246                                         if (fnmatch(target, apkg->name, conf->nocase))
1247                                                 continue;
1248 
1249                                         opkg_msg(NOTICE, "    %s", pkg->name);
1250 
1251                                         if ((conf->nocase ? strcasecmp(target, apkg->name)
1252                                             : strcmp(target, apkg->name)))
1253                                                 opkg_msg(NOTICE, "\t%s %s\n", rel_str, apkg->name);
1254 
1255                                         opkg_message(NOTICE, "\n");
1256                                 }
1257                         }
1258                 }
1259                 pkg_vec_free(available_pkgs);
1260         }
1261         return 0;
1262 }
1263 
1264 static int opkg_whatprovides_cmd(int argc, char **argv)
1265 {
1266         return opkg_what_provides_replaces_cmd(WHATPROVIDES, argc, argv);
1267 }
1268 
1269 static int opkg_whatreplaces_cmd(int argc, char **argv)
1270 {
1271         return opkg_what_provides_replaces_cmd(WHATREPLACES, argc, argv);
1272 }
1273 
1274 static int opkg_search_cmd(int argc, char **argv)
1275 {
1276         int i;
1277 
1278         pkg_vec_t *installed;
1279         pkg_t *pkg;
1280         str_list_t *installed_files;
1281         str_list_elt_t *iter;
1282         char *installed_file;
1283 
1284         if (argc < 1) {
1285                 return -1;
1286         }
1287 
1288         installed = pkg_vec_alloc();
1289         pkg_hash_fetch_all_installed(installed);
1290         pkg_vec_sort(installed, pkg_compare_names);
1291 
1292         for (i = 0; i < installed->len; i++) {
1293                 pkg = installed->pkgs[i];
1294 
1295                 installed_files = pkg_get_installed_files(pkg);
1296 
1297                 for (iter = str_list_first(installed_files); iter;
1298                      iter = str_list_next(installed_files, iter)) {
1299                         installed_file = (char *)iter->data;
1300                         if (fnmatch(argv[0], installed_file, conf->nocase) == 0)
1301                                 print_pkg(pkg);
1302                 }
1303 
1304                 pkg_free_installed_files(pkg);
1305         }
1306 
1307         pkg_vec_free(installed);
1308 
1309         return 0;
1310 }
1311 
1312 static int opkg_compare_versions_cmd(int argc, char **argv)
1313 {
1314         int rc;
1315         pkg_t *p1, *p2;
1316 
1317         if (argc == 3) {
1318                 /* this is a bit gross */
1319                 p1 = pkg_new();
1320                 p2 = pkg_new();
1321                 parse_version(p1, argv[0]);
1322                 parse_version(p2, argv[2]);
1323                 rc = pkg_version_satisfied(p1, p2, argv[1]);
1324                 pkg_deinit(p1);
1325                 pkg_deinit(p2);
1326                 free(p1);
1327                 free(p2);
1328                 return rc ? 0 : 1;
1329         } else {
1330                 opkg_msg(ERROR,
1331                          "opkg compare_versions <v1> <op> <v2>\n"
1332                          "<op> is one of <= >= << >> =\n");
1333                 return -1;
1334         }
1335 }
1336 
1337 static int opkg_print_architecture_cmd(int argc, char **argv)
1338 {
1339         nv_pair_list_elt_t *l;
1340 
1341         list_for_each_entry(l, &conf->arch_list.head, node) {
1342                 nv_pair_t *nv = (nv_pair_t *) l->data;
1343                 printf("arch %s %s\n", nv->name, nv->value);
1344         }
1345         return 0;
1346 }
1347 
1348 /* XXX: CLEANUP: The usage strings should be incorporated into this
1349    array for easier maintenance */
1350 static opkg_cmd_t cmds[] = {
1351         {"update", 0, (opkg_cmd_fun_t) opkg_update_cmd,
1352          PFM_DESCRIPTION | PFM_SOURCE},
1353         {"upgrade", 1, (opkg_cmd_fun_t) opkg_upgrade_cmd,
1354          PFM_DESCRIPTION | PFM_SOURCE},
1355         {"list", 0, (opkg_cmd_fun_t) opkg_list_cmd, PFM_SOURCE},
1356         {"list_installed", 0, (opkg_cmd_fun_t) opkg_list_installed_cmd,
1357          PFM_SOURCE},
1358         {"list-installed", 0, (opkg_cmd_fun_t) opkg_list_installed_cmd,
1359          PFM_SOURCE},
1360         {"list_upgradable", 0, (opkg_cmd_fun_t) opkg_list_upgradable_cmd,
1361          PFM_SOURCE},
1362         {"list-upgradable", 0, (opkg_cmd_fun_t) opkg_list_upgradable_cmd,
1363          PFM_SOURCE},
1364         {"list_changed_conffiles", 0,
1365          (opkg_cmd_fun_t) opkg_list_changed_conffiles_cmd, PFM_SOURCE},
1366         {"list-changed-conffiles", 0,
1367          (opkg_cmd_fun_t) opkg_list_changed_conffiles_cmd, PFM_SOURCE},
1368         {"info", 0, (opkg_cmd_fun_t) opkg_info_cmd, 0},
1369         {"flag", 1, (opkg_cmd_fun_t) opkg_flag_cmd,
1370          PFM_DESCRIPTION | PFM_SOURCE},
1371         {"status", 0, (opkg_cmd_fun_t) opkg_status_cmd,
1372          PFM_DESCRIPTION | PFM_SOURCE},
1373         {"install", 1, (opkg_cmd_fun_t) opkg_install_cmd,
1374          PFM_DESCRIPTION | PFM_SOURCE},
1375         {"remove", 1, (opkg_cmd_fun_t) opkg_remove_cmd,
1376          PFM_DESCRIPTION | PFM_SOURCE},
1377         {"configure", 0, (opkg_cmd_fun_t) opkg_configure_cmd,
1378          PFM_DESCRIPTION | PFM_SOURCE},
1379         {"files", 1, (opkg_cmd_fun_t) opkg_files_cmd,
1380          PFM_DESCRIPTION | PFM_SOURCE},
1381         {"search", 1, (opkg_cmd_fun_t) opkg_search_cmd,
1382          PFM_DESCRIPTION | PFM_SOURCE},
1383         {"find", 1, (opkg_cmd_fun_t) opkg_find_cmd, PFM_SOURCE},
1384         {"download", 1, (opkg_cmd_fun_t) opkg_download_cmd,
1385          PFM_DESCRIPTION | PFM_SOURCE},
1386         {"compare_versions", 1, (opkg_cmd_fun_t) opkg_compare_versions_cmd, 0},
1387         {"compare-versions", 1, (opkg_cmd_fun_t) opkg_compare_versions_cmd, 0},
1388         {"print-architecture", 0, (opkg_cmd_fun_t) opkg_print_architecture_cmd,
1389          PFM_DESCRIPTION | PFM_SOURCE},
1390         {"print_architecture", 0, (opkg_cmd_fun_t) opkg_print_architecture_cmd,
1391          PFM_DESCRIPTION | PFM_SOURCE},
1392         {"print-installation-architecture", 0,
1393          (opkg_cmd_fun_t) opkg_print_architecture_cmd,
1394          PFM_DESCRIPTION | PFM_SOURCE},
1395         {"print_installation_architecture", 0,
1396          (opkg_cmd_fun_t) opkg_print_architecture_cmd,
1397          PFM_DESCRIPTION | PFM_SOURCE},
1398         {"depends", 1, (opkg_cmd_fun_t) opkg_depends_cmd,
1399          PFM_DESCRIPTION | PFM_SOURCE},
1400         {"whatdepends", 1, (opkg_cmd_fun_t) opkg_whatdepends_cmd,
1401          PFM_DESCRIPTION | PFM_SOURCE},
1402         {"whatdependsrec", 1, (opkg_cmd_fun_t) opkg_whatdepends_recursively_cmd,
1403          PFM_DESCRIPTION | PFM_SOURCE},
1404         {"whatrecommends", 1, (opkg_cmd_fun_t) opkg_whatrecommends_cmd,
1405          PFM_DESCRIPTION | PFM_SOURCE},
1406         {"whatsuggests", 1, (opkg_cmd_fun_t) opkg_whatsuggests_cmd,
1407          PFM_DESCRIPTION | PFM_SOURCE},
1408         {"whatprovides", 1, (opkg_cmd_fun_t) opkg_whatprovides_cmd,
1409          PFM_DESCRIPTION | PFM_SOURCE},
1410         {"whatreplaces", 1, (opkg_cmd_fun_t) opkg_whatreplaces_cmd,
1411          PFM_DESCRIPTION | PFM_SOURCE},
1412         {"whatconflicts", 1, (opkg_cmd_fun_t) opkg_whatconflicts_cmd,
1413          PFM_DESCRIPTION | PFM_SOURCE},
1414 };
1415 
1416 opkg_cmd_t *opkg_cmd_find(const char *name)
1417 {
1418         int i;
1419         opkg_cmd_t *cmd;
1420         int num_cmds = sizeof(cmds) / sizeof(opkg_cmd_t);
1421 
1422         for (i = 0; i < num_cmds; i++) {
1423                 cmd = &cmds[i];
1424                 if (strcmp(name, cmd->name) == 0)
1425                         return cmd;
1426         }
1427 
1428         return NULL;
1429 }
1430 
1431 int opkg_cmd_exec(opkg_cmd_t * cmd, int argc, const char **argv)
1432 {
1433         opkg_cli_argc = argc;
1434         opkg_cli_argv = argv;
1435         return (cmd->fun) (argc, argv);
1436 }
1437 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt