#include "../command.h" #include #include static struct { bool force; bool prompt; bool verbose; bool recurse; } flags; static void help(void) { printf("Usage: rm [-irfv] FILE...\n\n"); printf("Remove (unlink) FILESs\n\n"); printf("\t-i\tAlways prompt before removing\n"); printf("\t-f\tForce, never prompt\n"); printf("\t-v\tVerbose\n"); printf("\t-R,-r\tRecurse\n"); } static int short_arg(char c, char* next) { UNUSED(next); switch (c) { case 'i': flags.prompt = true; break; case 'f': flags.force = true; break; case 'v': flags.verbose = true; break; case 'R': case 'r': flags.recurse = true; break; default: return ARG_INVALID; } return ARG_UNUSED; } static void rm_file(char* path); static bool rm_dir() { DIR* d = opendir(get_path_buffer()); if (d == NULL) { error_s("failed to stat '%s': %s\n", get_path_buffer(), strerror(errno)); return false; } struct dirent* file; while ((file = readdir(d)) != NULL) { if (is_dot_dir(file->d_name)) continue; rm_file(file->d_name); } closedir(d); return true; } static void rm_file(char* path) { int save = push_path_buffer(path); struct stat s; if (lstat(get_path_buffer(), &s) < 0) { pop_path_buffer(save); error_s("failed to stat '%s': %s\n", get_path_buffer(), strerror(errno)); return; } if (S_ISDIR(s.st_mode)) { if (!flags.force) { error_s("cannot delete '%s': Is a directory\n", get_path_buffer()); pop_path_buffer(save); return; } if (flags.recurse && !rm_dir()) { pop_path_buffer(save); return; } } if (flags.prompt) { fprintf(stderr, "delete '%s'? ", get_path_buffer()); fflush(stderr); char c = getchar(); if (c != 'y' && c != 'Y') { fprintf(stderr, "Skipping...\n"); pop_path_buffer(save); return; } } if (remove(get_path_buffer()) < 0) { error_s("failed to delete '%s': %s\n", get_path_buffer(), strerror(errno)); } else if (flags.verbose) { output("deleted '%s'\n", get_path_buffer()); } pop_path_buffer(save); } COMMAND(rm) { if (argc < 1) { global_help(help); return EXIT_SUCCESS; } flags.prompt = false; flags.force = false; flags.verbose = false; flags.recurse = false; int start = parse_args(argc, argv, help, short_arg, NULL); #ifdef FRENCH if (streql(argv[0], "-fr")) { printf("\x1b[94mremoving \x1b[97mthe \x1b[91mfrench \x1b[93m(baguette noises)\x1b[0m\n"); } #endif for (int i = start; i < argc; i++) { rm_file(argv[i]); } return EXIT_SUCCESS; }