]> git.ipfire.org Git - thirdparty/bash.git/blobdiff - builtins/umask.def
Imported from ../bash-2.05.tar.gz.
[thirdparty/bash.git] / builtins / umask.def
index 1d84aa9a4d1a8fa1c334e4943bd3b475b0578963..1c1591e05def7b2fa76497df800babaccbaaf8f7 100644 (file)
@@ -7,7 +7,7 @@ This file is part of GNU Bash, the Bourne Again SHell.
 
 Bash is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 1, or (at your option) any later
+Software Foundation; either version 2, or (at your option) any later
 version.
 
 Bash is distributed in the hope that it will be useful, but WITHOUT ANY
@@ -17,26 +17,40 @@ for more details.
 
 You should have received a copy of the GNU General Public License along
 with Bash; see the file COPYING.  If not, write to the Free Software
-Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA.
 
 $PRODUCES umask.c
 
 $BUILTIN umask
 $FUNCTION umask_builtin
-$SHORT_DOC umask [-S] [mode]
+$SHORT_DOC umask [-p] [-S] [mode]
 The user file-creation mask is set to MODE.  If MODE is omitted, or if
 `-S' is supplied, the current value of the mask is printed.  The `-S'
 option makes the output symbolic; otherwise an octal number is output.
-If MODE begins with a digit, it is interpreted as an octal number,
-otherwise it is a symbolic mode string like that accepted by chmod(1).
+If `-p' is supplied, and MODE is omitted, the output is in a form
+that may be used as input.  If MODE begins with a digit, it is
+interpreted as an octal number, otherwise it is a symbolic mode string
+like that accepted by chmod(1).
 $END
 
+#include <config.h>
+
+#include "../bashtypes.h"
+#include "filecntl.h"
+#ifndef _MINIX
+#  include <sys/file.h>
+#endif
+
+#if defined (HAVE_UNISTD_H)
+#include <unistd.h>
+#endif
+
 #include <stdio.h>
-#include <sys/types.h>
-#include <sys/file.h>
+
 #include "../shell.h"
-#include "../posixstat.h"
+#include "posixstat.h"
 #include "common.h"
+#include "bashgetopt.h"
 
 /* **************************************************************** */
 /*                                                                  */
@@ -49,47 +63,44 @@ static int symbolic_umask ();
 
 /* Set or display the mask used by the system when creating files.  Flag
    of -S means display the umask in a symbolic mode. */
+int
 umask_builtin (list)
      WORD_LIST *list;
 {
-  int print_symbolically = 0;
+  int print_symbolically, opt, umask_value, pflag;
+  mode_t umask_arg;
 
-  while (list)
+  print_symbolically = pflag = 0;
+  reset_internal_getopt ();
+  while ((opt = internal_getopt (list, "Sp")) != -1)
     {
-      if (ISOPTION (list->word->word, 'S'))
+      switch (opt)
        {
-         list = list->next;
+       case 'S':
          print_symbolically++;
-         continue;
-       }
-      else if (ISOPTION (list->word->word, '-'))
-       {
-         list = list->next;
          break;
-       }
-      else if (*(list->word->word) == '-')
-       {
-         bad_option (list->word->word);
-         builtin_error ("usage: umask [-S] [mode]");
+       case 'p':
+         pflag++;
+         break;
+       default:
+         builtin_usage ();
          return (EX_USAGE);
        }
-      else
-       break;
     }
 
+  list = loptend;
+
   if (list)
     {
-      int new_umask;
-
       if (digit (*list->word->word))
        {
-         new_umask = read_octal (list->word->word);
+         umask_value = read_octal (list->word->word);
 
          /* Note that other shells just let you set the umask to zero
             by specifying a number out of range.  This is a problem
             with those shells.  We don't change the umask if the input
             is lousy. */
-         if (new_umask == -1)
+         if (umask_value == -1)
            {
              builtin_error ("`%s' is not an octal number from 000 to 777",
                                list->word->word);
@@ -98,26 +109,28 @@ umask_builtin (list)
        }
       else
        {
-         new_umask = symbolic_umask (list);
-         if (new_umask == -1)
+         umask_value = symbolic_umask (list);
+         if (umask_value == -1)
            return (EXECUTION_FAILURE);
        }
-      umask (new_umask);
+      umask_arg = (mode_t)umask_value;
+      umask (umask_arg);
       if (print_symbolically)
-       print_symbolic_umask (new_umask);
+       print_symbolic_umask (umask_arg);
     }
   else                         /* Display the UMASK for this user. */
     {
-      int old_umask;
-
-      old_umask = umask (022);
-      umask (old_umask);
+      umask_arg = umask (022);
+      umask (umask_arg);
 
+      if (pflag)
+       printf ("umask%s ", (print_symbolically ? " -S" : ""));
       if (print_symbolically)
-       print_symbolic_umask (old_umask);
+       print_symbolic_umask (umask_arg);
       else
-       printf ("%03o\n", old_umask);
+       printf ("%03o\n", umask_arg);
     }
+
   fflush (stdout);
   return (EXECUTION_SUCCESS);
 }
@@ -126,7 +139,7 @@ umask_builtin (list)
    printed if the corresponding bit is clear in the umask. */
 static void
 print_symbolic_umask (um)
-     int um;
+     mode_t um;
 {
   char ubits[4], gbits[4], obits[4];           /* u=rwx,g=rwx,o=rwx */
   int i;
@@ -161,51 +174,37 @@ print_symbolic_umask (um)
   printf ("u=%s,g=%s,o=%s\n", ubits, gbits, obits);
 }
 
-/* Set the umask from a symbolic mode string similar to that accepted
-   by chmod.  If the -S argument is given, then print the umask in a
-   symbolic form. */
-static int
-symbolic_umask (list)
-     WORD_LIST *list;
+int
+parse_symbolic_mode (mode, initial_bits)
+     char *mode;
+     int initial_bits;
 {
-  int um, umc, c;
-  int who, op, perm, mask;
+  int who, op, perm, mask, bits, c;
   char *s;
 
-  /* Get the initial umask.  Don't change it yet. */
-  um = umask (022);
-  umask (um);
-
-  /* All work below is done with the complement of the umask -- its
-     more intuitive and easier to deal with.  It is complemented
-     again before being returned. */
-  umc = ~um;
-
-  s = list->word->word;
-
-  for (;;)
+  for (s = mode, bits = initial_bits;;)
     {
       who = op = perm = mask = 0;
 
       /* Parse the `who' portion of the symbolic mode clause. */
       while (member (*s, "agou"))
-        {
+       {
          switch (c = *s++)
            {
-             case 'u':
-               who |= S_IRWXU;
-               continue;
-             case 'g':
-               who |= S_IRWXG;
-               continue;
-             case 'o':
-               who |= S_IRWXO;
-               continue;
-             case 'a':
-               who |= S_IRWXU | S_IRWXG | S_IRWXO;
-               continue;
-             default:
-               break;
+           case 'u':
+             who |= S_IRWXU;
+             continue;
+           case 'g':
+             who |= S_IRWXG;
+             continue;
+           case 'o':
+             who |= S_IRWXO;
+             continue;
+           case 'a':
+             who |= S_IRWXU | S_IRWXG | S_IRWXO;
+             continue;
+           default:
+             break;
            }
        }
 
@@ -213,13 +212,13 @@ symbolic_umask (list)
       op = *s++;
       switch (op)
        {
-         case '+':
-         case '-':
-         case '=':
-           break;
-         default:
-           builtin_error ("bad symbolic mode operator: %c", op);
-           return (-1);
+       case '+':
+       case '-':
+       case '=':
+         break;
+       default:
+         builtin_error ("bad symbolic mode operator: %c", op);
+         return (-1);
        }
 
       /* Parse out the `perm' section of the symbolic mode clause. */
@@ -229,17 +228,15 @@ symbolic_umask (list)
 
          switch (c)
            {
-             case 'r':
-               perm |= S_IRUGO;
-               break;
-
-             case 'w':
-               perm |= S_IWUGO;
-               break;
-
-             case 'x':
-               perm |= S_IXUGO;
-               break;
+           case 'r':
+             perm |= S_IRUGO;
+             break;
+           case 'w':
+             perm |= S_IWUGO;
+             break;
+           case 'x':
+             perm |= S_IXUGO;
+             break;
            }
        }
 
@@ -252,29 +249,22 @@ symbolic_umask (list)
 
          switch (op)
            {
-             case '+':
-               umc |= perm;
-               break;
-
-             case '-':
-               umc &= ~perm;
-               break;
-
-             case '=':
-               umc &= ~who;
-               umc |= perm;
-               break;
-
-             default:
-               builtin_error ("bad operation character: %c", op);
-               return (-1);
-           }
-
-         if (!*s)
-           {
-             um = ~umc & 0777;
+           case '+':
+             bits |= perm;
+             break;
+           case '-':
+             bits &= ~perm;
              break;
+           case '=':
+             bits &= ~who;
+             bits |= perm;
+             break;
+
+           /* No other values are possible. */
            }
+
+         if (*s == '\0')
+           break;
          else
            s++;        /* skip past ',' */
        }
@@ -284,5 +274,30 @@ symbolic_umask (list)
          return (-1);
        }
     }
+
+  return (bits);
+}
+
+/* Set the umask from a symbolic mode string similar to that accepted
+   by chmod.  If the -S argument is given, then print the umask in a
+   symbolic form. */
+static int
+symbolic_umask (list)
+     WORD_LIST *list;
+{
+  int um, bits;
+
+  /* Get the initial umask.  Don't change it yet. */
+  um = umask (022);
+  umask (um);
+
+  /* All work is done with the complement of the umask -- it's
+     more intuitive and easier to deal with.  It is complemented
+     again before being returned. */
+  bits = parse_symbolic_mode (list->word->word, ~um);
+  if (bits == -1)
+    return (-1);
+
+  um = ~bits & 0777;
   return (um);
 }