src/main.c
changeset 445 aada48958b92
parent 442 c4bcba8023a9
child 447 0a5e583393e1
     1.1 --- a/src/main.c	Sat Aug 23 16:28:31 2014 +0100
     1.2 +++ b/src/main.c	Mon Sep 08 10:26:39 2014 +0100
     1.3 @@ -1,7 +1,7 @@
     1.4  /*
     1.5   * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
     1.6   * Copyright (C) 2008  Red Hat, Inc
     1.7 - * Copyright (C) 2009, 2011-2012  J. Ali Harlow <ali@juiblex.co.uk>
     1.8 + * Copyright (C) 2009, 2011-2012, 2014  J. Ali Harlow <ali@juiblex.co.uk>
     1.9   *
    1.10   * This program is free software; you can redistribute it and/or modify
    1.11   * it under the terms of the GNU General Public License as published by
    1.12 @@ -37,6 +37,7 @@
    1.13  #endif
    1.14  #include <fnmatch.h>
    1.15  #include <errno.h>
    1.16 +#include <getopt.h>
    1.17  #include "razor.h"
    1.18  
    1.19  static const char system_repo_filename[] = "system.rzdb";
    1.20 @@ -46,6 +47,14 @@
    1.21  static const char *repo_filename = system_repo_filename;
    1.22  static const char *yum_url;
    1.23  
    1.24 +#ifndef FALSE
    1.25 +#define FALSE 0
    1.26 +#endif
    1.27 +
    1.28 +#ifndef TRUE
    1.29 +#define TRUE (!FALSE)
    1.30 +#endif
    1.31 +
    1.32  #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
    1.33  
    1.34  static int
    1.35 @@ -59,8 +68,110 @@
    1.36  	      struct razor_transaction *trans, struct razor_set *next,
    1.37  	      const char *verb);
    1.38  
    1.39 +static int command_help(int argc, char * const argv[]);
    1.40 +
    1.41 +struct razor_option {
    1.42 +	char *name;
    1.43 +	int has_arg;
    1.44 +	int val;
    1.45 +	char *description;
    1.46 +	char *arg_description;
    1.47 +};
    1.48 +
    1.49 +static void
    1.50 +razor_usage(const char *command, int n_options, struct razor_option *options,
    1.51 +	    const char *parameter_string)
    1.52 +{
    1.53 +	int i, help_printed = FALSE;
    1.54 +	char buf[19];
    1.55 +
    1.56 +	printf("Usage: razor %s [options] %s\n", command, parameter_string);
    1.57 +	printf("(Specify the --help global option for a list of other "
    1.58 +	       "help options)\n");
    1.59 +	printf("\nOptions:\n");
    1.60 +
    1.61 +	for(i = 0; i < n_options; i++) {
    1.62 +		if (!help_printed && strcmp(options[i].name, "help") > 0) {
    1.63 +			printf("  --help              "
    1.64 +			       "Show this help message and exit\n");
    1.65 +			help_printed = TRUE;
    1.66 +		}
    1.67 +
    1.68 +		if (options[i].has_arg != no_argument)
    1.69 +			snprintf(buf, sizeof(buf), "%s=%s", options[i].name,
    1.70 +				 options[i].arg_description);
    1.71 +		else
    1.72 +			strncpy(buf, options[i].name, sizeof(buf));
    1.73 +		buf[18] = '\0';
    1.74 +
    1.75 +		printf("  --%-18s%s\n", buf, options[i].description);
    1.76 +	}
    1.77 +
    1.78 +	if (!help_printed)
    1.79 +		printf("  --help              "
    1.80 +		       "Show this help message and exit\n");
    1.81 +}
    1.82 +
    1.83 +/**
    1.84 + * razor_getopt:
    1.85 + *
    1.86 + *
    1.87 + * Returns: The next option found or -2 on handled or -1 on error
    1.88 + *          or 0 on end of option list.
    1.89 + **/
    1.90 +static int
    1.91 +razor_getopt(int argc, char * const argv[], int n_options,
    1.92 +	     struct razor_option *options, const char *parameter_string,
    1.93 +	     const char **arg)
    1.94 +{
    1.95 +	int i, opt, do_help = 0, retval;
    1.96 +	struct option *longopts;
    1.97 +
    1.98 +	longopts = calloc((n_options + 2), sizeof(*longopts));
    1.99 +
   1.100 +	for(i = 0; i < n_options; i++) {
   1.101 +		longopts[i].name = options[i].name;
   1.102 +		longopts[i].has_arg = options[i].has_arg;
   1.103 +		longopts[i].flag = &retval;
   1.104 +		longopts[i].val = options[i].val;
   1.105 +	}
   1.106 +
   1.107 +	longopts[i].name = "help";
   1.108 +	longopts[i].has_arg = no_argument;
   1.109 +	longopts[i].flag = &do_help;
   1.110 +	longopts[i].val = TRUE;
   1.111 +
   1.112 +	opterr = 0;
   1.113 +
   1.114 +	opt = getopt_long(argc, argv, "+", longopts, NULL);
   1.115 +
   1.116 +	switch (opt)
   1.117 +	{
   1.118 +		case 0:
   1.119 +			if (do_help) {
   1.120 +				razor_usage(argv[0], n_options, options,
   1.121 +					    parameter_string);
   1.122 +				retval = -2;
   1.123 +			} else if (arg)
   1.124 +				*arg = optarg;
   1.125 +			break;
   1.126 +
   1.127 +		case -1:
   1.128 +			retval = 0;
   1.129 +			break;
   1.130 +
   1.131 +		default:
   1.132 +			razor_usage(argv[0], n_options, options,
   1.133 +				    parameter_string);
   1.134 +			retval = -1;
   1.135 +	}
   1.136 +
   1.137 +	free(longopts);
   1.138 +	return retval;
   1.139 +}
   1.140 +
   1.141  static struct razor_package_iterator *
   1.142 -create_iterator_from_argv(struct razor_set *set, int argc, const char *argv[])
   1.143 +create_iterator_from_argv(struct razor_set *set, int argc, char * const argv[])
   1.144  {
   1.145  	struct razor_package_query *query;
   1.146  	struct razor_package_iterator *iter;
   1.147 @@ -117,18 +228,35 @@
   1.148  }
   1.149  
   1.150  static int
   1.151 -command_list(int argc, const char *argv[])
   1.152 +command_list(int argc, char * const argv[])
   1.153  {
   1.154 +	int opt;
   1.155  	struct razor_package_iterator *pi;
   1.156  	struct razor_error *error = NULL;
   1.157  	struct razor_set *set;
   1.158  	uint32_t flags = 0;
   1.159 -	int i = 0;
   1.160 +	enum {
   1.161 +		opt_only_names = 1,
   1.162 +	};
   1.163 +	static struct razor_option options[] = {
   1.164 +		{ .name = "only-names", .has_arg = no_argument,
   1.165 +		  .val = opt_only_names,
   1.166 +		  .description = "Only list package names" },
   1.167 +	};
   1.168  
   1.169 -	if (i < argc && strcmp(argv[i], "--only-names") == 0) {
   1.170 -		flags |= LIST_PACKAGES_ONLY_NAMES;
   1.171 -		i++;
   1.172 -	}
   1.173 +	do {
   1.174 +		opt = razor_getopt(argc, argv, ARRAY_SIZE(options), options,
   1.175 +				   "pattern ...", NULL);
   1.176 +		switch (opt) {
   1.177 +			case -2:
   1.178 +				return 0;
   1.179 +			case -1:
   1.180 +				return 1;
   1.181 +			case opt_only_names:
   1.182 +				flags |= LIST_PACKAGES_ONLY_NAMES;
   1.183 +				break;
   1.184 +		}
   1.185 +	} while (opt);
   1.186  
   1.187  	set = razor_root_open_read_only(install_root, &error);
   1.188  	if (set == NULL) {
   1.189 @@ -137,7 +265,7 @@
   1.190  		return 1;
   1.191  	}
   1.192  
   1.193 -	pi = create_iterator_from_argv(set, argc - i, argv + i);
   1.194 +	pi = create_iterator_from_argv(set, argc - optind, argv + optind);
   1.195  	list_packages(pi, flags);
   1.196  	razor_package_iterator_destroy(pi);
   1.197  	razor_set_unref(set);
   1.198 @@ -183,7 +311,7 @@
   1.199  }
   1.200  
   1.201  static int
   1.202 -list_properties(int argc, const char *argv[], uint32_t type)
   1.203 +list_properties(int argc, char * const argv[], uint32_t type)
   1.204  {
   1.205  	struct razor_set *set;
   1.206  	struct razor_error *error = NULL;
   1.207 @@ -191,6 +319,13 @@
   1.208  	struct razor_package_iterator *pi;
   1.209  	const char *name, *version, *arch;
   1.210  
   1.211 +	switch (razor_getopt(argc, argv, 0, NULL, "pattern ...", NULL)) {
   1.212 +		case -2:
   1.213 +			return 0;
   1.214 +		case -1:
   1.215 +			return 1;
   1.216 +	}
   1.217 +
   1.218  	set = razor_root_open_read_only(install_root, &error);
   1.219  	if (set == NULL) {
   1.220  		fprintf(stderr, "%s\n", razor_error_get_msg(error));
   1.221 @@ -198,7 +333,7 @@
   1.222  		return 1;
   1.223  	}
   1.224  
   1.225 -	pi = create_iterator_from_argv(set, argc, argv);
   1.226 +	pi = create_iterator_from_argv(set, argc - optind, argv + optind);
   1.227  	while (razor_package_iterator_next(pi, &package,
   1.228  					   RAZOR_DETAIL_NAME, &name,
   1.229  					   RAZOR_DETAIL_VERSION, &version,
   1.230 @@ -212,31 +347,31 @@
   1.231  }
   1.232  
   1.233  static int
   1.234 -command_list_requires(int argc, const char *argv[])
   1.235 +command_list_requires(int argc, char * const argv[])
   1.236  {
   1.237  	return list_properties(argc, argv, RAZOR_PROPERTY_REQUIRES);
   1.238  }
   1.239  
   1.240  static int
   1.241 -command_list_provides(int argc, const char *argv[])
   1.242 +command_list_provides(int argc, char * const argv[])
   1.243  {
   1.244  	return list_properties(argc, argv, RAZOR_PROPERTY_PROVIDES);
   1.245  }
   1.246  
   1.247  static int
   1.248 -command_list_obsoletes(int argc, const char *argv[])
   1.249 +command_list_obsoletes(int argc, char * const argv[])
   1.250  {
   1.251  	return list_properties(argc, argv, RAZOR_PROPERTY_OBSOLETES);
   1.252  }
   1.253  
   1.254  static int
   1.255 -command_list_conflicts(int argc, const char *argv[])
   1.256 +command_list_conflicts(int argc, char * const argv[])
   1.257  {
   1.258  	return list_properties(argc, argv, RAZOR_PROPERTY_CONFLICTS);
   1.259  }
   1.260  
   1.261  static int
   1.262 -command_list_scripts(int argc, const char *argv[])
   1.263 +command_list_scripts(int argc, char * const argv[])
   1.264  {
   1.265  	struct razor_set *set;
   1.266  	struct razor_error *error = NULL;
   1.267 @@ -244,6 +379,13 @@
   1.268  	struct razor_package_iterator *pi;
   1.269  	const char *preunprog, *preun, *postunprog, *postun;
   1.270  
   1.271 +	switch (razor_getopt(argc, argv, 0, NULL, "pattern ...", NULL)) {
   1.272 +		case -2:
   1.273 +			return 0;
   1.274 +		case -1:
   1.275 +			return 1;
   1.276 +	}
   1.277 +
   1.278  	set = razor_root_open_read_only(install_root, &error);
   1.279  	if (set == NULL) {
   1.280  		fprintf(stderr, "%s\n", razor_error_get_msg(error));
   1.281 @@ -251,7 +393,7 @@
   1.282  		return 1;
   1.283  	}
   1.284  
   1.285 -	pi = create_iterator_from_argv(set, argc, argv);
   1.286 +	pi = create_iterator_from_argv(set, argc - optind, argv + optind);
   1.287  	while (razor_package_iterator_next(pi, &package,
   1.288  					   RAZOR_DETAIL_PREUNPROG, &preunprog,
   1.289  					   RAZOR_DETAIL_PREUN, &preun,
   1.290 @@ -278,11 +420,23 @@
   1.291  }
   1.292  
   1.293  static int
   1.294 -command_list_files(int argc, const char *argv[])
   1.295 +command_list_files(int argc, char * const argv[])
   1.296  {
   1.297  	struct razor_error *error = NULL;
   1.298  	struct razor_set *set;
   1.299  
   1.300 +	switch (razor_getopt(argc, argv, 0, NULL, "[pattern]", NULL)) {
   1.301 +		case -2:
   1.302 +			return 0;
   1.303 +		case -1:
   1.304 +			return 1;
   1.305 +	}
   1.306 +
   1.307 +	if (argc - optind > 1) {
   1.308 +		razor_usage(argv[0], 0, NULL, "[pattern]");
   1.309 +		return 1;
   1.310 +	}
   1.311 +
   1.312  	set = razor_root_open_read_only(install_root, &error);
   1.313  	if (set == NULL) {
   1.314  		fprintf(stderr, "%s\n", razor_error_get_msg(error));
   1.315 @@ -290,19 +444,31 @@
   1.316  		return 1;
   1.317  	}
   1.318  
   1.319 -	razor_set_list_files(set, argv[0]);
   1.320 +	razor_set_list_files(set, argv[optind]);
   1.321  	razor_set_unref(set);
   1.322  
   1.323  	return 0;
   1.324  }
   1.325  
   1.326  static int
   1.327 -command_list_file_packages(int argc, const char *argv[])
   1.328 +command_list_file_packages(int argc, char * const argv[])
   1.329  {
   1.330  	struct razor_error *error = NULL;
   1.331  	struct razor_set *set;
   1.332  	struct razor_package_iterator *pi;
   1.333  
   1.334 +	switch (razor_getopt(argc, argv, 0, NULL, "pattern", NULL)) {
   1.335 +		case -2:
   1.336 +			return 0;
   1.337 +		case -1:
   1.338 +			return 1;
   1.339 +	}
   1.340 +
   1.341 +	if (argc - optind != 1) {
   1.342 +		razor_usage(argv[0], 0, NULL, "pattern");
   1.343 +		return 1;
   1.344 +	}
   1.345 +
   1.346  	set = razor_root_open_read_only(install_root, &error);
   1.347  	if (set == NULL) {
   1.348  		fprintf(stderr, "%s\n", razor_error_get_msg(error));
   1.349 @@ -310,7 +476,7 @@
   1.350  		return 1;
   1.351  	}
   1.352  
   1.353 -	pi = razor_package_iterator_create_for_file(set, argv[0]);
   1.354 +	pi = razor_package_iterator_create_for_file(set, argv[optind]);
   1.355  	list_packages(pi, 0);
   1.356  	razor_package_iterator_destroy(pi);
   1.357  
   1.358 @@ -320,7 +486,7 @@
   1.359  }
   1.360  
   1.361  static int
   1.362 -command_list_package_files(int argc, const char *argv[])
   1.363 +command_list_package_files(int argc, char * const argv[])
   1.364  {
   1.365  	struct razor_error *error = NULL;
   1.366  	struct razor_set *set;
   1.367 @@ -328,6 +494,13 @@
   1.368  	struct razor_package *package;
   1.369  	const char *name, *version, *arch;
   1.370  
   1.371 +	switch (razor_getopt(argc, argv, 0, NULL, "pattern ...", NULL)) {
   1.372 +		case -2:
   1.373 +			return 0;
   1.374 +		case -1:
   1.375 +			return 1;
   1.376 +	}
   1.377 +
   1.378  	set = razor_root_open_read_only(install_root, &error);
   1.379  	if (set == NULL) {
   1.380  		fprintf(stderr, "%s\n", razor_error_get_msg(error));
   1.381 @@ -335,7 +508,7 @@
   1.382  		return 1;
   1.383  	}
   1.384  
   1.385 -	pi = create_iterator_from_argv(set, argc, argv);
   1.386 +	pi = create_iterator_from_argv(set, argc - optind, argv + optind);
   1.387  	while (razor_package_iterator_next(pi, &package,
   1.388  					   RAZOR_DETAIL_NAME, &name,
   1.389  					   RAZOR_DETAIL_VERSION, &version,
   1.390 @@ -362,9 +535,6 @@
   1.391  	const char *name, *version;
   1.392  	uint32_t flags;
   1.393  
   1.394 -	if (ref_name == NULL)
   1.395 -		return 0;
   1.396 -
   1.397  	set = razor_root_open_read_only(install_root, &error);
   1.398  	if (set == NULL) {
   1.399  		fprintf(stderr, "%s\n", razor_error_get_msg(error));
   1.400 @@ -398,16 +568,42 @@
   1.401  }
   1.402  
   1.403  static int
   1.404 -command_what_requires(int argc, const char *argv[])
   1.405 +command_what_requires(int argc, char * const argv[])
   1.406  {
   1.407 -	return list_property_packages(argv[0], argv[1],
   1.408 +	switch (razor_getopt(argc, argv, 0, NULL, "name [version-release]",
   1.409 +			     NULL)) {
   1.410 +		case -2:
   1.411 +			return 0;
   1.412 +		case -1:
   1.413 +			return 1;
   1.414 +	}
   1.415 +
   1.416 +	if (argc - optind < 1 || argc - optind > 2) {
   1.417 +		razor_usage(argv[0], 0, NULL, "name [version-release]");
   1.418 +		return 1;
   1.419 +	}
   1.420 +
   1.421 +	return list_property_packages(argv[optind], argv[optind + 1],
   1.422  				      RAZOR_PROPERTY_REQUIRES);
   1.423  }
   1.424  
   1.425  static int
   1.426 -command_what_provides(int argc, const char *argv[])
   1.427 +command_what_provides(int argc, char * const argv[])
   1.428  {
   1.429 -	return list_property_packages(argv[0], argv[1],
   1.430 +	switch (razor_getopt(argc, argv, 0, NULL, "name [version-release]",
   1.431 +			     NULL)) {
   1.432 +		case -2:
   1.433 +			return 0;
   1.434 +		case -1:
   1.435 +			return 1;
   1.436 +	}
   1.437 +
   1.438 +	if (argc - optind < 1 || argc - optind > 2) {
   1.439 +		razor_usage(argv[0], 0, NULL, "name [version-release]");
   1.440 +		return 1;
   1.441 +	}
   1.442 +
   1.443 +	return list_property_packages(argv[optind], argv[optind + 1],
   1.444  				      RAZOR_PROPERTY_PROVIDES);
   1.445  }
   1.446  
   1.447 @@ -489,13 +685,25 @@
   1.448  	"/pub/fedora/linux/development/i386/os"
   1.449  
   1.450  static int
   1.451 -command_import_yum(int argc, const char *argv[])
   1.452 +command_import_yum(int argc, char * const argv[])
   1.453  {
   1.454  	int retval;
   1.455  	struct razor_set *set;
   1.456  	struct razor_atomic *atomic;
   1.457  	char buffer[512];
   1.458  
   1.459 +	switch (razor_getopt(argc, argv, 0, NULL, "", NULL)) {
   1.460 +		case -2:
   1.461 +			return 0;
   1.462 +		case -1:
   1.463 +			return 1;
   1.464 +	}
   1.465 +
   1.466 +	if (argc - optind > 0) {
   1.467 +		razor_usage(argv[0], 0, NULL, "");
   1.468 +		return 1;
   1.469 +	}
   1.470 +
   1.471  	printf("downloading from %s.\n", yum_url);
   1.472  	snprintf(buffer, sizeof buffer,
   1.473  		 "%s/repodata/primary.xml.gz", yum_url);
   1.474 @@ -524,7 +732,7 @@
   1.475  
   1.476  #if HAVE_RPMLIB
   1.477  static int
   1.478 -command_import_rpmdb(int argc, const char *argv[])
   1.479 +command_import_rpmdb(int argc, char * const argv[])
   1.480  {
   1.481  	struct razor_set *set;
   1.482  	struct razor_root *root;
   1.483 @@ -532,6 +740,18 @@
   1.484  	struct razor_atomic *atomic;
   1.485  	int retval;
   1.486  
   1.487 +	switch (razor_getopt(argc, argv, 0, NULL, "", NULL)) {
   1.488 +		case -2:
   1.489 +			return 0;
   1.490 +		case -1:
   1.491 +			return 1;
   1.492 +	}
   1.493 +
   1.494 +	if (argc - optind > 0) {
   1.495 +		razor_usage(argv[0], 0, NULL, "");
   1.496 +		return 1;
   1.497 +	}
   1.498 +
   1.499  	root = razor_root_open(install_root, &error);
   1.500  	if (root == NULL) {
   1.501  		fprintf(stderr, "%s\n", razor_error_get_msg(error));
   1.502 @@ -605,7 +825,7 @@
   1.503  }
   1.504  
   1.505  static int
   1.506 -command_remove(int argc, const char *argv[])
   1.507 +command_remove(int argc, char * const argv[])
   1.508  {
   1.509  	struct razor_set *system, *upstream, *next;
   1.510  	struct razor_transaction *trans;
   1.511 @@ -613,6 +833,13 @@
   1.512  	struct razor_root *root;
   1.513  	int i, retval;
   1.514  
   1.515 +	switch (razor_getopt(argc, argv, 0, NULL, "pattern ...", NULL)) {
   1.516 +		case -2:
   1.517 +			return 0;
   1.518 +		case -1:
   1.519 +			return 1;
   1.520 +	}
   1.521 +
   1.522  	root = razor_root_open(install_root, &error);
   1.523  	if (root == NULL) {
   1.524  		fprintf(stderr, "%s\n", razor_error_get_msg(error));
   1.525 @@ -624,7 +851,7 @@
   1.526  	upstream = razor_set_create_without_root();
   1.527  	trans = razor_transaction_create(system, upstream);
   1.528  	razor_set_unref(upstream);
   1.529 -	for (i = 0; i < argc; i++) {
   1.530 +	for (i = optind; i < argc; i++) {
   1.531  		if (mark_packages_for_removal(trans, system, argv[i]) == 0) {
   1.532  			fprintf(stderr, "no match for %s\n", argv[i]);
   1.533  			razor_transaction_destroy(trans);
   1.534 @@ -667,11 +894,23 @@
   1.535  }
   1.536  
   1.537  static int
   1.538 -command_diff(int argc, const char *argv[])
   1.539 +command_diff(int argc, char * const argv[])
   1.540  {
   1.541  	struct razor_error *error = NULL;
   1.542  	struct razor_set *set, *updated;
   1.543  
   1.544 +	switch (razor_getopt(argc, argv, 0, NULL, "", NULL)) {
   1.545 +		case -2:
   1.546 +			return 0;
   1.547 +		case -1:
   1.548 +			return 1;
   1.549 +	}
   1.550 +
   1.551 +	if (argc - optind > 0) {
   1.552 +		razor_usage(argv[0], 0, NULL, "");
   1.553 +		return 1;
   1.554 +	}
   1.555 +
   1.556  	set = razor_root_open_read_only(install_root, &error);
   1.557  	if (set)
   1.558  		updated = razor_set_open(rawhide_repo_filename, 0, &error);
   1.559 @@ -694,7 +933,7 @@
   1.560  }
   1.561  
   1.562  static int
   1.563 -command_import_rpms(int argc, const char *argv[])
   1.564 +command_import_rpms(int argc, char * const argv[])
   1.565  {
   1.566  	DIR *dir;
   1.567  	struct dirent *de;
   1.568 @@ -705,14 +944,23 @@
   1.569  	struct razor_atomic *atomic;
   1.570  	int len, imported_count = 0;
   1.571  	char filename[256];
   1.572 -	const char *dirname = argv[0];
   1.573 +	const char *dirname;
   1.574  	int retval;
   1.575  
   1.576 -	if (dirname == NULL) {
   1.577 -		fprintf(stderr, "usage: razor import-rpms DIR\n");
   1.578 -		return -1;
   1.579 +	switch (razor_getopt(argc, argv, 0, NULL, "dir", NULL)) {
   1.580 +		case -2:
   1.581 +			return 0;
   1.582 +		case -1:
   1.583 +			return 1;
   1.584  	}
   1.585  
   1.586 +	if (argc - optind != 1) {
   1.587 +		razor_usage(argv[0], 0, NULL, "dir");
   1.588 +		return 1;
   1.589 +	}
   1.590 +
   1.591 +	dirname = argv[optind];
   1.592 +
   1.593  	dir = opendir(dirname);
   1.594  	if (dir == NULL) {
   1.595  		fprintf(stderr, "couldn't read dir %s\n", dirname);
   1.596 @@ -1054,7 +1302,7 @@
   1.597  }
   1.598  
   1.599  static int
   1.600 -command_install_or_update(int argc, const char *argv[], int do_update)
   1.601 +command_install_or_update(int argc, char * const argv[], int do_update)
   1.602  {
   1.603  	struct razor_relocations *relocations = NULL;
   1.604  	struct razor_set *system, *upstream, *next, *set;
   1.605 @@ -1062,36 +1310,53 @@
   1.606  	struct razor_error *error = NULL;
   1.607  	struct razor_atomic *atomic;
   1.608  	struct razor_root *root;
   1.609 -	int i, retval, len, dependencies = 1;
   1.610 +	int opt, i, retval = 0, len, dependencies = 1;
   1.611  	char *oldpath;
   1.612 +	const char *arg;
   1.613 +	enum {
   1.614 +		opt_no_dependencies = 1,
   1.615 +		opt_relocate = 2,
   1.616 +	};
   1.617 +	static struct razor_option options[] = {
   1.618 +		{ .name = "no-dependencies", .has_arg = no_argument,
   1.619 +		  .val = opt_no_dependencies,
   1.620 +		  .description = "Do not verify package dependencies" },
   1.621 +		{ .name = "relocate", .has_arg = required_argument,
   1.622 +		  .val = opt_relocate,
   1.623 +		  .description = "Relocate files from path OLD to NEW",
   1.624 +		  .arg_description = "OLD=NEW" },
   1.625 +	};
   1.626  
   1.627 -	for (i = 0; i < argc; i++) {
   1.628 -		if (strcmp(argv[i], "--no-dependencies") == 0)
   1.629 -			dependencies = 0;
   1.630 -		else if (strcmp(argv[i], "--relocate") == 0) {
   1.631 -			i++;
   1.632 -			if (i >= argc || strchr(argv[i], '=') == NULL) {
   1.633 -				fprintf(stderr,
   1.634 -				    "Usage: razor %s [OPTION...] RPM\n",
   1.635 -				    do_update ? "update" : "install");
   1.636 -				fprintf(stderr, "Options:\n");
   1.637 -				fprintf(stderr, "    [--no-dependencies]\n");
   1.638 -				fprintf(stderr,
   1.639 -				    "    [--relocate OLDPATH=NEWPATH] RPM\n");
   1.640 -				return -1;
   1.641 -			}
   1.642 -			len = strchr(argv[i], '=') - argv[i];
   1.643 -			oldpath = malloc(len + 1);
   1.644 -			strncpy(oldpath, argv[i], len);
   1.645 -			oldpath[len] = '\0';
   1.646 -			if (!relocations)
   1.647 -			       relocations = razor_relocations_create();
   1.648 -			razor_relocations_add(relocations, oldpath,
   1.649 -					      argv[i] + len + 1);
   1.650 -			free(oldpath);
   1.651 -		} else
   1.652 -			break;
   1.653 -	}
   1.654 +	do {
   1.655 +		opt = razor_getopt(argc, argv, ARRAY_SIZE(options), options,
   1.656 +				   "rpm ...", &arg);
   1.657 +		switch (opt) {
   1.658 +			case -2:
   1.659 +				return 0;
   1.660 +			case -1:
   1.661 +				return 1;
   1.662 +			case opt_no_dependencies:
   1.663 +				dependencies = 0;
   1.664 +				break;
   1.665 +			case opt_relocate:
   1.666 +				if (strchr(arg, '=') == NULL) {
   1.667 +					razor_usage(argv[0],
   1.668 +						    ARRAY_SIZE(options),
   1.669 +						    options, "rpm ...");
   1.670 +					return 1;
   1.671 +				}
   1.672 +				len = strchr(arg, '=') - arg;
   1.673 +				oldpath = malloc(len + 1);
   1.674 +				strncpy(oldpath, arg, len);
   1.675 +				oldpath[len] = '\0';
   1.676 +				if (!relocations)
   1.677 +				       relocations = razor_relocations_create();
   1.678 +				razor_relocations_add(relocations, oldpath,
   1.679 +						      arg + len + 1);
   1.680 +				free(oldpath);
   1.681 +				break;
   1.682 +		}
   1.683 +	} while (opt);
   1.684  
   1.685  	upstream = razor_set_open(rawhide_repo_filename, 0, &error);
   1.686  	if (upstream == NULL) {
   1.687 @@ -1132,9 +1397,9 @@
   1.688  	system = razor_root_get_system_set(root);
   1.689  	trans = razor_transaction_create(system, upstream);
   1.690  
   1.691 -	if (i == argc && do_update)
   1.692 +	if (optind == argc && do_update)
   1.693  		razor_transaction_update_all(trans);
   1.694 -	for (; i < argc; i++) {
   1.695 +	for (i = optind; i < argc; i++) {
   1.696  		if (do_update &&
   1.697  		    mark_packages_for_update(trans, system, argv[i]))
   1.698  			continue;
   1.699 @@ -1207,23 +1472,35 @@
   1.700  }
   1.701  
   1.702  static int
   1.703 -command_update(int argc, const char *argv[])
   1.704 +command_update(int argc, char * const argv[])
   1.705  {
   1.706  	return command_install_or_update(argc, argv, 1);
   1.707  }
   1.708  
   1.709  static int
   1.710 -command_install(int argc, const char *argv[])
   1.711 +command_install(int argc, char * const argv[])
   1.712  {
   1.713  	return command_install_or_update(argc, argv, 0);
   1.714  }
   1.715  
   1.716  static int
   1.717 -command_init(int argc, const char *argv[])
   1.718 +command_init(int argc, char * const argv[])
   1.719  {
   1.720  	int retval;
   1.721  	struct razor_error *error = NULL;
   1.722  
   1.723 +	switch (razor_getopt(argc, argv, 0, NULL, "", NULL)) {
   1.724 +		case -2:
   1.725 +			return 0;
   1.726 +		case -1:
   1.727 +			return 1;
   1.728 +	}
   1.729 +
   1.730 +	if (argc - optind > 0) {
   1.731 +		razor_usage(argv[0], 0, NULL, "");
   1.732 +		return 1;
   1.733 +	}
   1.734 +
   1.735  	retval = razor_root_create(install_root, &error);
   1.736  	if (retval) {
   1.737  		fprintf(stderr, "%s\n", razor_error_get_msg(error));
   1.738 @@ -1235,17 +1512,31 @@
   1.739  }
   1.740  
   1.741  static int
   1.742 -command_download(int argc, const char *argv[])
   1.743 +command_download(int argc, char * const argv[])
   1.744  {
   1.745  	struct razor_error *error = NULL;
   1.746  	struct razor_atomic *atomic;
   1.747  	struct razor_set *set;
   1.748  	struct razor_package_iterator *pi;
   1.749  	struct razor_package *package;
   1.750 -	const char *pattern = argv[0], *name, *version, *arch;
   1.751 +	const char *pattern, *name, *version, *arch;
   1.752  	char url[256], file[256];
   1.753  	int matches = 0;
   1.754  
   1.755 +	switch (razor_getopt(argc, argv, 0, NULL, "[pattern]", NULL)) {
   1.756 +		case -2:
   1.757 +			return 0;
   1.758 +		case -1:
   1.759 +			return 1;
   1.760 +	}
   1.761 +
   1.762 +	if (argc - optind > 1) {
   1.763 +		razor_usage(argv[0], 0, NULL, "[pattern]");
   1.764 +		return 1;
   1.765 +	}
   1.766 +
   1.767 +	pattern = argv[optind];
   1.768 +
   1.769  	set = razor_set_open(rawhide_repo_filename, 0, &error);
   1.770  	if (set == NULL) {
   1.771  		fprintf(stderr, "%s\n", razor_error_get_msg(error));
   1.772 @@ -1300,15 +1591,29 @@
   1.773  }
   1.774  
   1.775  static int
   1.776 -command_info(int argc, const char *argv[])
   1.777 +command_info(int argc, char * const argv[])
   1.778  {
   1.779  	struct razor_error *error = NULL;
   1.780  	struct razor_set *set;
   1.781  	struct razor_package_iterator *pi;
   1.782  	struct razor_package *package;
   1.783 -	const char *pattern = argv[0], *name, *version, *arch;
   1.784 +	const char *pattern, *name, *version, *arch;
   1.785  	const char *summary, *description, *url, *license;
   1.786  
   1.787 +	switch (razor_getopt(argc, argv, 0, NULL, "[pattern]", NULL)) {
   1.788 +		case -2:
   1.789 +			return 0;
   1.790 +		case -1:
   1.791 +			return 1;
   1.792 +	}
   1.793 +
   1.794 +	if (argc - optind > 1) {
   1.795 +		razor_usage(argv[0], 0, NULL, "[pattern]");
   1.796 +		return 1;
   1.797 +	}
   1.798 +
   1.799 +	pattern = argv[optind];
   1.800 +
   1.801  	set = razor_root_open_read_only(install_root, &error);
   1.802  	if (set == NULL) {
   1.803  		fprintf(stderr, "%s\n", razor_error_get_msg(error));
   1.804 @@ -1351,7 +1656,7 @@
   1.805  #define SEARCH_MAX 256
   1.806  
   1.807  static int
   1.808 -command_search(int argc, const char *argv[])
   1.809 +command_search(int argc, char * const argv[])
   1.810  {
   1.811  	struct razor_error *error = NULL;
   1.812  	struct razor_set *set;
   1.813 @@ -1361,12 +1666,19 @@
   1.814  	const char *name, *version, *arch;
   1.815  	const char *summary, *description, *url, *license;
   1.816  
   1.817 -	if (!argv[0]) {
   1.818 -		fprintf(stderr, "must specify a search term\n");
   1.819 +	switch (razor_getopt(argc, argv, 0, NULL, "pattern", NULL)) {
   1.820 +		case -2:
   1.821 +			return 0;
   1.822 +		case -1:
   1.823 +			return 1;
   1.824 +	}
   1.825 +
   1.826 +	if (argc != 2) {
   1.827 +		razor_usage(argv[0], 0, NULL, "pattern");
   1.828  		return 1;
   1.829  	}
   1.830  
   1.831 -	snprintf(pattern, sizeof pattern, "*%s*", argv[0]);
   1.832 +	snprintf(pattern, sizeof pattern, "*%s*", argv[1]);
   1.833  
   1.834  	set = razor_set_open(rawhide_repo_filename, 0, &error);
   1.835  	if (set == NULL) {
   1.836 @@ -1400,52 +1712,86 @@
   1.837  static struct {
   1.838  	const char *name;
   1.839  	const char *description;
   1.840 -	int (*func)(int argc, const char *argv[]);
   1.841 +	int (*func)(int argc, char * const argv[]);
   1.842  } razor_commands[] = {
   1.843 -	{ "list", "list all packages", command_list },
   1.844 -	{ "list-requires", "list all requires for the given package", command_list_requires },
   1.845 -	{ "list-provides", "list all provides for the given package", command_list_provides },
   1.846 -	{ "list-obsoletes", "list all obsoletes for the given package", command_list_obsoletes },
   1.847 -	{ "list-conflicts", "list all conflicts for the given package", command_list_conflicts },
   1.848 -	{ "list-scripts", "list all scripts for the given package", command_list_scripts },
   1.849 -	{ "list-files", "list files for package set", command_list_files },
   1.850 -	{ "list-file-packages", "list packages owning file", command_list_file_packages },
   1.851 -	{ "list-package-files", "list files in package", command_list_package_files },
   1.852 -	{ "what-requires", "list the packages that have the given requires", command_what_requires },
   1.853 -	{ "what-provides", "list the packages that have the given provides", command_what_provides },
   1.854 -	{ "import-yum", "import yum metadata files", command_import_yum },
   1.855 +	{ "diff", "Show diff between two package sets", command_diff },
   1.856 +	{ "download", "Download packages", command_download },
   1.857 +	{ "help", "List available commands", command_help },
   1.858  #if HAVE_RPMLIB
   1.859 -	{ "import-rpmdb", "import the system rpm database", command_import_rpmdb },
   1.860 +	{ "import-rpmdb", "Import the system rpm database",
   1.861 +	  command_import_rpmdb },
   1.862  #endif
   1.863 -	{ "import-rpms", "import rpms from the given directory", command_import_rpms },
   1.864 -	{ "update", "update all or specified packages", command_update },
   1.865 -	{ "remove", "remove specified packages", command_remove },
   1.866 -	{ "diff", "show diff between two package sets", command_diff },
   1.867 -	{ "install", "install rpm", command_install },
   1.868 -	{ "init", "init razor root", command_init },
   1.869 -	{ "download", "download packages", command_download },
   1.870 -	{ "info", "display package details", command_info },
   1.871 -	{ "search", "search package details", command_search }
   1.872 +	{ "import-rpms", "Import rpms from the given directory",
   1.873 +	  command_import_rpms },
   1.874 +	{ "import-yum", "Import yum metadata files", command_import_yum },
   1.875 +	{ "info", "Display package details", command_info },
   1.876 +	{ "init", "Init razor root", command_init },
   1.877 +	{ "install", "Install rpm", command_install },
   1.878 +	{ "list", "List all packages", command_list },
   1.879 +	{ "list-conflicts", "List all conflicts for the given package",
   1.880 +	  command_list_conflicts },
   1.881 +	{ "list-file-packages", "List packages owning file",
   1.882 +	  command_list_file_packages },
   1.883 +	{ "list-files", "List files for package set", command_list_files },
   1.884 +	{ "list-obsoletes", "List all obsoletes for the given package",
   1.885 +	  command_list_obsoletes },
   1.886 +	{ "list-package-files", "List files in package",
   1.887 +	  command_list_package_files },
   1.888 +	{ "list-provides", "List all provides for the given package",
   1.889 +	  command_list_provides },
   1.890 +	{ "list-requires", "List all requires for the given package",
   1.891 +	  command_list_requires },
   1.892 +	{ "list-scripts", "List all scripts for the given package",
   1.893 +	  command_list_scripts },
   1.894 +	{ "remove", "Remove specified packages", command_remove },
   1.895 +	{ "search", "Search package details", command_search },
   1.896 +	{ "update", "Update all or specified packages", command_update },
   1.897 +	{ "what-provides", "List the packages that have the given provides",
   1.898 +	  command_what_provides },
   1.899 +	{ "what-requires", "List the packages that have the given requires",
   1.900 +	  command_what_requires },
   1.901  };
   1.902  
   1.903  static int
   1.904 -usage(void)
   1.905 +command_help(int argc, char * const argv[])
   1.906  {
   1.907  	int i;
   1.908  
   1.909 -	printf("usage:\n");
   1.910 +	printf("Available commands:\n");
   1.911  	for (i = 0; i < ARRAY_SIZE(razor_commands); i++)
   1.912  		printf("  %-20s%s\n",
   1.913  		       razor_commands[i].name, razor_commands[i].description);
   1.914 +	printf("\nType \"razor --help\" for help about global options\n"
   1.915 +	       "or \"razor <command> --help\" for help about a particular "
   1.916 +	       "command's options.\n");
   1.917  
   1.918 -	return 1;
   1.919 +	return 0;
   1.920  }
   1.921  
   1.922  int
   1.923 -main(int argc, const char *argv[])
   1.924 +main(int argc, char *argv[])
   1.925  {
   1.926  	char *repo, *root;
   1.927 -	int i;
   1.928 +	int i, opt, main_optind;
   1.929 +	int do_help_commands = 0;
   1.930 +	enum {
   1.931 +		opt_database = 1,
   1.932 +		opt_help,
   1.933 +		opt_help_commands,
   1.934 +		opt_root,
   1.935 +		opt_url,
   1.936 +	};
   1.937 +	struct option options[] = {
   1.938 +		{ .name = "database", .has_arg = required_argument,
   1.939 +		  .val = opt_database },
   1.940 +		{ .name = "help", .has_arg = no_argument, .val = opt_help },
   1.941 +		{ .name = "help-commands", .has_arg = no_argument,
   1.942 +		  .flag = &do_help_commands, .val = TRUE },
   1.943 +		{ .name = "root", .has_arg = required_argument,
   1.944 +		  .val = opt_root },
   1.945 +		{ .name = "url", .has_arg = required_argument, .val = opt_url },
   1.946 +		{ 0, }
   1.947 +	};
   1.948  
   1.949  	repo = getenv("RAZOR_REPO");
   1.950  	if (repo != NULL)
   1.951 @@ -1462,12 +1808,53 @@
   1.952  	if (getenv("RAZOR_NO_ROOT_NAME_CHECKS"))
   1.953  		razor_disable_root_name_checks(1);
   1.954  
   1.955 -	if (argc < 2)
   1.956 -		return usage();
   1.957 +	optind = 1;
   1.958 +	opterr = 0;
   1.959 +
   1.960 +	while ((opt = getopt_long(argc, argv, "+", options, NULL)) != -1) {
   1.961 +		switch (opt) {
   1.962 +			case opt_database:
   1.963 +				razor_set_database_path(optarg);
   1.964 +				break;
   1.965 +			case opt_help:
   1.966 +			default:
   1.967 +				printf("Usage: razor [global-options] command "
   1.968 +				       "[command-options-and-arguments]\n\n");
   1.969 +				printf("Options:\n");
   1.970 +				printf("  --help              "
   1.971 +				       "Show this help message and exit\n");
   1.972 +				printf("  --help-commands     List commands\n");
   1.973 +				printf("  --database=PATH     "
   1.974 +				       "Use alternative database\n");
   1.975 +				printf("  --root=ROOT         "
   1.976 +				       "Use ROOT as top level directory\n");
   1.977 +				printf("  --url=URL           "
   1.978 +				       "Use URL as upstream repository\n");
   1.979 +				return opt != opt_help;
   1.980 +			case opt_root:
   1.981 +				install_root = optarg;
   1.982 +				break;
   1.983 +			case opt_url:
   1.984 +				yum_url = optarg;
   1.985 +				break;
   1.986 +			case 0:
   1.987 +				break;
   1.988 +		}
   1.989 +	}
   1.990 +
   1.991 +	main_optind = optind;
   1.992 +	optind = 1;
   1.993 +
   1.994 +	if (do_help_commands || argc - main_optind < 1) {
   1.995 +		command_help(argc - main_optind, argv + main_optind);
   1.996 +		return 1;
   1.997 +	}
   1.998  
   1.999  	for (i = 0; i < ARRAY_SIZE(razor_commands); i++)
  1.1000 -		if (strcmp(razor_commands[i].name, argv[1]) == 0)
  1.1001 -			return razor_commands[i].func(argc - 2, argv + 2);
  1.1002 +		if (strcmp(razor_commands[i].name, argv[main_optind]) == 0)
  1.1003 +			return razor_commands[i].func(argc - main_optind,
  1.1004 +						      argv + main_optind);
  1.1005  
  1.1006 -	return usage();
  1.1007 +	command_help(argc - main_optind, argv + main_optind);
  1.1008 +	return 1;
  1.1009  }