From 3755e1cde35828aad4af0578d4271af6b7d57b61 Mon Sep 17 00:00:00 2001 From: Timo Teras Date: Tue, 13 Jan 2009 14:09:45 +0200 Subject: apk: per applet options --- src/add.c | 2 +- src/apk.c | 100 +++++++++++++++++++++++++++++++++++++---------------- src/apk_applet.h | 12 +++++-- src/apk_database.h | 1 + src/create.c | 2 +- src/database.c | 7 +++- src/del.c | 2 +- src/index.c | 2 +- src/info.c | 79 +++++++++++++++++++++++++++++++++++++----- src/ver.c | 2 +- 10 files changed, 163 insertions(+), 46 deletions(-) diff --git a/src/add.c b/src/add.c index 562ce269a7..2716fe4835 100644 --- a/src/add.c +++ b/src/add.c @@ -13,7 +13,7 @@ #include "apk_applet.h" #include "apk_database.h" -static int add_main(int argc, char **argv) +static int add_main(void *ctx, int argc, char **argv) { struct apk_database db; int i; diff --git a/src/apk.c b/src/apk.c index e874cbb3e7..4062e568b2 100644 --- a/src/apk.c +++ b/src/apk.c @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -67,21 +68,11 @@ static struct apk_applet *find_applet(const char *name) return NULL; } -int main(int argc, char **argv) +static struct apk_applet *deduce_applet(int argc, char **argv) { - static struct option generic_options[] = { - {"root", required_argument, NULL, 'Q' }, - {"repository", required_argument, NULL, 'X' }, - {"quiet", no_argument, NULL, 'q' }, - {"progress", no_argument, NULL, 0x100 }, - {0, 0, 0, 0}, - }; - struct apk_applet *applet = NULL; + struct apk_applet *a; const char *prog; - int r; - - umask(0); - apk_cwd_fd = open(".", O_RDONLY); + int i; prog = strrchr(argv[0], '/'); if (prog == NULL) @@ -90,10 +81,64 @@ int main(int argc, char **argv) prog++; if (strncmp(prog, "apk_", 4) == 0) - applet = find_applet(prog + 4); + return find_applet(prog + 4); + + for (i = 1; i < argc; i++) { + if (argv[i][0] == '-') + continue; + + a = find_applet(argv[i]); + if (a != NULL) + return a; + } + + return NULL; +} + +#define NUM_GENERIC_OPTS 4 +static struct option generic_options[32] = { + { "root", required_argument, NULL, 'Q' }, + { "repository", required_argument, NULL, 'X' }, + { "quiet", no_argument, NULL, 'q' }, + { "progress", no_argument, NULL, 0x100 }, +}; + +int main(int argc, char **argv) +{ + struct apk_applet *applet; + char short_options[256], *sopt; + struct option *opt; + int r, optindex; + void *ctx = NULL; - while ((r = getopt_long(argc, argv, "", - generic_options, NULL)) != -1) { + umask(0); + apk_cwd_fd = open(".", O_RDONLY); + apk_root = getenv("ROOT"); + + applet = deduce_applet(argc, argv); + if (applet == NULL) + return usage(); + + if (applet->num_options && applet->options) { + memcpy(&generic_options[NUM_GENERIC_OPTS], + applet->options, + applet->num_options * sizeof(struct option)); + } + for (opt = &generic_options[0], sopt = short_options; + opt->name != NULL; opt++) { + if (opt->flag == NULL && isalnum(opt->val)) { + *(sopt++) = opt->val; + if (opt->has_arg != no_argument) + *(sopt++) = ':'; + } + } + + if (applet->context_size != 0) + ctx = calloc(1, applet->context_size); + + optindex = 0; + while ((r = getopt_long(argc, argv, short_options, + generic_options, &optindex)) != -1) { switch (r) { case 'Q': apk_root = optarg; @@ -108,27 +153,24 @@ int main(int argc, char **argv) apk_progress = 1; break; default: - return usage(); + if (applet->parse == NULL) + return usage(); + if (applet->parse(ctx, r, optindex - NUM_GENERIC_OPTS, + optarg) != 0) + return usage(); + break; } } - argc -= optind; - argv += optind; - - if (apk_root == NULL) - apk_root = getenv("ROOT"); if (apk_root == NULL) apk_root = "/"; - if (applet == NULL) { - if (argc > 0) - applet = find_applet(argv[0]); - if (applet == NULL) - return usage(); - + argc -= optind; + argv += optind; + if (argc >= 1 && strcmp(argv[0], applet->name) == 0) { argc--; argv++; } - return applet->main(argc, argv); + return applet->main(ctx, argc, argv); } diff --git a/src/apk_applet.h b/src/apk_applet.h index e4c2e1dcef..4fdce0d81b 100644 --- a/src/apk_applet.h +++ b/src/apk_applet.h @@ -12,13 +12,21 @@ #ifndef APK_APPLET_H #define APK_APPLET_H +#include + extern const char *apk_root; extern const char *apk_repository; struct apk_applet { const char *name; - const char *usage; - int (*main)(int argc, char **argv); + const char *usage; + + int context_size; + int num_options; + struct option *options; + + int (*parse)(void *ctx, int optch, int optindex, const char *optarg); + int (*main)(void *ctx, int argc, char **argv); }; extern struct apk_applet *__start_apkapplets, *__stop_apkapplets; diff --git a/src/apk_database.h b/src/apk_database.h index 06d7b6d81a..c6134d75e1 100644 --- a/src/apk_database.h +++ b/src/apk_database.h @@ -93,6 +93,7 @@ typedef union apk_database_or_void { } apk_database_t __attribute__ ((__transparent_union__)); struct apk_name *apk_db_get_name(struct apk_database *db, apk_blob_t name); +struct apk_name *apk_db_query_name(struct apk_database *db, apk_blob_t name); void apk_name_free(struct apk_name *pkgname); int apk_db_create(const char *root); diff --git a/src/create.c b/src/create.c index c1dbea3a7d..d12abfbef6 100644 --- a/src/create.c +++ b/src/create.c @@ -13,7 +13,7 @@ #include "apk_applet.h" #include "apk_database.h" -static int create_main(int argc, char **argv) +static int create_main(void *ctx, int argc, char **argv) { if (strcmp(apk_root, "/") == 0) { apk_error("Will not recreate system root."); diff --git a/src/database.c b/src/database.c index a45d8d143a..373acb6525 100644 --- a/src/database.c +++ b/src/database.c @@ -87,11 +87,16 @@ static const struct apk_hash_ops dir_hash_ops = { .delete_item = (apk_hash_delete_f) free, }; +struct apk_name *apk_db_query_name(struct apk_database *db, apk_blob_t name) +{ + return (struct apk_name *) apk_hash_get(&db->available.names, name); +} + struct apk_name *apk_db_get_name(struct apk_database *db, apk_blob_t name) { struct apk_name *pn; - pn = (struct apk_name *) apk_hash_get(&db->available.names, name); + pn = apk_db_query_name(db, name); if (pn != NULL) return pn; diff --git a/src/del.c b/src/del.c index 2fc604876b..546a4db7d4 100644 --- a/src/del.c +++ b/src/del.c @@ -13,7 +13,7 @@ #include "apk_applet.h" #include "apk_database.h" -static int del_main(int argc, char **argv) +static int del_main(void *ctx, int argc, char **argv) { struct apk_database db; int i, j; diff --git a/src/index.c b/src/index.c index 91d1ce6ae9..81adc514bf 100644 --- a/src/index.c +++ b/src/index.c @@ -39,7 +39,7 @@ static int warn_if_no_providers(apk_hash_item item, void *ctx) return 0; } -static int index_main(int argc, char **argv) +static int index_main(void *ctx, int argc, char **argv) { struct apk_database db; struct counts counts = {0,0}; diff --git a/src/info.c b/src/info.c index 780850d5cd..2e4174279a 100644 --- a/src/info.c +++ b/src/info.c @@ -12,30 +12,91 @@ #include #include "apk_defines.h" #include "apk_applet.h" +#include "apk_package.h" #include "apk_database.h" +#include "apk_state.h" -static int info_main(int argc, char **argv) +struct info_ctx { + int (*action)(struct apk_database *db, int argc, char **argv); +}; + +static int info_list(struct apk_database *db, int argc, char **argv) { - struct apk_database db; struct apk_package *pkg; - if (apk_db_open(&db, apk_root) < 0) - return -1; - - list_for_each_entry(pkg, &db.installed.packages, installed_pkgs_list) { + list_for_each_entry(pkg, &db->installed.packages, installed_pkgs_list) { printf("%s", pkg->name->name); - if (!apk_quiet) - printf(" %s", pkg->version); + if (!apk_quiet) + printf("-%s - %s", pkg->version, pkg->description); printf("\n"); } + return 0; +} + +static int info_exists(struct apk_database *db, int argc, char **argv) +{ + struct apk_name *name; + int i, j; + + for (i = 0; i < argc; i++) { + name = apk_db_query_name(db, APK_BLOB_STR(argv[i])); + if (name == NULL) + return 1; + + for (j = 0; j < name->pkgs->num; j++) { + if (apk_pkg_get_state(name->pkgs->item[j]) == APK_STATE_INSTALL) + break; + } + if (j >= name->pkgs->num) + return 2; + } - apk_db_close(&db); return 0; } +static int info_parse(void *ctx, int optch, int optindex, const char *optarg) +{ + struct info_ctx *ictx = (struct info_ctx *) ctx; + + switch (optch) { + case 'e': + ictx->action = info_exists; + break; + default: + return -1; + } + return 0; +} + +static int info_main(void *ctx, int argc, char **argv) +{ + struct info_ctx *ictx = (struct info_ctx *) ctx; + struct apk_database db; + int r; + + if (apk_db_open(&db, apk_root) < 0) + return -1; + + if (ictx->action != NULL) + r = ictx->action(&db, argc, argv); + else + r = info_list(&db, argc, argv); + + apk_db_close(&db); + return r; +} + +static struct option info_options[] = { + { "installed", no_argument, NULL, 'e' }, +}; + static struct apk_applet apk_info = { .name = "info", .usage = "", + .context_size = sizeof(struct info_ctx), + .num_options = ARRAY_SIZE(info_options), + .options = info_options, + .parse = info_parse, .main = info_main, }; diff --git a/src/ver.c b/src/ver.c index 71e3d013c1..6665e8f994 100644 --- a/src/ver.c +++ b/src/ver.c @@ -29,7 +29,7 @@ static int res2char(int res) } } -static int ver_main(int argc, char **argv) +static int ver_main(void *ctx, int argc, char **argv) { struct apk_database db; struct apk_name *name; -- cgit v1.2.3