Bump to 1.14.1
[platform/upstream/augeas.git] / lib / grantpt.c
1 /* Acquire ownership of the slave side of a pseudo-terminal.
2    Copyright (C) 1998-2002, 2009-2016 Free Software Foundation, Inc.
3    Contributed by Zack Weinberg <zack@rabi.phys.columbia.edu>, 1998.
4
5    This program is free software: you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 3 of the License, or
8    (at your option) any later version.
9
10    This program 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
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
17
18 #include <config.h>
19
20 #include <stdlib.h>
21
22 #include <assert.h>
23 #include <errno.h>
24 #include <string.h>
25 #include <sys/wait.h>
26 #include <unistd.h>
27
28 #if HAVE_SETRLIMIT
29 # include <sys/types.h>
30 # include <sys/time.h>
31 # include <sys/resource.h>
32 #endif
33
34 #include "configmake.h"
35 #include "pty-private.h"
36
37 #ifndef _LIBC
38 # define __builtin_expect(expr,val) (expr)
39 # define __set_errno(e) errno = (e)
40 # define __dup2 dup2
41 # define __fork fork
42 # define __setrlimit setrlimit
43 # define __waitpid waitpid
44 #endif
45
46 int
47 grantpt (int fd)
48 {
49 #if defined __OpenBSD__ || defined _WIN32
50   /* On OpenBSD, master and slave of a pseudo-terminal are allocated together,
51      through an ioctl on /dev/ptm.  On Windows there are no ptys.
52      Therefore in either case there is no need for grantpt().  */
53   return 0;
54 #else
55   /* This function is most often called from a process without 'root'
56      credentials.  Use the helper program.  */
57   int retval = -1;
58   pid_t pid = __fork ();
59   if (pid == -1)
60     goto cleanup;
61   else if (pid == 0)
62     {
63       /* This is executed in the child process.  */
64
65 # if HAVE_SETRLIMIT && defined RLIMIT_CORE
66       /* Disable core dumps.  */
67       struct rlimit rl = { 0, 0 };
68       __setrlimit (RLIMIT_CORE, &rl);
69 # endif
70
71       /* We pass the master pseudo terminal as file descriptor PTY_FILENO.  */
72       if (fd != PTY_FILENO)
73         if (__dup2 (fd, PTY_FILENO) < 0)
74           _exit (FAIL_EBADF);
75
76 # ifdef CLOSE_ALL_FDS
77       CLOSE_ALL_FDS ();
78 # endif
79
80       execle (_PATH_PT_CHOWN, strrchr (_PATH_PT_CHOWN, '/') + 1, NULL, NULL);
81       _exit (FAIL_EXEC);
82     }
83   else
84     {
85       int w;
86
87       if (__waitpid (pid, &w, 0) == -1)
88         goto cleanup;
89       if (!WIFEXITED (w))
90         __set_errno (ENOEXEC);
91       else
92         switch (WEXITSTATUS (w))
93           {
94           case 0:
95             retval = 0;
96             break;
97           case FAIL_EBADF:
98             __set_errno (EBADF);
99             break;
100           case FAIL_EINVAL:
101             __set_errno (EINVAL);
102             break;
103           case FAIL_EACCES:
104             __set_errno (EACCES);
105             break;
106           case FAIL_EXEC:
107             __set_errno (ENOEXEC);
108             break;
109           case FAIL_ENOMEM:
110             __set_errno (ENOMEM);
111             break;
112
113           default:
114             assert(! "getpt: internal error: invalid exit code from pt_chown");
115           }
116     }
117
118  cleanup:
119   return retval;
120 #endif
121 }