2008-04-17 14:09:13 +00:00
|
|
|
/* apk.c - Alpine Package Keeper (APK)
|
|
|
|
*
|
|
|
|
* Copyright (C) 2005-2008 Natanael Copa <n@tanael.org>
|
|
|
|
* Copyright (C) 2008 Timo Teräs <timo.teras@iki.fi>
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
|
|
* under the terms of the GNU General Public License version 2 as published
|
|
|
|
* by the Free Software Foundation. See http://www.gnu.org/ for details.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
2008-04-22 08:16:26 +00:00
|
|
|
#include <fcntl.h>
|
2009-01-13 12:09:45 +00:00
|
|
|
#include <ctype.h>
|
2008-04-17 14:09:13 +00:00
|
|
|
#include <stdarg.h>
|
2008-04-21 16:30:10 +00:00
|
|
|
#include <stdlib.h>
|
2008-04-17 14:09:13 +00:00
|
|
|
#include <string.h>
|
2008-04-21 16:30:10 +00:00
|
|
|
#include <getopt.h>
|
|
|
|
#include <sys/stat.h>
|
2008-04-17 14:09:13 +00:00
|
|
|
|
|
|
|
#include "apk_defines.h"
|
|
|
|
#include "apk_applet.h"
|
|
|
|
|
2009-01-12 21:03:20 +00:00
|
|
|
const char *apk_root;
|
2008-04-21 16:30:10 +00:00
|
|
|
const char *apk_repository = NULL;
|
2009-01-16 09:33:55 +00:00
|
|
|
int apk_verbosity = 1, apk_progress = 0;
|
2008-04-22 08:16:26 +00:00
|
|
|
int apk_cwd_fd;
|
2008-04-21 16:30:10 +00:00
|
|
|
|
2008-04-17 14:09:13 +00:00
|
|
|
void apk_log(const char *prefix, const char *format, ...)
|
|
|
|
{
|
|
|
|
va_list va;
|
|
|
|
|
|
|
|
if (prefix != NULL)
|
2009-01-06 17:44:33 +00:00
|
|
|
fprintf(stderr, "%s", prefix);
|
2008-04-17 14:09:13 +00:00
|
|
|
va_start(va, format);
|
|
|
|
vfprintf(stderr, format, va);
|
|
|
|
va_end(va);
|
|
|
|
fprintf(stderr, "\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
int usage(void)
|
|
|
|
{
|
|
|
|
struct apk_applet **a, *applet;
|
|
|
|
|
|
|
|
printf("apk-tools " APK_VERSION "\n"
|
|
|
|
"\n"
|
|
|
|
"Usage:\n");
|
|
|
|
|
|
|
|
for (a = &__start_apkapplets; a < &__stop_apkapplets; a++) {
|
|
|
|
applet = *a;
|
|
|
|
printf(" apk %s %s\n",
|
|
|
|
applet->name, applet->usage);
|
|
|
|
}
|
|
|
|
printf("\n");
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2008-04-21 16:30:10 +00:00
|
|
|
static struct apk_applet *find_applet(const char *name)
|
|
|
|
{
|
|
|
|
struct apk_applet **a;
|
|
|
|
|
|
|
|
for (a = &__start_apkapplets; a < &__stop_apkapplets; a++) {
|
|
|
|
if (strcmp(name, (*a)->name) == 0)
|
|
|
|
return *a;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2009-01-13 12:09:45 +00:00
|
|
|
static struct apk_applet *deduce_applet(int argc, char **argv)
|
2008-04-17 14:09:13 +00:00
|
|
|
{
|
2009-01-13 12:09:45 +00:00
|
|
|
struct apk_applet *a;
|
2008-04-21 16:30:10 +00:00
|
|
|
const char *prog;
|
2009-01-13 12:09:45 +00:00
|
|
|
int i;
|
2008-04-17 14:09:13 +00:00
|
|
|
|
|
|
|
prog = strrchr(argv[0], '/');
|
|
|
|
if (prog == NULL)
|
|
|
|
prog = argv[0];
|
|
|
|
else
|
|
|
|
prog++;
|
|
|
|
|
2008-04-21 16:30:10 +00:00
|
|
|
if (strncmp(prog, "apk_", 4) == 0)
|
2009-01-13 12:09:45 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2009-01-16 09:33:55 +00:00
|
|
|
#define NUM_GENERIC_OPTS 5
|
2009-01-13 12:09:45 +00:00
|
|
|
static struct option generic_options[32] = {
|
|
|
|
{ "root", required_argument, NULL, 'Q' },
|
|
|
|
{ "repository", required_argument, NULL, 'X' },
|
|
|
|
{ "quiet", no_argument, NULL, 'q' },
|
2009-01-16 09:33:55 +00:00
|
|
|
{ "verbose", no_argument, NULL, 'v' },
|
2009-01-13 12:09:45 +00:00
|
|
|
{ "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;
|
2008-04-17 14:09:13 +00:00
|
|
|
|
2009-01-13 12:09:45 +00:00
|
|
|
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++) {
|
2009-01-15 09:10:14 +00:00
|
|
|
if (opt->flag == NULL &&
|
|
|
|
opt->val <= 0xff && isalnum(opt->val)) {
|
2009-01-13 12:09:45 +00:00
|
|
|
*(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) {
|
2008-04-21 16:30:10 +00:00
|
|
|
switch (r) {
|
|
|
|
case 'Q':
|
|
|
|
apk_root = optarg;
|
|
|
|
break;
|
|
|
|
case 'X':
|
|
|
|
apk_repository = optarg;
|
|
|
|
break;
|
2008-04-22 06:04:20 +00:00
|
|
|
case 'q':
|
2009-01-16 09:33:55 +00:00
|
|
|
apk_verbosity--;
|
|
|
|
break;
|
|
|
|
case 'v':
|
|
|
|
apk_verbosity++;
|
2008-04-22 06:04:20 +00:00
|
|
|
break;
|
2009-01-07 19:45:11 +00:00
|
|
|
case 0x100:
|
|
|
|
apk_progress = 1;
|
|
|
|
break;
|
2008-04-21 16:30:10 +00:00
|
|
|
default:
|
2009-01-13 12:09:45 +00:00
|
|
|
if (applet->parse == NULL)
|
|
|
|
return usage();
|
|
|
|
if (applet->parse(ctx, r, optindex - NUM_GENERIC_OPTS,
|
|
|
|
optarg) != 0)
|
|
|
|
return usage();
|
|
|
|
break;
|
2008-04-17 14:09:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-01-12 21:03:20 +00:00
|
|
|
if (apk_root == NULL)
|
|
|
|
apk_root = "/";
|
|
|
|
|
2009-01-13 12:09:45 +00:00
|
|
|
argc -= optind;
|
|
|
|
argv += optind;
|
|
|
|
if (argc >= 1 && strcmp(argv[0], applet->name) == 0) {
|
2008-04-21 16:30:10 +00:00
|
|
|
argc--;
|
|
|
|
argv++;
|
|
|
|
}
|
|
|
|
|
2009-01-13 12:09:45 +00:00
|
|
|
return applet->main(ctx, argc, argv);
|
2008-04-17 14:09:13 +00:00
|
|
|
}
|