b29e60c274558ebba2483a94ff40ad812963cd7c — Ben Brown 1 year, 2 days ago 448ee4f
Added -S flag to umask
1 files changed, 53 insertions(+), 6 deletions(-)

M builtin/umask.c
M builtin/umask.c => builtin/umask.c +53 -6
@@ 1,4 1,5 @@
 #define _POSIX_C_SOURCE 200809L
+#include <getopt.h>
 #include <mrsh/builtin.h>
 #include <stdio.h>
 #include <stdlib.h>


@@ 7,26 8,72 @@
 #include "builtin.h"
 
 /*
- * TODO: Implement -S flag and symbolic mode
+ * TODO: Implement symbolic mode
  */
 
-static const char umask_usage[] = "usage: umask [mode]\n";
+static const char umask_usage[] = "usage: umask [-S] [mode]\n";
+
+static void umask_modestring(char string[static 4], mode_t mode) {
+	size_t i = 0;
+
+	if (S_IROTH & mode) {
+		string[i++] = 'r';
+	}
+	if (S_IWOTH & mode) {
+		string[i++] = 'w';
+	}
+	if (S_IXOTH & mode) {
+		string[i++] = 'x';
+	}
+}
+
+static void umask_print_symbolic(mode_t mask) {
+	char user[4] = {0};
+	char group[4] = {0};
+	char other[4] = {0};
+	mode_t mode = 0777 & ~mask;
+
+	umask_modestring(user, (mode & 0700) >> 6);
+	umask_modestring(group, (mode & 0070) >> 3);
+	umask_modestring(other, (mode & 0007));
+
+	printf("u=%s,g=%s,o=%s\n", user, group, other);
+}
 
 int builtin_umask(struct mrsh_state *state, int argc, char *argv[]) {
 	mode_t mode;
 	mode_t default_mode = 0022;
+	bool umask_symbolic = false;
+
+	optind = 0;
+	int opt;
+	while ((opt = getopt(argc, argv, ":S")) != -1) {
+		switch(opt) {
+		case 'S':
+			umask_symbolic = true;
+			break;
+		default:
+			fprintf(stderr, "Unknown option -- '%c'\n", optopt);
+			fprintf(stderr, umask_usage);
+			return EXIT_FAILURE;
+		}
+	}
 
-	if (argc < 2) {
+	if (optind == argc) {
 		mode = umask(default_mode);
-		printf("%04o\n", mode);
 		umask(mode);
+		if (umask_symbolic) {
+			umask_print_symbolic(mode);
+		} else {
+			printf("%04o\n", mode);
+		}
 		return EXIT_SUCCESS;
 	}
 
 	char *endptr;
-	mode = strtol(argv[1], &endptr, 8);
+	mode = strtol(argv[optind], &endptr, 8);
 	if (*endptr != '\0') {
-		fprintf(stderr, "Invalid mode %s\n", argv[1]);
+		fprintf(stderr, "Invalid mode %s\n", argv[optind]);
 		fprintf(stderr, umask_usage);
 		return EXIT_FAILURE;
 	}