summaryrefslogtreecommitdiff
path: root/usr/src/lib/libast/common/string/strperm.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libast/common/string/strperm.c')
-rw-r--r--usr/src/lib/libast/common/string/strperm.c267
1 files changed, 267 insertions, 0 deletions
diff --git a/usr/src/lib/libast/common/string/strperm.c b/usr/src/lib/libast/common/string/strperm.c
new file mode 100644
index 0000000000..b54b193186
--- /dev/null
+++ b/usr/src/lib/libast/common/string/strperm.c
@@ -0,0 +1,267 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2007 AT&T Knowledge Ventures *
+* and is licensed under the *
+* Common Public License, Version 1.0 *
+* by AT&T Knowledge Ventures *
+* *
+* A copy of the License is available at *
+* http://www.opensource.org/licenses/cpl1.0.txt *
+* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * apply file permission expression expr to perm
+ *
+ * each expression term must match
+ *
+ * [ugoa]*[-&+|^=]?[rwxst0-7]*
+ *
+ * terms may be combined using ,
+ *
+ * if non-null, e points to the first unrecognized char in expr
+ */
+
+#include <ast.h>
+#include <ls.h>
+#include <modex.h>
+
+int
+strperm(const char* aexpr, char** e, register int perm)
+{
+ register char* expr = (char*)aexpr;
+ register int c;
+ register int typ;
+ register int who;
+ int num;
+ int op;
+ int mask;
+ int masked;
+
+ if (perm == -1)
+ {
+ perm = 0;
+ masked = 1;
+ mask = ~0;
+ }
+ else
+ masked = 0;
+ for (;;)
+ {
+ op = num = who = typ = 0;
+ for (;;)
+ {
+ switch (c = *expr++)
+ {
+ case 'u':
+ who |= S_ISVTX|S_ISUID|S_IRWXU;
+ continue;
+ case 'g':
+ who |= S_ISVTX|S_ISGID|S_IRWXG;
+ continue;
+ case 'o':
+ who |= S_ISVTX|S_IRWXO;
+ continue;
+ case 'a':
+ who = S_ISVTX|S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO;
+ continue;
+ default:
+ if (c >= '0' && c <= '7')
+ {
+ if (!who)
+ who = S_ISVTX|S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO;
+ c = '=';
+ }
+ expr--;
+ /*FALLTHROUGH*/
+ case '=':
+ if (who)
+ perm &= ~who;
+ else
+ perm = 0;
+ /*FALLTHROUGH*/
+ case '+':
+ case '|':
+ case '-':
+ case '&':
+ case '^':
+ op = c;
+ for (;;)
+ {
+ switch (c = *expr++)
+ {
+ case 'r':
+ typ |= S_IRUSR|S_IRGRP|S_IROTH;
+ continue;
+ case 'w':
+ typ |= S_IWUSR|S_IWGRP|S_IWOTH;
+ continue;
+ case 'X':
+ if (!S_ISDIR(perm) && !(perm & (S_IXUSR|S_IXGRP|S_IXOTH)))
+ continue;
+ /*FALLTHROUGH*/
+ case 'x':
+ typ |= S_IXUSR|S_IXGRP|S_IXOTH;
+ continue;
+ case 's':
+ typ |= S_ISUID|S_ISGID;
+ continue;
+ case 't':
+ typ |= S_ISVTX;
+ continue;
+ case 'l':
+ if (perm & S_IXGRP)
+ {
+ if (e)
+ *e = expr - 1;
+ return perm & S_IPERM;
+ }
+ typ |= S_ISGID;
+ continue;
+ case '=':
+ case '+':
+ case '|':
+ case '-':
+ case '&':
+ case '^':
+ case ',':
+ case 0:
+ if (who)
+ typ &= who;
+ else
+ switch (op)
+ {
+ case '=':
+ case '+':
+ case '|':
+ case '-':
+ case '&':
+ if (!masked)
+ {
+ masked = 1;
+ umask(mask = umask(0));
+ mask = ~mask;
+ }
+ typ &= mask;
+ break;
+ }
+ switch (op)
+ {
+ default:
+ if (who)
+ perm &= ~who;
+ else
+ perm = 0;
+ /*FALLTHROUGH*/
+ case '+':
+ case '|':
+ perm |= typ;
+ typ = 0;
+ break;
+ case '-':
+ perm &= ~typ;
+ typ = 0;
+ break;
+ case '&':
+ perm &= typ;
+ typ = 0;
+ break;
+ case '^':
+ if (typ &= perm)
+ {
+ /*
+ * propagate least restrictive to most restrictive
+ */
+
+ if (typ & S_IXOTH)
+ perm |= who & (S_IXUSR|S_IXGRP);
+ if (typ & S_IWOTH)
+ perm |= who & (S_IWUSR|S_IWGRP);
+ if (typ & S_IROTH)
+ perm |= who & (S_IRUSR|S_IRGRP);
+ if (typ & S_IXGRP)
+ perm |= who & S_IXUSR;
+ if (typ & S_IWGRP)
+ perm |= who & S_IWUSR;
+ if (typ & S_IRGRP)
+ perm |= who & S_IRUSR;
+
+ /*
+ * if any execute then read => execute
+ */
+
+ if ((typ |= perm) & (S_IXUSR|S_IXGRP|S_IXOTH))
+ {
+ if (typ & S_IRUSR)
+ perm |= who & S_IXUSR;
+ if (typ & S_IRGRP)
+ perm |= who & S_IXGRP;
+ if (typ & S_IROTH)
+ perm |= who & S_IXOTH;
+ }
+ typ = 0;
+ }
+ break;
+ }
+ switch (c)
+ {
+ case '=':
+ case '+':
+ case '|':
+ case '-':
+ case '&':
+ case '^':
+ op = c;
+ typ = 0;
+ continue;
+ }
+ if (c)
+ break;
+ /*FALLTHROUGH*/
+ default:
+ if (c < '0' || c > '7')
+ {
+ if (e)
+ *e = expr - 1;
+ if (typ)
+ {
+ if (who)
+ {
+ typ &= who;
+ perm &= ~who;
+ }
+ perm |= typ;
+ }
+ return perm & S_IPERM;
+ }
+ num = (num << 3) | (c - '0');
+ if (!who && (op == '+' || op == '-'))
+ who = S_ISVTX|S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO;
+ if (*expr < '0' || *expr > '7')
+ {
+ typ |= modei(num);
+ num = 0;
+ }
+ continue;
+ }
+ break;
+ }
+ break;
+ }
+ break;
+ }
+ }
+}