static int
xstrtoul(char *str, u_long *val)
{
char *end;
int base = 10;
u_long v;
if (str[0] == '0')
switch (str[1]) {
case 'x':
base = 16;
str += 2;
break;
case 'd':
base = 10;
str += 2;
break;
case 'o':
base = 8;
str += 2;
break;
case 'b':
base = 2;
str += 2;
break;
}
v = strtoul(str, &end, base);
if (*end != '\0' || str[0] == '\0')
return (EINVAL);
/* XXX this dance is ugly, but we can't do better ATM */
po = prop_dictionary_internalize_from_file(path);
if (po == NULL) {
po = prop_array_internalize_from_file(path);
if (po == NULL)
errx(1, "could not internalize '%s'", path);
}
printf("Usage: %s [options] file...\n", me);
printf(" %s -e file0 file1...\n", me);
printf(" %s -l\n", me);
printf("-b size \t Buffer size for -I\n");
printf("-e \t Pairwise compare plists\n");
printf("-h \t Print (this) help\n");
printf("-l \t Print available codecs\n");
printf("-o file \t Output file [stdout]\n");
printf("-s \t Silent operation\n");
printf("-O format \t Output format\n");
printf("-I format \t Input format when reading from stdin\n");
exit(0);
}
int
main(int argc, char *argv[])
{
u_char *buf;
prop_parser_t parser;
prop_codec_t codeco = NULL;
prop_codec_t codeci = NULL;
prop_object_t object;
char *s;
ssize_t len;
int c, i, ret;
int fdo = STDOUT_FILENO;
int cmp = 0;
u_long buflen = 8192;
int silent = 0;
codeci = codeco = prop_codec_lookup(NULL);
if (codeco == NULL)
errx(1, "could not find default codec");
while ((c = getopt(argc, argv, OPTIONS)) != -1)
switch (c) {
case 'b': /* Buffer size for -I. */
if (xstrtoul(optarg, &buflen))
errx(1, "not a number '%s'", optarg);
if (buflen == 0)
errx(1, "buffer size must be nonzero");
break;
case 'e': /* Compare plists. */
cmp = 1;
break;
case 'h': /* Help. */
usage();
/* UNREACHED */
case 'l': /* List available codecs */
printf("%s\n", prop_codec_list());
return (0);
case 'o': /* Output file. */
fdo = open(optarg, O_WRONLY|O_CREAT|O_TRUNC, 0644);
if (fdo == -1)
errx(1, "could not open output '%s'", optarg);
break;
case 's': /* Silent operation. */
silent = 1;
break;
case 'I': /* Input format. */
codeci = prop_codec_lookup(optarg);
if (codeci == NULL)
errx(1, "could not find codec '%s'", optarg);
break;
case 'O': /* Output format. */
codeco = prop_codec_lookup(optarg);
if (codeco == NULL)
errx(1, "could not find codec '%s'", optarg);
break;
case '?':
errx(1, "uknown option -%c", optopt);
/* UNREACHED */
case ':':
errx(1, "missing argument to -%c", optopt);
/* UNREACHED */
}
argc -= optind;
argv += optind;
if (cmp) {
prop_object_t po, pq;
if (argc == 0 || (argc % 2) != 0)
errx(1, "can only compare even number of plists");
for (i = 0; i < argc; i += 2) {
char *one = argv[i];
char *two = argv[i + 1];
po = prop_object_internalize_from_file(one);
pq = prop_object_internalize_from_file(two);
if (prop_object_equals(po, pq)) {
if (! silent)
printf("%s == %s\n", one, two);
} else {
if (! silent)
printf("%s != %s\n", one, two);
return (1);
}
for (i = 0; i < argc; i++) {
po = prop_object_internalize_from_file(argv[i]);
s = prop_codec_externalize(codeco, po);
if (s == NULL)
errx(1, "could not externalize '%s'", argv[i]);
if (write(fdo, s, strlen(s)) == -1)
err(1, "could not write output");
free(s);
prop_object_release(po);
}
}
/* If we were called to recode or compare files our job is done. */
if (argc != 0)
return (0);
buf = malloc(buflen);
if (buf == NULL)
errx(1, "could not allocate input buffer");
/* Otherwise we're supposed to read stdin. */
ret = prop_parser_create(codeci, &parser);
if (ret)
errx(1, "could not create parser: %s", strerror(ret));
while ((len = read(STDIN_FILENO, buf, buflen)) >= 0) {
ret = prop_parser_exec(codeci, parser, buf, len);
if (ret)
errx(1, "%s", strerror(ret));
while ((object = prop_parser_yield(codeci, parser)) != NULL) {
s = prop_codec_externalize(codeco, object);
if (s == NULL)
errx(1, "could not externalize with codec");
if (write(fdo, s, strlen(s)) == -1)
err(1, "could not write output");