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