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

This page was automatically generated by LXR 0.3.1.  •  OpenWrt