]> git.ipfire.org Git - thirdparty/bash.git/blame - builtins/umask.def
Imported from ../bash-2.02.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
177/* Set the umask from a symbolic mode string similar to that accepted
178 by chmod. If the -S argument is given, then print the umask in a
179 symbolic form. */
180static int
181symbolic_umask (list)
182 WORD_LIST *list;
183{
184 int um, umc, c;
185 int who, op, perm, mask;
186 char *s;
187
188 /* Get the initial umask. Don't change it yet. */
189 um = umask (022);
190 umask (um);
191
ccc6cda3 192 /* All work below is done with the complement of the umask -- it's
726f6388
JA
193 more intuitive and easier to deal with. It is complemented
194 again before being returned. */
195 umc = ~um;
196
197 s = list->word->word;
198
199 for (;;)
200 {
201 who = op = perm = mask = 0;
202
203 /* Parse the `who' portion of the symbolic mode clause. */
204 while (member (*s, "agou"))
205 {
206 switch (c = *s++)
207 {
208 case 'u':
209 who |= S_IRWXU;
210 continue;
211 case 'g':
212 who |= S_IRWXG;
213 continue;
214 case 'o':
215 who |= S_IRWXO;
216 continue;
217 case 'a':
218 who |= S_IRWXU | S_IRWXG | S_IRWXO;
219 continue;
220 default:
221 break;
222 }
223 }
224
225 /* The operation is now sitting in *s. */
226 op = *s++;
227 switch (op)
228 {
229 case '+':
230 case '-':
231 case '=':
232 break;
233 default:
234 builtin_error ("bad symbolic mode operator: %c", op);
235 return (-1);
236 }
237
238 /* Parse out the `perm' section of the symbolic mode clause. */
239 while (member (*s, "rwx"))
240 {
241 c = *s++;
242
243 switch (c)
244 {
245 case 'r':
246 perm |= S_IRUGO;
247 break;
248
249 case 'w':
250 perm |= S_IWUGO;
251 break;
252
253 case 'x':
254 perm |= S_IXUGO;
255 break;
256 }
257 }
258
259 /* Now perform the operation or return an error for a
260 bad permission string. */
261 if (!*s || *s == ',')
262 {
263 if (who)
264 perm &= who;
265
266 switch (op)
267 {
268 case '+':
269 umc |= perm;
270 break;
271
272 case '-':
273 umc &= ~perm;
274 break;
275
276 case '=':
277 umc &= ~who;
278 umc |= perm;
279 break;
280
d166f048
JA
281#if 0
282 /* No other values are possible. */
726f6388 283 default:
ccc6cda3 284 builtin_error ("bad symbolic mode operator: %c", op);
726f6388 285 return (-1);
d166f048 286#endif
726f6388
JA
287 }
288
289 if (!*s)
290 {
291 um = ~umc & 0777;
292 break;
293 }
294 else
295 s++; /* skip past ',' */
296 }
297 else
298 {
299 builtin_error ("bad character in symbolic mode: %c", *s);
300 return (-1);
301 }
302 }
303 return (um);
304}