Added gitignore entries needed to ignore derived objects generated from full build...
[bash.git] / builtins / umask.def
blob289a0f548e74f244f9fc2b3c5acd1a5b4b92f5df
1 This file is umask.def, from which is created umask.c.
2 It implements the builtin "umask" in Bash.
4 Copyright (C) 1987-2009 Free Software Foundation, Inc.
6 This file is part of GNU Bash, the Bourne Again SHell.
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.
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.
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/>.
21 $PRODUCES umask.c
23 $BUILTIN umask
24 $FUNCTION umask_builtin
25 $SHORT_DOC umask [-p] [-S] [mode]
26 Display or set file mode mask.
28 Sets the user file-creation mask to MODE. If MODE is omitted, prints
29 the current value of the mask.
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).
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
38 Exit Status:
39 Returns success unless MODE is invalid or an invalid option is given.
40 $END
42 #include <config.h>
44 #include "../bashtypes.h"
45 #include "filecntl.h"
46 #if ! defined(_MINIX) && defined (HAVE_SYS_FILE_H)
47 # include <sys/file.h>
48 #endif
50 #if defined (HAVE_UNISTD_H)
51 #include <unistd.h>
52 #endif
54 #include <stdio.h>
55 #include <chartypes.h>
57 #include "../bashintl.h"
59 #include "../shell.h"
60 #include "posixstat.h"
61 #include "common.h"
62 #include "bashgetopt.h"
64 #ifdef __LCC__
65 #define mode_t int
66 #endif
68 /* **************************************************************** */
69 /* */
70 /* UMASK Builtin and Helpers */
71 /* */
72 /* **************************************************************** */
74 static void print_symbolic_umask __P((mode_t));
75 static int symbolic_umask __P((WORD_LIST *));
77 /* Set or display the mask used by the system when creating files. Flag
78 of -S means display the umask in a symbolic mode. */
79 int
80 umask_builtin (list)
81 WORD_LIST *list;
83 int print_symbolically, opt, umask_value, pflag;
84 mode_t umask_arg;
86 print_symbolically = pflag = 0;
87 reset_internal_getopt ();
88 while ((opt = internal_getopt (list, "Sp")) != -1)
90 switch (opt)
92 case 'S':
93 print_symbolically++;
94 break;
95 case 'p':
96 pflag++;
97 break;
98 default:
99 builtin_usage ();
100 return (EX_USAGE);
104 list = loptend;
106 if (list)
108 if (DIGIT (*list->word->word))
110 umask_value = read_octal (list->word->word);
112 /* Note that other shells just let you set the umask to zero
113 by specifying a number out of range. This is a problem
114 with those shells. We don't change the umask if the input
115 is lousy. */
116 if (umask_value == -1)
118 sh_erange (list->word->word, _("octal number"));
119 return (EXECUTION_FAILURE);
122 else
124 umask_value = symbolic_umask (list);
125 if (umask_value == -1)
126 return (EXECUTION_FAILURE);
128 umask_arg = (mode_t)umask_value;
129 umask (umask_arg);
130 if (print_symbolically)
131 print_symbolic_umask (umask_arg);
133 else /* Display the UMASK for this user. */
135 umask_arg = umask (022);
136 umask (umask_arg);
138 if (pflag)
139 printf ("umask%s ", (print_symbolically ? " -S" : ""));
140 if (print_symbolically)
141 print_symbolic_umask (umask_arg);
142 else
143 printf ("%04lo\n", (unsigned long)umask_arg);
146 return (sh_chkwrite (EXECUTION_SUCCESS));
149 /* Print the umask in a symbolic form. In the output, a letter is
150 printed if the corresponding bit is clear in the umask. */
151 static void
152 print_symbolic_umask (um)
153 mode_t um;
155 char ubits[4], gbits[4], obits[4]; /* u=rwx,g=rwx,o=rwx */
156 int i;
158 i = 0;
159 if ((um & S_IRUSR) == 0)
160 ubits[i++] = 'r';
161 if ((um & S_IWUSR) == 0)
162 ubits[i++] = 'w';
163 if ((um & S_IXUSR) == 0)
164 ubits[i++] = 'x';
165 ubits[i] = '\0';
167 i = 0;
168 if ((um & S_IRGRP) == 0)
169 gbits[i++] = 'r';
170 if ((um & S_IWGRP) == 0)
171 gbits[i++] = 'w';
172 if ((um & S_IXGRP) == 0)
173 gbits[i++] = 'x';
174 gbits[i] = '\0';
176 i = 0;
177 if ((um & S_IROTH) == 0)
178 obits[i++] = 'r';
179 if ((um & S_IWOTH) == 0)
180 obits[i++] = 'w';
181 if ((um & S_IXOTH) == 0)
182 obits[i++] = 'x';
183 obits[i] = '\0';
185 printf ("u=%s,g=%s,o=%s\n", ubits, gbits, obits);
189 parse_symbolic_mode (mode, initial_bits)
190 char *mode;
191 int initial_bits;
193 int who, op, perm, bits, c;
194 char *s;
196 for (s = mode, bits = initial_bits;;)
198 who = op = perm = 0;
200 /* Parse the `who' portion of the symbolic mode clause. */
201 while (member (*s, "agou"))
203 switch (c = *s++)
205 case 'u':
206 who |= S_IRWXU;
207 continue;
208 case 'g':
209 who |= S_IRWXG;
210 continue;
211 case 'o':
212 who |= S_IRWXO;
213 continue;
214 case 'a':
215 who |= S_IRWXU | S_IRWXG | S_IRWXO;
216 continue;
217 default:
218 break;
222 /* The operation is now sitting in *s. */
223 op = *s++;
224 switch (op)
226 case '+':
227 case '-':
228 case '=':
229 break;
230 default:
231 builtin_error (_("`%c': invalid symbolic mode operator"), op);
232 return (-1);
235 /* Parse out the `perm' section of the symbolic mode clause. */
236 while (member (*s, "rwx"))
238 c = *s++;
240 switch (c)
242 case 'r':
243 perm |= S_IRUGO;
244 break;
245 case 'w':
246 perm |= S_IWUGO;
247 break;
248 case 'x':
249 perm |= S_IXUGO;
250 break;
254 /* Now perform the operation or return an error for a
255 bad permission string. */
256 if (!*s || *s == ',')
258 if (who)
259 perm &= who;
261 switch (op)
263 case '+':
264 bits |= perm;
265 break;
266 case '-':
267 bits &= ~perm;
268 break;
269 case '=':
270 if (who == 0)
271 who = S_IRWXU | S_IRWXG | S_IRWXO;
272 bits &= ~who;
273 bits |= perm;
274 break;
276 /* No other values are possible. */
279 if (*s == '\0')
280 break;
281 else
282 s++; /* skip past ',' */
284 else
286 builtin_error (_("`%c': invalid symbolic mode character"), *s);
287 return (-1);
291 return (bits);
294 /* Set the umask from a symbolic mode string similar to that accepted
295 by chmod. If the -S argument is given, then print the umask in a
296 symbolic form. */
297 static int
298 symbolic_umask (list)
299 WORD_LIST *list;
301 int um, bits;
303 /* Get the initial umask. Don't change it yet. */
304 um = umask (022);
305 umask (um);
307 /* All work is done with the complement of the umask -- it's
308 more intuitive and easier to deal with. It is complemented
309 again before being returned. */
310 bits = parse_symbolic_mode (list->word->word, ~um & 0777);
311 if (bits == -1)
312 return (-1);
314 um = ~bits & 0777;
315 return (um);