~emersion/mrsh

b29e60c274558ebba2483a94ff40ad812963cd7c — Ben Brown 1 year, 1 month 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;
	}