#include #include #include #include #include #include #include "mode_to_str.h" #include "make_path.h" #include "get_stat.h" #include "parse_mode.h" #include "recurse.h" char r_flag; char *f_flag = "chmod"; char H_flag; char v_flag; int change(const char *file, void *p) { char *mode_arg = (char *)p; struct stat sb; if (mu_get_stats(f_flag, H_flag, file, &sb)) return 1; mode_t mode = mu_parse_mode(mode_arg, sb.st_mode); if (chmod(file, mode) != 0) { if (f_flag) fprintf(stderr, "chmod: unable to chown %s: %s\n", file, strerror(errno)); return 1; } if (v_flag) printf("chmod: %s: changed mode to %s\n", file, mu_mode_2_str(mode)); return 0; } int main(int argc, char **argv) { /* Arg hacking */ char *arg = NULL; for (int i = 1; i < argc; i++) { if (argv[i][0] != '-' || strlen(argv[i]) <= 1) break; else if (argv[i][1] == 'x' || argv[i][1] == 'r' || argv[i][1] == 'w') { argv[i][0] = 'a'; arg = argv[i]; break; } } int opt; while ((opt = getopt(argc, argv, "RfHv")) != -1) { switch (opt) { case 'R': r_flag = 1; break; case 'f': f_flag = NULL; break; case 'H': H_flag = 1; break; case 'v': v_flag = 1; break; default: puts("chmod [RfHv] [ugoa]{+|-}[rwxXst] / [0 - 777] [file1 file2...]\n\t-H Symbolic link\n\t-R Recursive\n\t-f Silent\n\t-v Verbose"); return 0; } } argv += optind; argc -= optind; if (argc == 0) { fprintf(stderr, "chmod: missing operand\n"); return 0; } /* Restore arg */ if (arg) arg[0] = '-'; int ret = 0; for (int i = 1; i < argc; i++) { if (r_flag) { if (mu_recurse(f_flag, H_flag, argv[i], argv[0], change, change)) ret = 1; } else change(argv[i], argv[0]); } return ret; }