2 Mode Muncher -- modemuncher.c
6 [ME monchen, perh. influenced by MF mangier to eat --more at MANGER]
7 :to chew with a crunching sound: eat with relish
8 :to chew food with a crunching sound: eat food with relish
11 The NeXT Digital Edition of Webster's Ninth New Collegiate Dictionary
12 and Webster's Collegiate Thesaurus
15 /* struct for rwx <-> POSIX constant lookup tables */
22 typedef struct modeLookup modeLookup;
24 static modeLookup modesel[] =
26 /* RWX char Posix Constant */
38 {'\0', (mode_t)-1} /* do not delete this line */
43 static int rwxrwxrwx(mode_t *mode, const char *p)
46 mode_t tmp_mode = *mode;
48 tmp_mode &= ~(S_ISUID | S_ISGID); /* turn off suid and sgid flags */
49 for (count=0; count<9; count ++)
51 if (*p == modesel[count].rwx) tmp_mode |= modesel[count].bits; /* set a bit */
52 else if (*p == '-') tmp_mode &= ~modesel[count].bits; /* clear a bit */
53 else if (*p=='s') switch(count)
55 case 2: /* turn on suid flag */
56 tmp_mode |= S_ISUID | S_IXUSR;
59 case 5: /* turn on sgid flag */
60 tmp_mode |= S_ISGID | S_IXGRP;
64 return -4; /* failed! -- bad rwxrwxrwx mode change */
73 static void modechopper(mode_t mode, char *p)
75 /* requires char p[10] */
81 for (count=0; count<9; count ++)
83 if (mode & modesel[count].bits) *p = modesel[count].rwx;
88 *p=0; /* to finish the string */
90 /* dealing with suid and sgid flags */
91 if (mode & S_ISUID) pp[2] = (mode & S_IXUSR) ? 's' : 'S';
92 if (mode & S_ISGID) pp[5] = (mode & S_IXGRP) ? 's' : 'S';
96 static int mode_munch(mode_t *mode, const char* p)
100 mode_t affected_bits, ch_mode;
107 modechopper(*mode, tmp);
108 printf("modemuncher: got base mode = %s\n", tmp);
113 /* step 0 -- clear temporary variables */
117 /* step 1 -- who's affected? */
120 printf("modemuncher step 1\n");
123 /* mode string given in rwxrwxrwx format */
124 if (*p== 'r' || *p == '-') return rwxrwxrwx(mode, p);
126 /* mode string given in 0644 format */
127 if (*p >= '0' && *p <= '7') {
129 mode_t tmp_mode = strtol(p, &e, 8);
130 if (*p == 0 || *e != 0)
136 /* mode string given in ugoa+-=rwx format */
141 affected_bits |= 04700;
145 affected_bits |= 02070;
149 affected_bits |= 01007;
153 affected_bits |= 07777;
162 goto no_more_affected;
166 /* If none specified, affect all bits. */
167 if (affected_bits == 0) affected_bits = 07777;
169 /* step 2 -- how is it changed? */
172 printf("modemuncher step 2 (*p='%c')\n", *p);
188 return -1; /* failed! -- bad operator */
192 /* step 3 -- what are the changes? */
195 printf("modemuncher step 3\n");
198 for (p++ ; *p!=0 ; p++)
214 /* Set the setuid/gid bits if `u' or `g' is selected. */
227 /* step 4 -- apply the changes */
230 printf("modemuncher step 4\n");
232 if (*p != ',') doneFlag = 1;
233 if (*p != 0 && *p != ' ' && *p != ',')
237 printf("modemuncher: comma error!\n");
238 printf("modemuncher: doneflag = %u\n", doneFlag);
240 return -2; /* failed! -- bad mode change */
244 /*if (!ch_mode) return -2;*/ /* failed! -- bad mode change */
245 if (ch_mode) switch (op)
248 *mode = *mode |= ch_mode & affected_bits;
252 *mode = *mode &= ~(ch_mode & affected_bits);
256 *mode = ch_mode & affected_bits;
260 return -3; /* failed! -- unknown error */
264 modechopper(*mode, tmp);
265 printf("modemuncher: returning mode = %s\n", tmp);
268 return 0; /* successful call */