Dash:
[t2-trunk.git] / misc / luabash / posix / modemuncher.c
blobfae6940a54ebb2e3ea038adec6477d8f3d8d33ec
1 /*
2 Mode Muncher -- modemuncher.c
3 961110 Claudio Terra
5 munch vb
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
9 --munch-er n
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 */
16 struct modeLookup
18 char rwx;
19 mode_t bits;
22 typedef struct modeLookup modeLookup;
24 static modeLookup modesel[] =
26 /* RWX char Posix Constant */
27 {'r', S_IRUSR},
28 {'w', S_IWUSR},
29 {'x', S_IXUSR},
31 {'r', S_IRGRP},
32 {'w', S_IWGRP},
33 {'x', S_IXGRP},
35 {'r', S_IROTH},
36 {'w', S_IWOTH},
37 {'x', S_IXOTH},
38 {(char)NULL, (mode_t)-1} /* do not delete this line */
43 static int rwxrwxrwx(mode_t *mode, const char *p)
45 int count;
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;
57 break;
59 case 5: /* turn on sgid flag */
60 tmp_mode |= S_ISGID | S_IXGRP;
61 break;
63 default:
64 return -4; /* failed! -- bad rwxrwxrwx mode change */
65 break;
67 p++;
69 *mode = tmp_mode;
70 return 0;
73 static void modechopper(mode_t mode, char *p)
75 /* requires char p[10] */
76 int count;
77 char *pp;
79 pp=p;
81 for (count=0; count<9; count ++)
83 if (mode & modesel[count].bits) *p = modesel[count].rwx;
84 else *p='-';
86 p++;
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)
99 char op=0;
100 mode_t affected_bits, ch_mode;
101 int doneFlag = 0;
102 #ifdef DEBUG
103 char tmp[10];
104 #endif
106 #ifdef DEBUG
107 modechopper(*mode, tmp);
108 printf("modemuncher: got base mode = %s\n", tmp);
109 #endif
111 while (!doneFlag)
113 /* step 0 -- clear temporary variables */
114 affected_bits=0;
115 ch_mode=0;
117 /* step 1 -- who's affected? */
119 #ifdef DEBUG
120 printf("modemuncher step 1\n");
121 #endif
123 /* mode string given in rwxrwxrwx format */
124 if (*p== 'r' || *p == '-') return rwxrwxrwx(mode, p);
126 /* mode string given in ugoa+-=rwx format */
127 for ( ; ; p++)
128 switch (*p)
130 case 'u':
131 affected_bits |= 04700;
132 break;
134 case 'g':
135 affected_bits |= 02070;
136 break;
138 case 'o':
139 affected_bits |= 01007;
140 break;
142 case 'a':
143 affected_bits |= 07777;
144 break;
146 /* ignore spaces */
147 case ' ':
148 break;
151 default:
152 goto no_more_affected;
155 no_more_affected:
156 /* If none specified, affect all bits. */
157 if (affected_bits == 0) affected_bits = 07777;
159 /* step 2 -- how is it changed? */
161 #ifdef DEBUG
162 printf("modemuncher step 2 (*p='%c')\n", *p);
163 #endif
165 switch (*p)
167 case '+':
168 case '-':
169 case '=':
170 op = *p;
171 break;
173 /* ignore spaces */
174 case ' ':
175 break;
177 default:
178 return -1; /* failed! -- bad operator */
182 /* step 3 -- what are the changes? */
184 #ifdef DEBUG
185 printf("modemuncher step 3\n");
186 #endif
188 for (p++ ; *p!=0 ; p++)
189 switch (*p)
191 case 'r':
192 ch_mode |= 00444;
193 break;
195 case 'w':
196 ch_mode |= 00222;
197 break;
199 case 'x':
200 ch_mode |= 00111;
201 break;
203 case 's':
204 /* Set the setuid/gid bits if `u' or `g' is selected. */
205 ch_mode |= 06000;
206 break;
208 /* ignore spaces */
209 case ' ':
210 break;
212 default:
213 goto specs_done;
216 specs_done:
217 /* step 4 -- apply the changes */
219 #ifdef DEBUG
220 printf("modemuncher step 4\n");
221 #endif
222 if (*p != ',') doneFlag = 1;
223 if (*p != 0 && *p != ' ' && *p != ',')
226 #ifdef DEBUG
227 printf("modemuncher: comma error!\n");
228 printf("modemuncher: doneflag = %u\n", doneFlag);
229 #endif
230 return -2; /* failed! -- bad mode change */
233 p++;
234 /*if (!ch_mode) return -2;*/ /* failed! -- bad mode change */
235 if (ch_mode) switch (op)
237 case '+':
238 *mode = *mode |= ch_mode & affected_bits;
239 break;
241 case '-':
242 *mode = *mode &= ~(ch_mode & affected_bits);
243 break;
245 case '=':
246 *mode = ch_mode & affected_bits;
247 break;
249 default:
250 return -3; /* failed! -- unknown error */
253 #ifdef DEBUG
254 modechopper(*mode, tmp);
255 printf("modemuncher: returning mode = %s\n", tmp);
256 #endif
258 return 0; /* successful call */