+}
+
+static void usage(int status)
+{
+ fprintf(
+ status ? stderr : stdout,
+ "Usage: ddnuke [options] <dev>\n"
+ "\n"
+ "Options:\n"
+ " -q Run quietly\n"
+ " -y Assume yes to all prompts\n"
+ " -o <offset> Position to start writing\n"
+ " -r Write three times: 0x00, then 0xaa, then 0x55\n"
+ );
+ exit(status);
+}
+
+int main(int argc, char *argv[])
+{
+ off_t offset = 0;
+ const char *file;
+ bool quiet = false;
+ bool random = false;
+ bool yes = false;
+ int o;
+
+ setlocale(LC_NUMERIC, "en_US");
+
+ while ((o = getopt(argc, argv, "ho:qry")) != -1) {
+ switch (o) {
+ case 'o':
+ offset = atoll(optarg);
+ break;
+ case 'q':
+ quiet = true;
+ break;
+ case 'r':
+ random = true;
+ break;
+ case 'y':
+ yes = true;
+ break;
+ case 'h':
+ usage(EX_OK);
+ break;
+ default:
+ usage(EX_USAGE);
+ break;
+ }
+ }
+ if (argc != optind + 1)
+ usage(EX_USAGE);
+ file = argv[optind];
+
+ int fd = open(file, O_WRONLY|O_CLOEXEC);
+ if (fd == -1)
+ err(EX_NOINPUT, "open(%s) failed", file);
+
+ if (!quiet) {
+ pid_t pid;
+ const char *argv[] = {"fdisk", "-l", file, NULL};
+ if (posix_spawnp(&pid, argv[0], NULL, NULL, (char *const *)argv, NULL))
+ err(EX_OSERR, "spawn(%s %s) failed", argv[0], file);
+ waitpid(pid, NULL, 0);
+ printf("\n");
+ }
+
+ if (!yes) {
+ printf("Do you want to wipe '%s'? (y/N) ", file);
+ fflush(stdout);
+ char c = 0;
+ if (fread(&c, 1, 1, stdin)) {/* don't care */}
+ if (tolower(c) != 'y')
+ errx(EX_UNAVAILABLE, "User decided not to wipe");
+ }
+
+ off_t max_size = get_size(fd);
+
+ nuke(fd, offset, max_size, 0x00);
+ if (random) {
+ nuke(fd, offset, max_size, 0xaa);
+ nuke(fd, offset, max_size, 0x55);
+ }
+
+ return EX_OK;