/* $NetBSD$ */ #include #include #include #include #include #include #include #include #include #include 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); *val = v; return (0); } static prop_object_t prop_object_internalize_from_file(const char *path) { prop_object_t po; /* 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); } return (po); } #define OPTIONS "b:ehlo:sI:O:" static void usage(void) { const char *me = getprogname(); 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); } prop_object_release(po); prop_object_release(pq); } } else { prop_object_t po; char *s; 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"); free(s); prop_object_release(object); } if (len == 0) break; } prop_parser_destroy(codeci, parser); return (0); }