1/* vi: set sw=4 ts=4: */ 2/* 3 * Utility routines. 4 * 5 * Copyright (C) tons of folks. Tracking down who wrote what 6 * isn't something I'm going to worry about... If you wrote something 7 * here, please feel free to acknowledge your work. 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 2 of the License, or 12 * (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 * General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 * 23 * Based in part on code from sash, Copyright (c) 1999 by David I. Bell 24 * Permission has been granted to redistribute this code under the GPL. 25 * 26 */ 27 28#include <stdio.h> 29#include <stdlib.h> 30#include "libbb.h" 31 32 33/* This function parses the sort of string you might pass 34 * to chmod (i.e., [ugoa]{+|-|=}[rwxst] ) and returns the 35 * correct mode described by the string. */ 36extern int parse_mode(const char *s, mode_t * theMode) 37{ 38 static const mode_t group_set[] = { 39 S_ISUID | S_IRWXU, /* u */ 40 S_ISGID | S_IRWXG, /* g */ 41 S_IRWXO, /* o */ 42 S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO /* a */ 43 }; 44 45 static const mode_t mode_set[] = { 46 S_IRUSR | S_IRGRP | S_IROTH, /* r */ 47 S_IWUSR | S_IWGRP | S_IWOTH, /* w */ 48 S_IXUSR | S_IXGRP | S_IXOTH, /* x */ 49 S_ISUID | S_ISGID, /* s */ 50 S_ISVTX /* t */ 51 }; 52 53 static const char group_chars[] = "ugoa"; 54 static const char mode_chars[] = "rwxst"; 55 56 const char *p; 57 58 mode_t andMode = 59 S_ISVTX | S_ISUID | S_ISGID | S_IRWXU | S_IRWXG | S_IRWXO; 60 mode_t orMode = 0; 61 mode_t mode; 62 mode_t groups; 63 char type; 64 char c; 65 66 if (s==NULL) { 67 return (FALSE); 68 } 69 70 do { 71 mode = 0; 72 groups = 0; 73 NEXT_GROUP: 74 if ((c = *s++) == '\0') { 75 return -1; 76 } 77 for (p=group_chars ; *p ; p++) { 78 if (*p == c) { 79 groups |= group_set[(int)(p-group_chars)]; 80 goto NEXT_GROUP; 81 } 82 } 83 switch (c) { 84 case '=': 85 case '+': 86 case '-': 87 type = c; 88 if (groups == 0) { /* The default is "all" */ 89 groups |= S_ISUID | S_ISGID | S_ISVTX 90 | S_IRWXU | S_IRWXG | S_IRWXO; 91 } 92 break; 93 default: 94 if ((c < '0') || (c > '7') || (mode | groups)) { 95 return (FALSE); 96 } else { 97 *theMode = strtol(--s, NULL, 8); 98 return (TRUE); 99 } 100 } 101 102 NEXT_MODE: 103 if (((c = *s++) != '\0') && (c != ',')) { 104 for (p=mode_chars ; *p ; p++) { 105 if (*p == c) { 106 mode |= mode_set[(int)(p-mode_chars)]; 107 goto NEXT_MODE; 108 } 109 } 110 break; /* We're done so break out of loop.*/ 111 } 112 switch (type) { 113 case '=': 114 andMode &= ~(groups); /* Now fall through. */ 115 case '+': 116 orMode |= mode & groups; 117 break; 118 case '-': 119 andMode &= ~(mode & groups); 120 orMode &= ~(mode & groups); 121 break; 122 } 123 } while (c == ','); 124 125 *theMode &= andMode; 126 *theMode |= orMode; 127 128 return TRUE; 129} 130 131/* END CODE */ 132/* 133Local Variables: 134c-file-style: "linux" 135c-basic-offset: 4 136tab-width: 4 137End: 138*/ 139