Update copyright notices with scripts/update-copyrights.
[jlayton/glibc.git] / sysdeps / mach / hurd / setresgid.c
1 /* setresgid -- set real group ID, effective group ID, and saved-set group ID
2    Copyright (C) 2002-2013 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, see
17    <http://www.gnu.org/licenses/>.  */
18
19 #include <errno.h>
20 #include <unistd.h>
21 #include <hurd.h>
22 #include <hurd/id.h>
23
24 /* Set the real group ID, effective group ID, and saved-set group ID,
25    of the calling process to RGID, EGID, and SGID, respectively.  */
26 int
27 __setresgid (gid_t rgid, gid_t egid, gid_t sgid)
28 {
29   auth_t newauth;
30   error_t err;
31
32   HURD_CRITICAL_BEGIN;
33   __mutex_lock (&_hurd_id.lock);
34   err = _hurd_check_ids ();
35
36   if (!err)
37     {
38       /* Make a new auth handle which has EGID as the first element in the
39          list of effective gids.  */
40
41       uid_t *newgen, *newaux;
42       uid_t auxs[2] = { rgid, sgid };
43       size_t ngen, naux;
44
45       newgen = _hurd_id.gen.gids;
46       ngen = _hurd_id.gen.ngids;
47       if (egid != -1)
48         {
49           if (_hurd_id.gen.ngids == 0)
50             {
51               /* No effective gids now.  The new set will be just UID.  */
52               newgen = &egid;
53               ngen = 1;
54             }
55           else
56             {
57               _hurd_id.gen.gids[0] = egid;
58               _hurd_id.valid = 0;
59             }
60         }
61
62       newaux = _hurd_id.aux.gids;
63       naux = _hurd_id.aux.ngids;
64       if (rgid != -1)
65         {
66           if (_hurd_id.aux.ngids == 0)
67             {
68               newaux = &rgid;
69               naux = 1;
70             }
71           else
72             {
73               _hurd_id.aux.gids[0] = rgid;
74               _hurd_id.valid = 0;
75             }
76         }
77
78       if (sgid != -1)
79         {
80           if (rgid == -1)
81             {
82               if (_hurd_id.aux.ngids >= 1)
83                 auxs[0] = _hurd_id.aux.gids[0];
84               else if (_hurd_id.gen.ngids >= 1)
85                 auxs[0] = _hurd_id.gen.gids[0];
86               else
87                 /* Not even an effective GID.
88                    Fall back to the only GID we have. */
89                 auxs[0] = sgid;
90             }
91           if (_hurd_id.aux.ngids <= 1)
92             {
93               /* No saved gids now.  The new set will be just UID.  */
94               newaux = auxs;
95               naux = 2;
96             }
97           else
98             {
99               _hurd_id.aux.gids[1] = sgid;
100               _hurd_id.valid = 0;
101             }
102         }
103
104       err = __USEPORT (AUTH, __auth_makeauth
105                        (port, NULL, MACH_MSG_TYPE_COPY_SEND, 0,
106                         _hurd_id.gen.uids, _hurd_id.gen.nuids,
107                         _hurd_id.aux.uids, _hurd_id.aux.nuids,
108                         newgen, ngen, newaux, naux,
109                         &newauth));
110     }
111   __mutex_unlock (&_hurd_id.lock);
112   HURD_CRITICAL_END;
113
114   if (err)
115     return __hurd_fail (err);
116
117   /* Install the new handle and reauthenticate everything.  */
118   err = __setauth (newauth);
119   __mach_port_deallocate (__mach_task_self (), newauth);
120   return err;
121 }
122 libc_hidden_def (__setresgid)
123 weak_alias (__setresgid, setresgid)