commit 2dfe5c6b8bb36d7c23f379e353ee458ff0881d39
parent 73c2898e91eb7466402858831ee38c754cb42480
Author: Connor Lane Smith <cls@lubutu.com>
Date: Fri, 27 May 2011 23:48:07 +0100
octal-only chmod
Diffstat:
M | Makefile | | | 6 | +++--- |
A | chmod.1 | | | 24 | ++++++++++++++++++++++++ |
A | chmod.c | | | 61 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | chown.c | | | 1 | - |
4 files changed, 88 insertions(+), 4 deletions(-)
diff --git a/Makefile b/Makefile
@@ -4,9 +4,9 @@ HDR = text.h util.h
LIB = util/afgets.o util/agetcwd.o util/concat.o util/enmasse.o util/eprintf.o \
util/recurse.o
-SRC = basename.c cat.c chown.c date.c dirname.c echo.c false.c grep.c head.c \
- ln.c ls.c mkdir.c mkfifo.c pwd.c rm.c sleep.c tail.c tee.c touch.c \
- true.c wc.c
+SRC = basename.c cat.c chmod.c chown.c date.c dirname.c echo.c false.c grep.c \
+ head.c ln.c ls.c mkdir.c mkfifo.c pwd.c rm.c sleep.c tail.c tee.c \
+ touch.c true.c wc.c
OBJ = $(SRC:.c=.o) $(LIB)
BIN = $(SRC:.c=)
MAN = $(SRC:.c=.1)
diff --git a/chmod.1 b/chmod.1
@@ -0,0 +1,24 @@
+.TH CHMOD 1 sbase\-VERSION
+.SH NAME
+chmod \- change file mode
+.SH SYNOPSIS
+.B chmod
+.RB [ -Rr ]
+.RI mode
+.RI [ file ...]
+.SH DESCRIPTION
+.B chmod
+changes the file mode for the given files. The
+.I mode
+is a four digit octal number derived from its comprising bits.
+.P
+The first digit defines the setuid (4), setgid (2), and sticky (1) attributes.
+The second digit defines the owner's permissions: read (4), write (2), and
+execute (1); the third defines permissions for others in the file's group; and
+the fourth for all other users. Leading zeroes may be omitted.
+.SH OPTIONS
+.TP
+.B -R, -r
+change directory mode recursively.
+.SH SEE ALSO
+.IR chmod (2)
diff --git a/chmod.c b/chmod.c
@@ -0,0 +1,61 @@
+/* See LICENSE file for copyright and license details. */
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include "util.h"
+
+static void chmodr(const char *);
+
+static bool rflag = false;
+static mode_t mode = 0;
+
+int
+main(int argc, char *argv[])
+{
+ char c, *end;
+ int octal;
+
+ while((c = getopt(argc, argv, "Rr")) != -1)
+ switch(c) {
+ case 'R':
+ case 'r':
+ rflag = true;
+ break;
+ default:
+ exit(EXIT_FAILURE);
+ }
+ if(optind == argc)
+ eprintf("usage: %s [-Rr] mode [file...]\n", argv[0]);
+ octal = strtol(argv[optind++], &end, 8);
+ if(*end != '\0')
+ eprintf("%s: not an octal number\n", argv[optind-1]);
+
+ /* posix doesn't specify modal bits */
+ if(octal & 04000) mode |= S_ISUID;
+ if(octal & 02000) mode |= S_ISGID;
+ if(octal & 01000) mode |= S_ISVTX;
+ if(octal & 00400) mode |= S_IRUSR;
+ if(octal & 00200) mode |= S_IWUSR;
+ if(octal & 00100) mode |= S_IXUSR;
+ if(octal & 00040) mode |= S_IRGRP;
+ if(octal & 00020) mode |= S_IWGRP;
+ if(octal & 00010) mode |= S_IXGRP;
+ if(octal & 00004) mode |= S_IROTH;
+ if(octal & 00002) mode |= S_IWOTH;
+ if(octal & 00001) mode |= S_IXOTH;
+
+ for(; optind < argc; optind++)
+ chmodr(argv[optind]);
+ return EXIT_SUCCESS;
+}
+
+void
+chmodr(const char *path)
+{
+ if(chmod(path, mode) != 0)
+ eprintf("chmod %s:", path);
+ if(rflag)
+ recurse(path, chmodr);
+}
diff --git a/chown.c b/chown.c
@@ -3,7 +3,6 @@
#include <grp.h>
#include <pwd.h>
#include <stdbool.h>
-#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>