summaryrefslogtreecommitdiffstats
path: root/source/ap/ash/patches/ash-setmode.patch
diff options
context:
space:
mode:
Diffstat (limited to 'source/ap/ash/patches/ash-setmode.patch')
-rw-r--r--source/ap/ash/patches/ash-setmode.patch510
1 files changed, 510 insertions, 0 deletions
diff --git a/source/ap/ash/patches/ash-setmode.patch b/source/ap/ash/patches/ash-setmode.patch
new file mode 100644
index 000000000..b9a26d9ca
--- /dev/null
+++ b/source/ap/ash/patches/ash-setmode.patch
@@ -0,0 +1,510 @@
+diff -urN netbsd-sh/miscbltin.c ash-0.3.7.orig/miscbltin.c
+--- netbsd-sh/miscbltin.c Fri Jan 12 17:50:37 2001
++++ ash-0.3.7.orig/miscbltin.c Mon Apr 23 22:16:46 2001
+@@ -70,6 +70,15 @@
+
+ #undef rflag
+
++#ifdef __GLIBC__
++mode_t getmode(const void *, mode_t);
++void *setmode(const char *);
++
++#if !defined(__GLIBC__) || __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
++typedef enum __rlimit_resource rlim_t;
++#endif
++#endif
++
+ extern char **argptr; /* argument list for builtin command */
+
+
+diff -urN netbsd-sh/setmode.c ash-0.3.7.orig/setmode.c
+--- netbsd-sh/setmode.c Thu Jan 1 01:00:00 1970
++++ ash-0.3.7.orig/setmode.c Mon Apr 23 22:16:46 2001
+@@ -0,0 +1,486 @@
++/* $NetBSD: setmode.c,v 1.28 2000/01/25 15:43:43 enami Exp $ */
++
++/*
++ * Copyright (c) 1989, 1993, 1994
++ * The Regents of the University of California. All rights reserved.
++ *
++ * This code is derived from software contributed to Berkeley by
++ * Dave Borman at Cray Research, Inc.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 3. All advertising materials mentioning features or use of this software
++ * must display the following acknowledgement:
++ * This product includes software developed by the University of
++ * California, Berkeley and its contributors.
++ * 4. Neither the name of the University nor the names of its contributors
++ * may be used to endorse or promote products derived from this software
++ * without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
++ * SUCH DAMAGE.
++ */
++
++#include <sys/cdefs.h>
++#if defined(LIBC_SCCS) && !defined(lint)
++#if 0
++static char sccsid[] = "@(#)setmode.c 8.2 (Berkeley) 3/25/94";
++#else
++__RCSID("$NetBSD: setmode.c,v 1.28 2000/01/25 15:43:43 enami Exp $");
++#endif
++#endif /* LIBC_SCCS and not lint */
++
++#include <sys/types.h>
++#include <sys/stat.h>
++
++#include <assert.h>
++#include <ctype.h>
++#include <errno.h>
++#include <signal.h>
++#include <stdlib.h>
++#include <unistd.h>
++
++#ifdef SETMODE_DEBUG
++#include <stdio.h>
++#endif
++
++#ifdef __weak_alias
++__weak_alias(getmode,_getmode)
++__weak_alias(setmode,_setmode)
++#endif
++
++#ifdef __GLIBC__
++#define S_ISTXT __S_ISVTX
++#endif
++
++#define SET_LEN 6 /* initial # of bitcmd struct to malloc */
++#define SET_LEN_INCR 4 /* # of bitcmd structs to add as needed */
++
++typedef struct bitcmd {
++ char cmd;
++ char cmd2;
++ mode_t bits;
++} BITCMD;
++
++#define CMD2_CLR 0x01
++#define CMD2_SET 0x02
++#define CMD2_GBITS 0x04
++#define CMD2_OBITS 0x08
++#define CMD2_UBITS 0x10
++
++static BITCMD *addcmd __P((BITCMD *, int, int, int, u_int));
++static void compress_mode __P((BITCMD *));
++#ifdef SETMODE_DEBUG
++static void dumpmode __P((BITCMD *));
++#endif
++
++/*
++ * Given the old mode and an array of bitcmd structures, apply the operations
++ * described in the bitcmd structures to the old mode, and return the new mode.
++ * Note that there is no '=' command; a strict assignment is just a '-' (clear
++ * bits) followed by a '+' (set bits).
++ */
++mode_t
++getmode(bbox, omode)
++ const void *bbox;
++ mode_t omode;
++{
++ const BITCMD *set;
++ mode_t clrval, newmode, value;
++
++ _DIAGASSERT(bbox != NULL);
++
++ set = (const BITCMD *)bbox;
++ newmode = omode;
++ for (value = 0;; set++)
++ switch(set->cmd) {
++ /*
++ * When copying the user, group or other bits around, we "know"
++ * where the bits are in the mode so that we can do shifts to
++ * copy them around. If we don't use shifts, it gets real
++ * grundgy with lots of single bit checks and bit sets.
++ */
++ case 'u':
++ value = (newmode & S_IRWXU) >> 6;
++ goto common;
++
++ case 'g':
++ value = (newmode & S_IRWXG) >> 3;
++ goto common;
++
++ case 'o':
++ value = newmode & S_IRWXO;
++common: if (set->cmd2 & CMD2_CLR) {
++ clrval =
++ (set->cmd2 & CMD2_SET) ? S_IRWXO : value;
++ if (set->cmd2 & CMD2_UBITS)
++ newmode &= ~((clrval<<6) & set->bits);
++ if (set->cmd2 & CMD2_GBITS)
++ newmode &= ~((clrval<<3) & set->bits);
++ if (set->cmd2 & CMD2_OBITS)
++ newmode &= ~(clrval & set->bits);
++ }
++ if (set->cmd2 & CMD2_SET) {
++ if (set->cmd2 & CMD2_UBITS)
++ newmode |= (value<<6) & set->bits;
++ if (set->cmd2 & CMD2_GBITS)
++ newmode |= (value<<3) & set->bits;
++ if (set->cmd2 & CMD2_OBITS)
++ newmode |= value & set->bits;
++ }
++ break;
++
++ case '+':
++ newmode |= set->bits;
++ break;
++
++ case '-':
++ newmode &= ~set->bits;
++ break;
++
++ case 'X':
++ if (omode & (S_IFDIR|S_IXUSR|S_IXGRP|S_IXOTH))
++ newmode |= set->bits;
++ break;
++
++ case '\0':
++ default:
++#ifdef SETMODE_DEBUG
++ (void)printf("getmode:%04o -> %04o\n", omode, newmode);
++#endif
++ return (newmode);
++ }
++}
++
++#define ADDCMD(a, b, c, d) do { \
++ if (set >= endset) { \
++ BITCMD *newset; \
++ setlen += SET_LEN_INCR; \
++ newset = realloc(saveset, sizeof(BITCMD) * setlen); \
++ if (newset == NULL) { \
++ free(saveset); \
++ return (NULL); \
++ } \
++ set = newset + (set - saveset); \
++ saveset = newset; \
++ endset = newset + (setlen - 2); \
++ } \
++ set = addcmd(set, (a), (b), (c), (d)); \
++} while (/*CONSTCOND*/0)
++
++#define STANDARD_BITS (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO)
++
++void *
++setmode(p)
++ const char *p;
++{
++ int perm, who;
++ char op, *ep;
++ BITCMD *set, *saveset, *endset;
++ sigset_t sigset, sigoset;
++ mode_t mask;
++ int equalopdone = 0; /* pacify gcc */
++ int permXbits, setlen;
++
++ if (!*p)
++ return (NULL);
++
++ /*
++ * Get a copy of the mask for the permissions that are mask relative.
++ * Flip the bits, we want what's not set. Since it's possible that
++ * the caller is opening files inside a signal handler, protect them
++ * as best we can.
++ */
++ sigfillset(&sigset);
++ (void)sigprocmask(SIG_BLOCK, &sigset, &sigoset);
++ (void)umask(mask = umask(0));
++ mask = ~mask;
++ (void)sigprocmask(SIG_SETMASK, &sigoset, NULL);
++
++ setlen = SET_LEN + 2;
++
++ if ((set = malloc((u_int)(sizeof(BITCMD) * setlen))) == NULL)
++ return (NULL);
++ saveset = set;
++ endset = set + (setlen - 2);
++
++ /*
++ * If an absolute number, get it and return; disallow non-octal digits
++ * or illegal bits.
++ */
++ if (isdigit((unsigned char)*p)) {
++ perm = (mode_t)strtol(p, &ep, 8);
++ if (*ep || perm & ~(STANDARD_BITS|S_ISTXT)) {
++ free(saveset);
++ return (NULL);
++ }
++ ADDCMD('=', (STANDARD_BITS|S_ISTXT), perm, mask);
++ set->cmd = 0;
++ return (saveset);
++ }
++
++ /*
++ * Build list of structures to set/clear/copy bits as described by
++ * each clause of the symbolic mode.
++ */
++ for (;;) {
++ /* First, find out which bits might be modified. */
++ for (who = 0;; ++p) {
++ switch (*p) {
++ case 'a':
++ who |= STANDARD_BITS;
++ break;
++ case 'u':
++ who |= S_ISUID|S_IRWXU;
++ break;
++ case 'g':
++ who |= S_ISGID|S_IRWXG;
++ break;
++ case 'o':
++ who |= S_IRWXO;
++ break;
++ default:
++ goto getop;
++ }
++ }
++
++getop: if ((op = *p++) != '+' && op != '-' && op != '=') {
++ free(saveset);
++ return (NULL);
++ }
++ if (op == '=')
++ equalopdone = 0;
++
++ who &= ~S_ISTXT;
++ for (perm = 0, permXbits = 0;; ++p) {
++ switch (*p) {
++ case 'r':
++ perm |= S_IRUSR|S_IRGRP|S_IROTH;
++ break;
++ case 's':
++ /*
++ * If specific bits where requested and
++ * only "other" bits ignore set-id.
++ */
++ if (who == 0 || (who & ~S_IRWXO))
++ perm |= S_ISUID|S_ISGID;
++ break;
++ case 't':
++ /*
++ * If specific bits where requested and
++ * only "other" bits ignore set-id.
++ */
++ if (who == 0 || (who & ~S_IRWXO)) {
++ who |= S_ISTXT;
++ perm |= S_ISTXT;
++ }
++ break;
++ case 'w':
++ perm |= S_IWUSR|S_IWGRP|S_IWOTH;
++ break;
++ case 'X':
++ permXbits = S_IXUSR|S_IXGRP|S_IXOTH;
++ break;
++ case 'x':
++ perm |= S_IXUSR|S_IXGRP|S_IXOTH;
++ break;
++ case 'u':
++ case 'g':
++ case 'o':
++ /*
++ * When ever we hit 'u', 'g', or 'o', we have
++ * to flush out any partial mode that we have,
++ * and then do the copying of the mode bits.
++ */
++ if (perm) {
++ ADDCMD(op, who, perm, mask);
++ perm = 0;
++ }
++ if (op == '=')
++ equalopdone = 1;
++ if (op == '+' && permXbits) {
++ ADDCMD('X', who, permXbits, mask);
++ permXbits = 0;
++ }
++ ADDCMD(*p, who, op, mask);
++ break;
++
++ default:
++ /*
++ * Add any permissions that we haven't already
++ * done.
++ */
++ if (perm || (op == '=' && !equalopdone)) {
++ if (op == '=')
++ equalopdone = 1;
++ ADDCMD(op, who, perm, mask);
++ perm = 0;
++ }
++ if (permXbits) {
++ ADDCMD('X', who, permXbits, mask);
++ permXbits = 0;
++ }
++ goto apply;
++ }
++ }
++
++apply: if (!*p)
++ break;
++ if (*p != ',')
++ goto getop;
++ ++p;
++ }
++ set->cmd = 0;
++#ifdef SETMODE_DEBUG
++ (void)printf("Before compress_mode()\n");
++ dumpmode(saveset);
++#endif
++ compress_mode(saveset);
++#ifdef SETMODE_DEBUG
++ (void)printf("After compress_mode()\n");
++ dumpmode(saveset);
++#endif
++ return (saveset);
++}
++
++static BITCMD *
++addcmd(set, op, who, oparg, mask)
++ BITCMD *set;
++ int oparg, who;
++ int op;
++ u_int mask;
++{
++
++ _DIAGASSERT(set != NULL);
++
++ switch (op) {
++ case '=':
++ set->cmd = '-';
++ set->bits = who ? who : STANDARD_BITS;
++ set++;
++
++ op = '+';
++ /* FALLTHROUGH */
++ case '+':
++ case '-':
++ case 'X':
++ set->cmd = op;
++ set->bits = (who ? who : mask) & oparg;
++ break;
++
++ case 'u':
++ case 'g':
++ case 'o':
++ set->cmd = op;
++ if (who) {
++ set->cmd2 = ((who & S_IRUSR) ? CMD2_UBITS : 0) |
++ ((who & S_IRGRP) ? CMD2_GBITS : 0) |
++ ((who & S_IROTH) ? CMD2_OBITS : 0);
++ set->bits = (mode_t)~0;
++ } else {
++ set->cmd2 = CMD2_UBITS | CMD2_GBITS | CMD2_OBITS;
++ set->bits = mask;
++ }
++
++ if (oparg == '+')
++ set->cmd2 |= CMD2_SET;
++ else if (oparg == '-')
++ set->cmd2 |= CMD2_CLR;
++ else if (oparg == '=')
++ set->cmd2 |= CMD2_SET|CMD2_CLR;
++ break;
++ }
++ return (set + 1);
++}
++
++#ifdef SETMODE_DEBUG
++static void
++dumpmode(set)
++ BITCMD *set;
++{
++
++ _DIAGASSERT(set != NULL);
++
++ for (; set->cmd; ++set)
++ (void)printf("cmd: '%c' bits %04o%s%s%s%s%s%s\n",
++ set->cmd, set->bits, set->cmd2 ? " cmd2:" : "",
++ set->cmd2 & CMD2_CLR ? " CLR" : "",
++ set->cmd2 & CMD2_SET ? " SET" : "",
++ set->cmd2 & CMD2_UBITS ? " UBITS" : "",
++ set->cmd2 & CMD2_GBITS ? " GBITS" : "",
++ set->cmd2 & CMD2_OBITS ? " OBITS" : "");
++}
++#endif
++
++/*
++ * Given an array of bitcmd structures, compress by compacting consecutive
++ * '+', '-' and 'X' commands into at most 3 commands, one of each. The 'u',
++ * 'g' and 'o' commands continue to be separate. They could probably be
++ * compacted, but it's not worth the effort.
++ */
++static void
++compress_mode(set)
++ BITCMD *set;
++{
++ BITCMD *nset;
++ int setbits, clrbits, Xbits, op;
++
++ _DIAGASSERT(set != NULL);
++
++ for (nset = set;;) {
++ /* Copy over any 'u', 'g' and 'o' commands. */
++ while ((op = nset->cmd) != '+' && op != '-' && op != 'X') {
++ *set++ = *nset++;
++ if (!op)
++ return;
++ }
++
++ for (setbits = clrbits = Xbits = 0;; nset++) {
++ if ((op = nset->cmd) == '-') {
++ clrbits |= nset->bits;
++ setbits &= ~nset->bits;
++ Xbits &= ~nset->bits;
++ } else if (op == '+') {
++ setbits |= nset->bits;
++ clrbits &= ~nset->bits;
++ Xbits &= ~nset->bits;
++ } else if (op == 'X')
++ Xbits |= nset->bits & ~setbits;
++ else
++ break;
++ }
++ if (clrbits) {
++ set->cmd = '-';
++ set->cmd2 = 0;
++ set->bits = clrbits;
++ set++;
++ }
++ if (setbits) {
++ set->cmd = '+';
++ set->cmd2 = 0;
++ set->bits = setbits;
++ set++;
++ }
++ if (Xbits) {
++ set->cmd = 'X';
++ set->cmd2 = 0;
++ set->bits = Xbits;
++ set++;
++ }
++ }
++}
+