]>
Commit | Line | Data |
---|---|---|
726f6388 JA |
1 | This file is umask.def, from which is created umask.c. |
2 | It implements the builtin "umask" in Bash. | |
3 | ||
4 | Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc. | |
5 | ||
6 | This file is part of GNU Bash, the Bourne Again SHell. | |
7 | ||
8 | Bash is free software; you can redistribute it and/or modify it under | |
9 | the terms of the GNU General Public License as published by the Free | |
bb70624e | 10 | Software Foundation; either version 2, or (at your option) any later |
726f6388 JA |
11 | version. |
12 | ||
13 | Bash is distributed in the hope that it will be useful, but WITHOUT ANY | |
14 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
15 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
16 | for more details. | |
17 | ||
18 | You should have received a copy of the GNU General Public License along | |
19 | with Bash; see the file COPYING. If not, write to the Free Software | |
bb70624e | 20 | Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. |
726f6388 JA |
21 | |
22 | $PRODUCES umask.c | |
23 | ||
24 | $BUILTIN umask | |
25 | $FUNCTION umask_builtin | |
cce855bc | 26 | $SHORT_DOC umask [-p] [-S] [mode] |
726f6388 JA |
27 | The user file-creation mask is set to MODE. If MODE is omitted, or if |
28 | `-S' is supplied, the current value of the mask is printed. The `-S' | |
29 | option makes the output symbolic; otherwise an octal number is output. | |
cce855bc JA |
30 | If `-p' is supplied, and MODE is omitted, the output is in a form |
31 | that may be used as input. If MODE begins with a digit, it is | |
32 | interpreted as an octal number, otherwise it is a symbolic mode string | |
33 | like that accepted by chmod(1). | |
726f6388 JA |
34 | $END |
35 | ||
ccc6cda3 JA |
36 | #include <config.h> |
37 | ||
38 | #include "../bashtypes.h" | |
bb70624e | 39 | #include "filecntl.h" |
cce855bc JA |
40 | #ifndef _MINIX |
41 | # include <sys/file.h> | |
42 | #endif | |
ccc6cda3 JA |
43 | |
44 | #if defined (HAVE_UNISTD_H) | |
45 | #include <unistd.h> | |
46 | #endif | |
47 | ||
48 | #include <stdio.h> | |
49 | ||
726f6388 | 50 | #include "../shell.h" |
bb70624e | 51 | #include "posixstat.h" |
726f6388 | 52 | #include "common.h" |
ccc6cda3 | 53 | #include "bashgetopt.h" |
726f6388 JA |
54 | |
55 | /* **************************************************************** */ | |
56 | /* */ | |
57 | /* UMASK Builtin and Helpers */ | |
58 | /* */ | |
59 | /* **************************************************************** */ | |
60 | ||
61 | static void print_symbolic_umask (); | |
62 | static int symbolic_umask (); | |
63 | ||
64 | /* Set or display the mask used by the system when creating files. Flag | |
65 | of -S means display the umask in a symbolic mode. */ | |
ccc6cda3 | 66 | int |
726f6388 JA |
67 | umask_builtin (list) |
68 | WORD_LIST *list; | |
69 | { | |
cce855bc | 70 | int print_symbolically, opt, umask_value, pflag; |
d166f048 | 71 | mode_t umask_arg; |
726f6388 | 72 | |
cce855bc | 73 | print_symbolically = pflag = 0; |
ccc6cda3 | 74 | reset_internal_getopt (); |
cce855bc | 75 | while ((opt = internal_getopt (list, "Sp")) != -1) |
726f6388 | 76 | { |
ccc6cda3 | 77 | switch (opt) |
726f6388 | 78 | { |
ccc6cda3 | 79 | case 'S': |
726f6388 | 80 | print_symbolically++; |
726f6388 | 81 | break; |
cce855bc JA |
82 | case 'p': |
83 | pflag++; | |
84 | break; | |
ccc6cda3 JA |
85 | default: |
86 | builtin_usage (); | |
726f6388 JA |
87 | return (EX_USAGE); |
88 | } | |
726f6388 JA |
89 | } |
90 | ||
ccc6cda3 JA |
91 | list = loptend; |
92 | ||
726f6388 JA |
93 | if (list) |
94 | { | |
726f6388 JA |
95 | if (digit (*list->word->word)) |
96 | { | |
ccc6cda3 | 97 | umask_value = read_octal (list->word->word); |
726f6388 JA |
98 | |
99 | /* Note that other shells just let you set the umask to zero | |
100 | by specifying a number out of range. This is a problem | |
101 | with those shells. We don't change the umask if the input | |
102 | is lousy. */ | |
ccc6cda3 | 103 | if (umask_value == -1) |
726f6388 JA |
104 | { |
105 | builtin_error ("`%s' is not an octal number from 000 to 777", | |
106 | list->word->word); | |
107 | return (EXECUTION_FAILURE); | |
108 | } | |
109 | } | |
110 | else | |
111 | { | |
ccc6cda3 JA |
112 | umask_value = symbolic_umask (list); |
113 | if (umask_value == -1) | |
726f6388 JA |
114 | return (EXECUTION_FAILURE); |
115 | } | |
d166f048 JA |
116 | umask_arg = (mode_t)umask_value; |
117 | umask (umask_arg); | |
726f6388 | 118 | if (print_symbolically) |
d166f048 | 119 | print_symbolic_umask (umask_arg); |
726f6388 JA |
120 | } |
121 | else /* Display the UMASK for this user. */ | |
122 | { | |
d166f048 JA |
123 | umask_arg = umask (022); |
124 | umask (umask_arg); | |
726f6388 | 125 | |
cce855bc JA |
126 | if (pflag) |
127 | printf ("umask%s ", (print_symbolically ? " -S" : "")); | |
726f6388 | 128 | if (print_symbolically) |
d166f048 | 129 | print_symbolic_umask (umask_arg); |
726f6388 | 130 | else |
d166f048 | 131 | printf ("%03o\n", umask_arg); |
726f6388 | 132 | } |
ccc6cda3 | 133 | |
726f6388 JA |
134 | fflush (stdout); |
135 | return (EXECUTION_SUCCESS); | |
136 | } | |
137 | ||
138 | /* Print the umask in a symbolic form. In the output, a letter is | |
139 | printed if the corresponding bit is clear in the umask. */ | |
140 | static void | |
141 | print_symbolic_umask (um) | |
d166f048 | 142 | mode_t um; |
726f6388 JA |
143 | { |
144 | char ubits[4], gbits[4], obits[4]; /* u=rwx,g=rwx,o=rwx */ | |
145 | int i; | |
146 | ||
147 | i = 0; | |
148 | if ((um & S_IRUSR) == 0) | |
149 | ubits[i++] = 'r'; | |
150 | if ((um & S_IWUSR) == 0) | |
151 | ubits[i++] = 'w'; | |
152 | if ((um & S_IXUSR) == 0) | |
153 | ubits[i++] = 'x'; | |
154 | ubits[i] = '\0'; | |
155 | ||
156 | i = 0; | |
157 | if ((um & S_IRGRP) == 0) | |
158 | gbits[i++] = 'r'; | |
159 | if ((um & S_IWGRP) == 0) | |
160 | gbits[i++] = 'w'; | |
161 | if ((um & S_IXGRP) == 0) | |
162 | gbits[i++] = 'x'; | |
163 | gbits[i] = '\0'; | |
164 | ||
165 | i = 0; | |
166 | if ((um & S_IROTH) == 0) | |
167 | obits[i++] = 'r'; | |
168 | if ((um & S_IWOTH) == 0) | |
169 | obits[i++] = 'w'; | |
170 | if ((um & S_IXOTH) == 0) | |
171 | obits[i++] = 'x'; | |
172 | obits[i] = '\0'; | |
173 | ||
174 | printf ("u=%s,g=%s,o=%s\n", ubits, gbits, obits); | |
175 | } | |
176 | ||
b72432fd JA |
177 | int |
178 | parse_symbolic_mode (mode, initial_bits) | |
179 | char *mode; | |
180 | int initial_bits; | |
726f6388 | 181 | { |
b72432fd | 182 | int who, op, perm, mask, bits, c; |
726f6388 JA |
183 | char *s; |
184 | ||
b72432fd | 185 | for (s = mode, bits = initial_bits;;) |
726f6388 JA |
186 | { |
187 | who = op = perm = mask = 0; | |
188 | ||
189 | /* Parse the `who' portion of the symbolic mode clause. */ | |
190 | while (member (*s, "agou")) | |
28ef6c31 | 191 | { |
726f6388 JA |
192 | switch (c = *s++) |
193 | { | |
b72432fd JA |
194 | case 'u': |
195 | who |= S_IRWXU; | |
196 | continue; | |
197 | case 'g': | |
198 | who |= S_IRWXG; | |
199 | continue; | |
200 | case 'o': | |
201 | who |= S_IRWXO; | |
202 | continue; | |
203 | case 'a': | |
204 | who |= S_IRWXU | S_IRWXG | S_IRWXO; | |
205 | continue; | |
206 | default: | |
207 | break; | |
726f6388 JA |
208 | } |
209 | } | |
210 | ||
211 | /* The operation is now sitting in *s. */ | |
212 | op = *s++; | |
213 | switch (op) | |
214 | { | |
b72432fd JA |
215 | case '+': |
216 | case '-': | |
217 | case '=': | |
218 | break; | |
219 | default: | |
220 | builtin_error ("bad symbolic mode operator: %c", op); | |
221 | return (-1); | |
726f6388 JA |
222 | } |
223 | ||
224 | /* Parse out the `perm' section of the symbolic mode clause. */ | |
225 | while (member (*s, "rwx")) | |
226 | { | |
227 | c = *s++; | |
228 | ||
229 | switch (c) | |
230 | { | |
b72432fd JA |
231 | case 'r': |
232 | perm |= S_IRUGO; | |
233 | break; | |
234 | case 'w': | |
235 | perm |= S_IWUGO; | |
236 | break; | |
237 | case 'x': | |
238 | perm |= S_IXUGO; | |
239 | break; | |
726f6388 JA |
240 | } |
241 | } | |
242 | ||
243 | /* Now perform the operation or return an error for a | |
244 | bad permission string. */ | |
245 | if (!*s || *s == ',') | |
246 | { | |
247 | if (who) | |
248 | perm &= who; | |
249 | ||
250 | switch (op) | |
251 | { | |
b72432fd JA |
252 | case '+': |
253 | bits |= perm; | |
254 | break; | |
255 | case '-': | |
256 | bits &= ~perm; | |
726f6388 | 257 | break; |
b72432fd JA |
258 | case '=': |
259 | bits &= ~who; | |
260 | bits |= perm; | |
261 | break; | |
262 | ||
263 | /* No other values are possible. */ | |
726f6388 | 264 | } |
b72432fd JA |
265 | |
266 | if (*s == '\0') | |
267 | break; | |
726f6388 JA |
268 | else |
269 | s++; /* skip past ',' */ | |
270 | } | |
271 | else | |
272 | { | |
273 | builtin_error ("bad character in symbolic mode: %c", *s); | |
274 | return (-1); | |
275 | } | |
276 | } | |
b72432fd JA |
277 | |
278 | return (bits); | |
279 | } | |
280 | ||
281 | /* Set the umask from a symbolic mode string similar to that accepted | |
282 | by chmod. If the -S argument is given, then print the umask in a | |
283 | symbolic form. */ | |
284 | static int | |
285 | symbolic_umask (list) | |
286 | WORD_LIST *list; | |
287 | { | |
288 | int um, bits; | |
289 | ||
290 | /* Get the initial umask. Don't change it yet. */ | |
291 | um = umask (022); | |
292 | umask (um); | |
293 | ||
294 | /* All work is done with the complement of the umask -- it's | |
295 | more intuitive and easier to deal with. It is complemented | |
296 | again before being returned. */ | |
297 | bits = parse_symbolic_mode (list->word->word, ~um); | |
bb70624e JA |
298 | if (bits == -1) |
299 | return (-1); | |
b72432fd JA |
300 | |
301 | um = ~bits & 0777; | |
726f6388 JA |
302 | return (um); |
303 | } |