]> git.pld-linux.org Git - packages/ash.git/blob - ash-setmode.patch
- dropped pre-cvs changelog
[packages/ash.git] / ash-setmode.patch
1 diff -urN netbsd-sh/miscbltin.c ash-0.3.7.orig/miscbltin.c
2 --- netbsd-sh/miscbltin.c       Fri Jan 12 17:50:37 2001
3 +++ ash-0.3.7.orig/miscbltin.c  Mon Apr 23 22:16:46 2001
4 @@ -70,6 +70,15 @@
5  
6  #undef rflag
7  
8 +#ifdef __GLIBC__
9 +mode_t getmode(const void *, mode_t);
10 +void *setmode(const char *);
11 +
12 +#if !defined(__GLIBC__) || __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
13 +typedef enum __rlimit_resource rlim_t;
14 +#endif
15 +#endif
16 +
17  extern char **argptr;          /* argument list for builtin command */
18  
19  
20 diff -urN netbsd-sh/setmode.c ash-0.3.7.orig/setmode.c
21 --- netbsd-sh/setmode.c Thu Jan  1 01:00:00 1970
22 +++ ash-0.3.7.orig/setmode.c    Mon Apr 23 22:16:46 2001
23 @@ -0,0 +1,486 @@
24 +/*     $NetBSD: setmode.c,v 1.28 2000/01/25 15:43:43 enami Exp $       */
25 +
26 +/*
27 + * Copyright (c) 1989, 1993, 1994
28 + *     The Regents of the University of California.  All rights reserved.
29 + *
30 + * This code is derived from software contributed to Berkeley by
31 + * Dave Borman at Cray Research, Inc.
32 + *
33 + * Redistribution and use in source and binary forms, with or without
34 + * modification, are permitted provided that the following conditions
35 + * are met:
36 + * 1. Redistributions of source code must retain the above copyright
37 + *    notice, this list of conditions and the following disclaimer.
38 + * 2. Redistributions in binary form must reproduce the above copyright
39 + *    notice, this list of conditions and the following disclaimer in the
40 + *    documentation and/or other materials provided with the distribution.
41 + * 3. All advertising materials mentioning features or use of this software
42 + *    must display the following acknowledgement:
43 + *     This product includes software developed by the University of
44 + *     California, Berkeley and its contributors.
45 + * 4. Neither the name of the University nor the names of its contributors
46 + *    may be used to endorse or promote products derived from this software
47 + *    without specific prior written permission.
48 + *
49 + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52 + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 + * SUCH DAMAGE.
60 + */
61 +
62 +#include <sys/cdefs.h>
63 +#if defined(LIBC_SCCS) && !defined(lint)
64 +#if 0
65 +static char sccsid[] = "@(#)setmode.c  8.2 (Berkeley) 3/25/94";
66 +#else
67 +__RCSID("$NetBSD: setmode.c,v 1.28 2000/01/25 15:43:43 enami Exp $");
68 +#endif
69 +#endif /* LIBC_SCCS and not lint */
70 +
71 +#include <sys/types.h>
72 +#include <sys/stat.h>
73 +
74 +#include <assert.h>
75 +#include <ctype.h>
76 +#include <errno.h>
77 +#include <signal.h>
78 +#include <stdlib.h>
79 +#include <unistd.h>
80 +
81 +#ifdef SETMODE_DEBUG
82 +#include <stdio.h>
83 +#endif
84 +
85 +#ifdef __weak_alias
86 +__weak_alias(getmode,_getmode)
87 +__weak_alias(setmode,_setmode)
88 +#endif
89 +
90 +#ifdef __GLIBC__
91 +#define S_ISTXT __S_ISVTX
92 +#endif
93 +
94 +#define        SET_LEN 6               /* initial # of bitcmd struct to malloc */
95 +#define        SET_LEN_INCR 4          /* # of bitcmd structs to add as needed */
96 +
97 +typedef struct bitcmd {
98 +       char    cmd;
99 +       char    cmd2;
100 +       mode_t  bits;
101 +} BITCMD;
102 +
103 +#define        CMD2_CLR        0x01
104 +#define        CMD2_SET        0x02
105 +#define        CMD2_GBITS      0x04
106 +#define        CMD2_OBITS      0x08
107 +#define        CMD2_UBITS      0x10
108 +
109 +static BITCMD  *addcmd __P((BITCMD *, int, int, int, u_int));
110 +static void     compress_mode __P((BITCMD *));
111 +#ifdef SETMODE_DEBUG
112 +static void     dumpmode __P((BITCMD *));
113 +#endif
114 +
115 +/*
116 + * Given the old mode and an array of bitcmd structures, apply the operations
117 + * described in the bitcmd structures to the old mode, and return the new mode.
118 + * Note that there is no '=' command; a strict assignment is just a '-' (clear
119 + * bits) followed by a '+' (set bits).
120 + */
121 +mode_t
122 +getmode(bbox, omode)
123 +       const void *bbox;
124 +       mode_t omode;
125 +{
126 +       const BITCMD *set;
127 +       mode_t clrval, newmode, value;
128 +
129 +       _DIAGASSERT(bbox != NULL);
130 +
131 +       set = (const BITCMD *)bbox;
132 +       newmode = omode;
133 +       for (value = 0;; set++)
134 +               switch(set->cmd) {
135 +               /*
136 +                * When copying the user, group or other bits around, we "know"
137 +                * where the bits are in the mode so that we can do shifts to
138 +                * copy them around.  If we don't use shifts, it gets real
139 +                * grundgy with lots of single bit checks and bit sets.
140 +                */
141 +               case 'u':
142 +                       value = (newmode & S_IRWXU) >> 6;
143 +                       goto common;
144 +
145 +               case 'g':
146 +                       value = (newmode & S_IRWXG) >> 3;
147 +                       goto common;
148 +
149 +               case 'o':
150 +                       value = newmode & S_IRWXO;
151 +common:                        if (set->cmd2 & CMD2_CLR) {
152 +                               clrval =
153 +                                   (set->cmd2 & CMD2_SET) ?  S_IRWXO : value;
154 +                               if (set->cmd2 & CMD2_UBITS)
155 +                                       newmode &= ~((clrval<<6) & set->bits);
156 +                               if (set->cmd2 & CMD2_GBITS)
157 +                                       newmode &= ~((clrval<<3) & set->bits);
158 +                               if (set->cmd2 & CMD2_OBITS)
159 +                                       newmode &= ~(clrval & set->bits);
160 +                       }
161 +                       if (set->cmd2 & CMD2_SET) {
162 +                               if (set->cmd2 & CMD2_UBITS)
163 +                                       newmode |= (value<<6) & set->bits;
164 +                               if (set->cmd2 & CMD2_GBITS)
165 +                                       newmode |= (value<<3) & set->bits;
166 +                               if (set->cmd2 & CMD2_OBITS)
167 +                                       newmode |= value & set->bits;
168 +                       }
169 +                       break;
170 +
171 +               case '+':
172 +                       newmode |= set->bits;
173 +                       break;
174 +
175 +               case '-':
176 +                       newmode &= ~set->bits;
177 +                       break;
178 +
179 +               case 'X':
180 +                       if (omode & (S_IFDIR|S_IXUSR|S_IXGRP|S_IXOTH))
181 +                               newmode |= set->bits;
182 +                       break;
183 +
184 +               case '\0':
185 +               default:
186 +#ifdef SETMODE_DEBUG
187 +                       (void)printf("getmode:%04o -> %04o\n", omode, newmode);
188 +#endif
189 +                       return (newmode);
190 +               }
191 +}
192 +
193 +#define        ADDCMD(a, b, c, d) do {                                         \
194 +       if (set >= endset) {                                            \
195 +               BITCMD *newset;                                         \
196 +               setlen += SET_LEN_INCR;                                 \
197 +               newset = realloc(saveset, sizeof(BITCMD) * setlen);     \
198 +               if (newset == NULL) {                                   \
199 +                       free(saveset);                                  \
200 +                       return (NULL);                                  \
201 +               }                                                       \
202 +               set = newset + (set - saveset);                         \
203 +               saveset = newset;                                       \
204 +               endset = newset + (setlen - 2);                         \
205 +       }                                                               \
206 +       set = addcmd(set, (a), (b), (c), (d));                          \
207 +} while (/*CONSTCOND*/0)
208 +
209 +#define        STANDARD_BITS   (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO)
210 +
211 +void *
212 +setmode(p)
213 +       const char *p;
214 +{
215 +       int perm, who;
216 +       char op, *ep;
217 +       BITCMD *set, *saveset, *endset;
218 +       sigset_t sigset, sigoset;
219 +       mode_t mask;
220 +       int equalopdone = 0;    /* pacify gcc */
221 +       int permXbits, setlen;
222 +
223 +       if (!*p)
224 +               return (NULL);
225 +
226 +       /*
227 +        * Get a copy of the mask for the permissions that are mask relative.
228 +        * Flip the bits, we want what's not set.  Since it's possible that
229 +        * the caller is opening files inside a signal handler, protect them
230 +        * as best we can.
231 +        */
232 +       sigfillset(&sigset);
233 +       (void)sigprocmask(SIG_BLOCK, &sigset, &sigoset);
234 +       (void)umask(mask = umask(0));
235 +       mask = ~mask;
236 +       (void)sigprocmask(SIG_SETMASK, &sigoset, NULL);
237 +
238 +       setlen = SET_LEN + 2;
239 +       
240 +       if ((set = malloc((u_int)(sizeof(BITCMD) * setlen))) == NULL)
241 +               return (NULL);
242 +       saveset = set;
243 +       endset = set + (setlen - 2);
244 +
245 +       /*
246 +        * If an absolute number, get it and return; disallow non-octal digits
247 +        * or illegal bits.
248 +        */
249 +       if (isdigit((unsigned char)*p)) {
250 +               perm = (mode_t)strtol(p, &ep, 8);
251 +               if (*ep || perm & ~(STANDARD_BITS|S_ISTXT)) {
252 +                       free(saveset);
253 +                       return (NULL);
254 +               }
255 +               ADDCMD('=', (STANDARD_BITS|S_ISTXT), perm, mask);
256 +               set->cmd = 0;
257 +               return (saveset);
258 +       }
259 +
260 +       /*
261 +        * Build list of structures to set/clear/copy bits as described by
262 +        * each clause of the symbolic mode.
263 +        */
264 +       for (;;) {
265 +               /* First, find out which bits might be modified. */
266 +               for (who = 0;; ++p) {
267 +                       switch (*p) {
268 +                       case 'a':
269 +                               who |= STANDARD_BITS;
270 +                               break;
271 +                       case 'u':
272 +                               who |= S_ISUID|S_IRWXU;
273 +                               break;
274 +                       case 'g':
275 +                               who |= S_ISGID|S_IRWXG;
276 +                               break;
277 +                       case 'o':
278 +                               who |= S_IRWXO;
279 +                               break;
280 +                       default:
281 +                               goto getop;
282 +                       }
283 +               }
284 +
285 +getop:         if ((op = *p++) != '+' && op != '-' && op != '=') {
286 +                       free(saveset);
287 +                       return (NULL);
288 +               }
289 +               if (op == '=')
290 +                       equalopdone = 0;
291 +
292 +               who &= ~S_ISTXT;
293 +               for (perm = 0, permXbits = 0;; ++p) {
294 +                       switch (*p) {
295 +                       case 'r':
296 +                               perm |= S_IRUSR|S_IRGRP|S_IROTH;
297 +                               break;
298 +                       case 's':
299 +                               /*
300 +                                * If specific bits where requested and 
301 +                                * only "other" bits ignore set-id. 
302 +                                */
303 +                               if (who == 0 || (who & ~S_IRWXO))
304 +                                       perm |= S_ISUID|S_ISGID;
305 +                               break;
306 +                       case 't':
307 +                               /*
308 +                                * If specific bits where requested and 
309 +                                * only "other" bits ignore set-id. 
310 +                                */
311 +                               if (who == 0 || (who & ~S_IRWXO)) {
312 +                                       who |= S_ISTXT;
313 +                                       perm |= S_ISTXT;
314 +                               }
315 +                               break;
316 +                       case 'w':
317 +                               perm |= S_IWUSR|S_IWGRP|S_IWOTH;
318 +                               break;
319 +                       case 'X':
320 +                               permXbits = S_IXUSR|S_IXGRP|S_IXOTH;
321 +                               break;
322 +                       case 'x':
323 +                               perm |= S_IXUSR|S_IXGRP|S_IXOTH;
324 +                               break;
325 +                       case 'u':
326 +                       case 'g':
327 +                       case 'o':
328 +                               /*
329 +                                * When ever we hit 'u', 'g', or 'o', we have
330 +                                * to flush out any partial mode that we have,
331 +                                * and then do the copying of the mode bits.
332 +                                */
333 +                               if (perm) {
334 +                                       ADDCMD(op, who, perm, mask);
335 +                                       perm = 0;
336 +                               }
337 +                               if (op == '=')
338 +                                       equalopdone = 1;
339 +                               if (op == '+' && permXbits) {
340 +                                       ADDCMD('X', who, permXbits, mask);
341 +                                       permXbits = 0;
342 +                               }
343 +                               ADDCMD(*p, who, op, mask);
344 +                               break;
345 +
346 +                       default:
347 +                               /*
348 +                                * Add any permissions that we haven't already
349 +                                * done.
350 +                                */
351 +                               if (perm || (op == '=' && !equalopdone)) {
352 +                                       if (op == '=')
353 +                                               equalopdone = 1;
354 +                                       ADDCMD(op, who, perm, mask);
355 +                                       perm = 0;
356 +                               }
357 +                               if (permXbits) {
358 +                                       ADDCMD('X', who, permXbits, mask);
359 +                                       permXbits = 0;
360 +                               }
361 +                               goto apply;
362 +                       }
363 +               }
364 +
365 +apply:         if (!*p)
366 +                       break;
367 +               if (*p != ',')
368 +                       goto getop;
369 +               ++p;
370 +       }
371 +       set->cmd = 0;
372 +#ifdef SETMODE_DEBUG
373 +       (void)printf("Before compress_mode()\n");
374 +       dumpmode(saveset);
375 +#endif
376 +       compress_mode(saveset);
377 +#ifdef SETMODE_DEBUG
378 +       (void)printf("After compress_mode()\n");
379 +       dumpmode(saveset);
380 +#endif
381 +       return (saveset);
382 +}
383 +
384 +static BITCMD *
385 +addcmd(set, op, who, oparg, mask)
386 +       BITCMD *set;
387 +       int oparg, who;
388 +       int op;
389 +       u_int mask;
390 +{
391 +
392 +       _DIAGASSERT(set != NULL);
393 +
394 +       switch (op) {
395 +       case '=':
396 +               set->cmd = '-';
397 +               set->bits = who ? who : STANDARD_BITS;
398 +               set++;
399 +
400 +               op = '+';
401 +               /* FALLTHROUGH */
402 +       case '+':
403 +       case '-':
404 +       case 'X':
405 +               set->cmd = op;
406 +               set->bits = (who ? who : mask) & oparg;
407 +               break;
408 +
409 +       case 'u':
410 +       case 'g':
411 +       case 'o':
412 +               set->cmd = op;
413 +               if (who) {
414 +                       set->cmd2 = ((who & S_IRUSR) ? CMD2_UBITS : 0) |
415 +                                   ((who & S_IRGRP) ? CMD2_GBITS : 0) |
416 +                                   ((who & S_IROTH) ? CMD2_OBITS : 0);
417 +                       set->bits = (mode_t)~0;
418 +               } else {
419 +                       set->cmd2 = CMD2_UBITS | CMD2_GBITS | CMD2_OBITS;
420 +                       set->bits = mask;
421 +               }
422 +       
423 +               if (oparg == '+')
424 +                       set->cmd2 |= CMD2_SET;
425 +               else if (oparg == '-')
426 +                       set->cmd2 |= CMD2_CLR;
427 +               else if (oparg == '=')
428 +                       set->cmd2 |= CMD2_SET|CMD2_CLR;
429 +               break;
430 +       }
431 +       return (set + 1);
432 +}
433 +
434 +#ifdef SETMODE_DEBUG
435 +static void
436 +dumpmode(set)
437 +       BITCMD *set;
438 +{
439 +
440 +       _DIAGASSERT(set != NULL);
441 +
442 +       for (; set->cmd; ++set)
443 +               (void)printf("cmd: '%c' bits %04o%s%s%s%s%s%s\n",
444 +                   set->cmd, set->bits, set->cmd2 ? " cmd2:" : "",
445 +                   set->cmd2 & CMD2_CLR ? " CLR" : "",
446 +                   set->cmd2 & CMD2_SET ? " SET" : "",
447 +                   set->cmd2 & CMD2_UBITS ? " UBITS" : "",
448 +                   set->cmd2 & CMD2_GBITS ? " GBITS" : "",
449 +                   set->cmd2 & CMD2_OBITS ? " OBITS" : "");
450 +}
451 +#endif
452 +
453 +/*
454 + * Given an array of bitcmd structures, compress by compacting consecutive
455 + * '+', '-' and 'X' commands into at most 3 commands, one of each.  The 'u',
456 + * 'g' and 'o' commands continue to be separate.  They could probably be 
457 + * compacted, but it's not worth the effort.
458 + */
459 +static void
460 +compress_mode(set)
461 +       BITCMD *set;
462 +{
463 +       BITCMD *nset;
464 +       int setbits, clrbits, Xbits, op;
465 +
466 +       _DIAGASSERT(set != NULL);
467 +
468 +       for (nset = set;;) {
469 +               /* Copy over any 'u', 'g' and 'o' commands. */
470 +               while ((op = nset->cmd) != '+' && op != '-' && op != 'X') {
471 +                       *set++ = *nset++;
472 +                       if (!op)
473 +                               return;
474 +               }
475 +
476 +               for (setbits = clrbits = Xbits = 0;; nset++) {
477 +                       if ((op = nset->cmd) == '-') {
478 +                               clrbits |= nset->bits;
479 +                               setbits &= ~nset->bits;
480 +                               Xbits &= ~nset->bits;
481 +                       } else if (op == '+') {
482 +                               setbits |= nset->bits;
483 +                               clrbits &= ~nset->bits;
484 +                               Xbits &= ~nset->bits;
485 +                       } else if (op == 'X')
486 +                               Xbits |= nset->bits & ~setbits;
487 +                       else
488 +                               break;
489 +               }
490 +               if (clrbits) {
491 +                       set->cmd = '-';
492 +                       set->cmd2 = 0;
493 +                       set->bits = clrbits;
494 +                       set++;
495 +               }
496 +               if (setbits) {
497 +                       set->cmd = '+';
498 +                       set->cmd2 = 0;
499 +                       set->bits = setbits;
500 +                       set++;
501 +               }
502 +               if (Xbits) {
503 +                       set->cmd = 'X';
504 +                       set->cmd2 = 0;
505 +                       set->bits = Xbits;
506 +                       set++;
507 +               }
508 +       }
509 +}
510
This page took 0.108821 seconds and 3 git commands to generate.