OSDN Git Service

ldso: Add remaining relocation types to the table
[uclinux-h8/uClibc.git] / libutil / openpty.c
1 /* Copyright (C) 1998, 1999, 2004 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Zack Weinberg <zack@rabi.phys.columbia.edu>, 1998.
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 <fcntl.h>
21 #include <limits.h>
22 #include <pty.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <termios.h>
26 #include <unistd.h>
27 #include <sys/types.h>
28
29 /* BCS: the following function is, IMO, overkill */
30 #if 0
31 /* Return the result of ptsname_r in the buffer pointed to by PTS,
32    which should be of length BUF_LEN.  If it is too long to fit in
33    this buffer, a sufficiently long buffer is allocated using malloc,
34    and returned in PTS.  0 is returned upon success, -1 otherwise.  */
35 static int
36 pts_name (int fd, char **pts, size_t buf_len)
37 {
38   int rv;
39   char *buf = *pts;
40
41   for (;;)
42     {
43       char *new_buf;
44
45       if (buf_len)
46         {
47           rv = ptsname_r (fd, buf, buf_len);
48
49           if (rv != 0 || memchr (buf, '\0', buf_len))
50             /* We either got an error, or we succeeded and the
51                returned name fit in the buffer.  */
52             break;
53
54           /* Try again with a longer buffer.  */
55           buf_len += buf_len;   /* Double it */
56         }
57       else
58         /* No initial buffer; start out by mallocing one.  */
59         buf_len = 128;          /* First time guess.  */
60
61       if (buf != *pts)
62         /* We've already malloced another buffer at least once.  */
63         new_buf = realloc (buf, buf_len);
64       else
65         new_buf = malloc (buf_len);
66       if (! new_buf)
67         {
68           rv = -1;
69           __set_errno (ENOMEM);
70           break;
71         }
72       buf = new_buf;
73     }
74
75   if (rv == 0)
76     *pts = buf;         /* Return buffer to the user.  */
77   else if (buf != *pts)
78     free (buf);         /* Free what we malloced when returning an error.  */
79
80   return rv;
81 }
82 #endif
83
84 /* Create pseudo tty master slave pair and set terminal attributes
85    according to TERMP and WINP.  Return handles for both ends in
86    AMASTER and ASLAVE, and return the name of the slave end in NAME.  */
87 libutil_hidden_proto(openpty)
88 int
89 openpty (int *amaster, int *aslave, char *name, struct termios *termp,
90          struct winsize *winp)
91 {
92 #if 0
93 #ifdef PATH_MAX
94   char _buf[PATH_MAX];
95 #else
96   char _buf[512];
97 #endif
98   char *buf = _buf;
99 #else
100 #ifdef PATH_MAX
101   char buf[PATH_MAX];
102 #else
103   char buf[512];
104 #endif
105 #endif
106   int master, slave;
107
108   master = posix_openpt (O_RDWR);
109   if (master == -1)
110     return -1;
111
112   if (grantpt (master))
113     goto fail;
114
115   if (unlockpt (master))
116     goto fail;
117
118 #if 0
119   if (pts_name (master, &buf, sizeof (_buf)))
120 #else
121   if (ptsname_r (master, buf, sizeof buf))
122 #endif
123     goto fail;
124
125   slave = open (buf, O_RDWR | O_NOCTTY);
126   if (slave == -1)
127     {
128 #if 0
129       if (buf != _buf)
130         free (buf);
131 #endif
132       goto fail;
133     }
134
135   /* XXX Should we ignore errors here?  */
136   if(termp)
137     tcsetattr (slave, TCSAFLUSH, termp);
138   if (winp)
139     ioctl (slave, TIOCSWINSZ, winp);
140
141   *amaster = master;
142   *aslave = slave;
143   if (name != NULL)
144     strcpy (name, buf);
145
146 #if 0
147   if (buf != _buf)
148     free (buf);
149 #endif
150   return 0;
151
152  fail:
153   close (master);
154   return -1;
155 }
156 libutil_hidden_def(openpty)