master hovercats/oakiss / pkg / rc / patch / 0003-implement-umask-builtin-on-unix.patch
  1From 0f88ba02c7bbcb91b428bfb294831769e521a81b Mon Sep 17 00:00:00 2001
  2From: Michael Forney <mforney@mforney.org>
  3Date: Sun, 19 Apr 2026 14:11:15 -0700
  4Subject: [PATCH] implement umask builtin on unix
  5
  6---
  7 exec.h   |  2 +-
  8 fns.h    |  1 +
  9 simple.c |  2 +-
 10 unix.c   | 46 ++++++++++++++++++++++++++++++++++++++++++++++
 11 4 files changed, 49 insertions(+), 2 deletions(-)
 12
 13diff --git a/exec.h b/exec.h
 14index 69b1004..ee8edab 100644
 15--- a/exec.h
 16+++ b/exec.h
 17@@ -77,7 +77,7 @@ extern void (*builtinfunc(char *name))(void);
 18 void execcd(void), execwhatis(void), execeval(void), execexec(void);
 19 int execforkexec(void);
 20 void execexit(void), execshift(void);
 21-void execwait(void), execumask(void), execdot(void), execflag(void);
 22+void execwait(void), execdot(void), execflag(void);
 23 void execfunc(var*), execcmds(io*, char*, var*, redir*);
 24 void startfunc(var*, word*, var*, redir*);
 25 
 26diff --git a/fns.h b/fns.h
 27index 339f08b..1644d1e 100644
 28--- a/fns.h
 29+++ b/fns.h
 30@@ -45,6 +45,7 @@ int	havewaitpid(int);
 31 int	idchr(int);
 32 void	inttoascii(char*, int);
 33 void	kinit(void);
 34+int	mapfd(int);
 35 int	match(char*, char*, int);
 36 char*	makepath(char*, char*);
 37 void	panic(char*, int);
 38diff --git a/simple.c b/simple.c
 39index 362b77b..1a9d27d 100644
 40--- a/simple.c
 41+++ b/simple.c
 42@@ -287,7 +287,7 @@ execshift(void)
 43 	poplist();
 44 }
 45 
 46-static int
 47+int
 48 mapfd(int fd)
 49 {
 50 	redir *rp;
 51diff --git a/unix.c b/unix.c
 52index 05d883c..cbb2054 100644
 53--- a/unix.c
 54+++ b/unix.c
 55@@ -12,9 +12,12 @@
 56 #include <errno.h>
 57 #include <fcntl.h>
 58 #include <dirent.h>
 59+#include <limits.h>
 60+#include <sys/stat.h>
 61 #include <sys/wait.h>
 62 
 63 static void execfinit(void);
 64+static void execumask(void);
 65 
 66 builtin Builtin[] = {
 67 	"cd",		execcd,
 68@@ -24,6 +27,7 @@ builtin Builtin[] = {
 69 	"exit",		execexit,
 70 	"shift",	execshift,
 71 	"wait",		execwait,
 72+	"umask",	execumask,
 73 	".",		execdot,
 74 	"flag",		execflag,
 75 	"finit",	execfinit,
 76@@ -81,6 +85,48 @@ execfinit(void)
 77 	start(rdfns, 2, runq->local, runq->redir);
 78 }
 79 
 80+static int
 81+octal(char *s)
 82+{
 83+	int n = 0;
 84+
 85+	while(n<INT_MAX/8 && '0'<=*s && *s<='7')
 86+		n = n*8+*s++-'0';
 87+	return *s=='\0' ? n : -1;
 88+}
 89+
 90+static void
 91+execumask(void)
 92+{
 93+	int m;
 94+	struct io *out;
 95+	char *e;
 96+
 97+	switch(count(runq->argv->words)){
 98+	case 2:
 99+		m = octal(runq->argv->words->next->word);
100+		if(m>=0 && m<=07777) {
101+			umask(m);
102+			break;
103+		}
104+		/* fallthrough */
105+	default:
106+		pfmt(err, "Usage: umask [umask]\n");
107+		setstatus("umask usage");
108+		poplist();
109+		return;
110+	case 1:
111+		umask(m = umask(0));
112+		out = openiofd(mapfd(1));
113+		pfmt(out, "%o\n", m);
114+		flushio(out);
115+		free(closeiostr(out));
116+		break;
117+	}
118+	setstatus("");
119+	poplist();
120+}
121+
122 static int
123 cmpenv(const void *aa, const void *ab)
124 {
125-- 
1262.49.0
127