summaryrefslogtreecommitdiff
path: root/luaext/modemuncher.c
diff options
context:
space:
mode:
authorPanu Matilainen <pmatilai@redhat.com>2008-04-16 15:13:25 +0300
committerPanu Matilainen <pmatilai@redhat.com>2008-04-16 15:37:52 +0300
commitd48e6c8380ebd1f8d4d4f2c80237dc1488da4721 (patch)
tree004158090fc80b15a620f2c960b0e029cad25835 /luaext/modemuncher.c
parent23f6917b10b6579f39199e4cf831bb13fc596824 (diff)
downloadrpm-d48e6c8380ebd1f8d4d4f2c80237dc1488da4721.tar.gz
rpm-d48e6c8380ebd1f8d4d4f2c80237dc1488da4721.tar.bz2
rpm-d48e6c8380ebd1f8d4d4f2c80237dc1488da4721.zip
Start phasing out internal copy of Lua
- don't build internal copy of Lua - move 3rd party extensions (posix and rexlib) to toplevel luaext/ directory, built by default (unless --without-lua specified) - auto*foo checks for external Lua - minimal tweaks to lposix.c and rpmlua.c to get them build with Lua 5.1
Diffstat (limited to 'luaext/modemuncher.c')
-rw-r--r--luaext/modemuncher.c271
1 files changed, 271 insertions, 0 deletions
diff --git a/luaext/modemuncher.c b/luaext/modemuncher.c
new file mode 100644
index 000000000..b1e966c9b
--- /dev/null
+++ b/luaext/modemuncher.c
@@ -0,0 +1,271 @@
+/*
+ Mode Muncher -- modemuncher.c
+ 961110 Claudio Terra
+
+ munch vb
+ [ME monchen, perh. influenced by MF mangier to eat --more at MANGER]
+ :to chew with a crunching sound: eat with relish
+ :to chew food with a crunching sound: eat food with relish
+ --munch-er n
+
+ The NeXT Digital Edition of Webster's Ninth New Collegiate Dictionary
+ and Webster's Collegiate Thesaurus
+*/
+
+/* struct for rwx <-> POSIX constant lookup tables */
+struct modeLookup
+{
+ char rwx;
+ mode_t bits;
+};
+
+typedef struct modeLookup modeLookup;
+
+static modeLookup modesel[] =
+{
+ /* RWX char Posix Constant */
+ {'r', S_IRUSR},
+ {'w', S_IWUSR},
+ {'x', S_IXUSR},
+
+ {'r', S_IRGRP},
+ {'w', S_IWGRP},
+ {'x', S_IXGRP},
+
+ {'r', S_IROTH},
+ {'w', S_IWOTH},
+ {'x', S_IXOTH},
+ {(char)NULL, (mode_t)-1} /* do not delete this line */
+};
+
+
+
+static int rwxrwxrwx(mode_t *mode, const char *p)
+{
+ int count;
+ mode_t tmp_mode = *mode;
+
+ tmp_mode &= ~(S_ISUID | S_ISGID); /* turn off suid and sgid flags */
+ for (count=0; count<9; count ++)
+ {
+ if (*p == modesel[count].rwx) tmp_mode |= modesel[count].bits; /* set a bit */
+ else if (*p == '-') tmp_mode &= ~modesel[count].bits; /* clear a bit */
+ else if (*p=='s') switch(count)
+ {
+ case 2: /* turn on suid flag */
+ tmp_mode |= S_ISUID | S_IXUSR;
+ break;
+
+ case 5: /* turn on sgid flag */
+ tmp_mode |= S_ISGID | S_IXGRP;
+ break;
+
+ default:
+ return -4; /* failed! -- bad rwxrwxrwx mode change */
+ break;
+ }
+ p++;
+ }
+ *mode = tmp_mode;
+ return 0;
+}
+
+static void modechopper(mode_t mode, char *p)
+{
+ /* requires char p[10] */
+ int count;
+ char *pp;
+
+ pp=p;
+
+ for (count=0; count<9; count ++)
+ {
+ if (mode & modesel[count].bits) *p = modesel[count].rwx;
+ else *p='-';
+
+ p++;
+ }
+ *p=0; /* to finish the string */
+
+ /* dealing with suid and sgid flags */
+ if (mode & S_ISUID) pp[2] = (mode & S_IXUSR) ? 's' : 'S';
+ if (mode & S_ISGID) pp[5] = (mode & S_IXGRP) ? 's' : 'S';
+
+}
+
+static int mode_munch(mode_t *mode, const char* p)
+{
+
+ char op=0;
+ mode_t affected_bits, ch_mode;
+ int doneFlag = 0;
+#ifdef DEBUG
+char tmp[10];
+#endif
+
+#ifdef DEBUG
+modechopper(*mode, tmp);
+printf("modemuncher: got base mode = %s\n", tmp);
+#endif
+
+ while (!doneFlag)
+ {
+ /* step 0 -- clear temporary variables */
+ affected_bits=0;
+ ch_mode=0;
+
+ /* step 1 -- who's affected? */
+
+#ifdef DEBUG
+printf("modemuncher step 1\n");
+#endif
+
+ /* mode string given in rwxrwxrwx format */
+ if (*p== 'r' || *p == '-') return rwxrwxrwx(mode, p);
+
+ /* mode string given in 0644 format */
+ if (*p >= '0' && *p <= '7') {
+ char *e;
+ mode_t tmp_mode = strtol(p, &e, 8);
+ if (*p == 0 || *e != 0)
+ return -5;
+ *mode = tmp_mode;
+ return 0;
+ }
+
+ /* mode string given in ugoa+-=rwx format */
+ for ( ; ; p++)
+ switch (*p)
+ {
+ case 'u':
+ affected_bits |= 04700;
+ break;
+
+ case 'g':
+ affected_bits |= 02070;
+ break;
+
+ case 'o':
+ affected_bits |= 01007;
+ break;
+
+ case 'a':
+ affected_bits |= 07777;
+ break;
+
+ /* ignore spaces */
+ case ' ':
+ break;
+
+
+ default:
+ goto no_more_affected;
+ }
+
+ no_more_affected:
+ /* If none specified, affect all bits. */
+ if (affected_bits == 0) affected_bits = 07777;
+
+ /* step 2 -- how is it changed? */
+
+#ifdef DEBUG
+printf("modemuncher step 2 (*p='%c')\n", *p);
+#endif
+
+ switch (*p)
+ {
+ case '+':
+ case '-':
+ case '=':
+ op = *p;
+ break;
+
+ /* ignore spaces */
+ case ' ':
+ break;
+
+ default:
+ return -1; /* failed! -- bad operator */
+ }
+
+
+ /* step 3 -- what are the changes? */
+
+#ifdef DEBUG
+printf("modemuncher step 3\n");
+#endif
+
+ for (p++ ; *p!=0 ; p++)
+ switch (*p)
+ {
+ case 'r':
+ ch_mode |= 00444;
+ break;
+
+ case 'w':
+ ch_mode |= 00222;
+ break;
+
+ case 'x':
+ ch_mode |= 00111;
+ break;
+
+ case 's':
+ /* Set the setuid/gid bits if `u' or `g' is selected. */
+ ch_mode |= 06000;
+ break;
+
+ /* ignore spaces */
+ case ' ':
+ break;
+
+ default:
+ goto specs_done;
+ }
+
+ specs_done:
+ /* step 4 -- apply the changes */
+
+#ifdef DEBUG
+ printf("modemuncher step 4\n");
+#endif
+ if (*p != ',') doneFlag = 1;
+ if (*p != 0 && *p != ' ' && *p != ',')
+ {
+
+#ifdef DEBUG
+printf("modemuncher: comma error!\n");
+printf("modemuncher: doneflag = %u\n", doneFlag);
+#endif
+ return -2; /* failed! -- bad mode change */
+
+ }
+ p++;
+ /*if (!ch_mode) return -2;*/ /* failed! -- bad mode change */
+ if (ch_mode) switch (op)
+ {
+ case '+':
+ *mode = *mode |= ch_mode & affected_bits;
+ break;
+
+ case '-':
+ *mode = *mode &= ~(ch_mode & affected_bits);
+ break;
+
+ case '=':
+ *mode = ch_mode & affected_bits;
+ break;
+
+ default:
+ return -3; /* failed! -- unknown error */
+ }
+ }
+#ifdef DEBUG
+modechopper(*mode, tmp);
+printf("modemuncher: returning mode = %s\n", tmp);
+#endif
+
+ return 0; /* successful call */
+}
+
+