]> git.ipfire.org Git - thirdparty/bash.git/blob - builtins/umask.def
Imported from ../bash-2.05.tar.gz.
[thirdparty/bash.git] / builtins / umask.def
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
10 Software Foundation; either version 2, or (at your option) any later
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
20 Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA.
21
22 $PRODUCES umask.c
23
24 $BUILTIN umask
25 $FUNCTION umask_builtin
26 $SHORT_DOC umask [-p] [-S] [mode]
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.
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).
34 $END
35
36 #include <config.h>
37
38 #include "../bashtypes.h"
39 #include "filecntl.h"
40 #ifndef _MINIX
41 # include <sys/file.h>
42 #endif
43
44 #if defined (HAVE_UNISTD_H)
45 #include <unistd.h>
46 #endif
47
48 #include <stdio.h>
49
50 #include "../shell.h"
51 #include "posixstat.h"
52 #include "common.h"
53 #include "bashgetopt.h"
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. */
66 int
67 umask_builtin (list)
68 WORD_LIST *list;
69 {
70 int print_symbolically, opt, umask_value, pflag;
71 mode_t umask_arg;
72
73 print_symbolically = pflag = 0;
74 reset_internal_getopt ();
75 while ((opt = internal_getopt (list, "Sp")) != -1)
76 {
77 switch (opt)
78 {
79 case 'S':
80 print_symbolically++;
81 break;
82 case 'p':
83 pflag++;
84 break;
85 default:
86 builtin_usage ();
87 return (EX_USAGE);
88 }
89 }
90
91 list = loptend;
92
93 if (list)
94 {
95 if (digit (*list->word->word))
96 {
97 umask_value = read_octal (list->word->word);
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. */
103 if (umask_value == -1)
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 {
112 umask_value = symbolic_umask (list);
113 if (umask_value == -1)
114 return (EXECUTION_FAILURE);
115 }
116 umask_arg = (mode_t)umask_value;
117 umask (umask_arg);
118 if (print_symbolically)
119 print_symbolic_umask (umask_arg);
120 }
121 else /* Display the UMASK for this user. */
122 {
123 umask_arg = umask (022);
124 umask (umask_arg);
125
126 if (pflag)
127 printf ("umask%s ", (print_symbolically ? " -S" : ""));
128 if (print_symbolically)
129 print_symbolic_umask (umask_arg);
130 else
131 printf ("%03o\n", umask_arg);
132 }
133
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)
142 mode_t um;
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 int
178 parse_symbolic_mode (mode, initial_bits)
179 char *mode;
180 int initial_bits;
181 {
182 int who, op, perm, mask, bits, c;
183 char *s;
184
185 for (s = mode, bits = initial_bits;;)
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 {
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;
208 }
209 }
210
211 /* The operation is now sitting in *s. */
212 op = *s++;
213 switch (op)
214 {
215 case '+':
216 case '-':
217 case '=':
218 break;
219 default:
220 builtin_error ("bad symbolic mode operator: %c", op);
221 return (-1);
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 {
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;
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 {
252 case '+':
253 bits |= perm;
254 break;
255 case '-':
256 bits &= ~perm;
257 break;
258 case '=':
259 bits &= ~who;
260 bits |= perm;
261 break;
262
263 /* No other values are possible. */
264 }
265
266 if (*s == '\0')
267 break;
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 }
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);
298 if (bits == -1)
299 return (-1);
300
301 um = ~bits & 0777;
302 return (um);
303 }