]> git.ipfire.org Git - thirdparty/bash.git/blame - builtins/umask.def
Imported from ../bash-2.03.tar.gz.
[thirdparty/bash.git] / builtins / umask.def
CommitLineData
726f6388
JA
1This file is umask.def, from which is created umask.c.
2It implements the builtin "umask" in Bash.
3
4Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
5
6This file is part of GNU Bash, the Bourne Again SHell.
7
8Bash is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
10Software Foundation; either version 1, or (at your option) any later
11version.
12
13Bash is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16for more details.
17
18You should have received a copy of the GNU General Public License along
19with Bash; see the file COPYING. If not, write to the Free Software
20Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
21
22$PRODUCES umask.c
23
24$BUILTIN umask
25$FUNCTION umask_builtin
cce855bc 26$SHORT_DOC umask [-p] [-S] [mode]
726f6388
JA
27The 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'
29option makes the output symbolic; otherwise an octal number is output.
cce855bc
JA
30If `-p' is supplied, and MODE is omitted, the output is in a form
31that may be used as input. If MODE begins with a digit, it is
32interpreted as an octal number, otherwise it is a symbolic mode string
33like that accepted by chmod(1).
726f6388
JA
34$END
35
ccc6cda3
JA
36#include <config.h>
37
38#include "../bashtypes.h"
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
JA
50#include "../shell.h"
51#include "../posixstat.h"
52#include "common.h"
ccc6cda3 53#include "bashgetopt.h"
726f6388
JA
54
55/* **************************************************************** */
56/* */
57/* UMASK Builtin and Helpers */
58/* */
59/* **************************************************************** */
60
61static void print_symbolic_umask ();
62static 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 66int
726f6388
JA
67umask_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. */
140static void
141print_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
177int
178parse_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"))
191 {
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. */
284static int
285symbolic_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);
298
299 um = ~bits & 0777;
726f6388
JA
300 return (um);
301}