apk: per applet options

cute-signatures
Timo Teras 2009-01-13 14:09:45 +02:00
parent 0a7910c144
commit 3755e1cde3
10 changed files with 163 additions and 46 deletions

View File

@ -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;

100
src/apk.c
View File

@ -11,6 +11,7 @@
#include <stdio.h>
#include <fcntl.h>
#include <ctype.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
@ -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);
while ((r = getopt_long(argc, argv, "",
generic_options, NULL)) != -1) {
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;
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);
}

View File

@ -12,13 +12,21 @@
#ifndef APK_APPLET_H
#define APK_APPLET_H
#include <getopt.h>
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;

View File

@ -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);

View File

@ -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.");

View File

@ -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;

View File

@ -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;

View File

@ -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};

View File

@ -12,30 +12,91 @@
#include <stdio.h>
#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;
list_for_each_entry(pkg, &db->installed.packages, installed_pkgs_list) {
printf("%s", pkg->name->name);
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;
}
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;
list_for_each_entry(pkg, &db.installed.packages, installed_pkgs_list) {
printf("%s", pkg->name->name);
if (!apk_quiet)
printf(" %s", pkg->version);
printf("\n");
}
if (ictx->action != NULL)
r = ictx->action(&db, argc, argv);
else
r = info_list(&db, argc, argv);
apk_db_close(&db);
return 0;
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,
};

View File

@ -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;