unistr/u8-chr, unistr/u8-strchr: use Boyer-Moore like algorithm.
[gnulib.git] / lib / openpty.c
1 /* Open a pseudo-terminal.
2    Copyright (C) 2010 Free Software Foundation, Inc.
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 3 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
16
17 #include <config.h>
18
19 /* Specification.  */
20 #include <pty.h>
21
22 #if HAVE_OPENPTY
23
24 /* Provide a wrapper with the prototype of glibc-2.8 and newer.  */
25 # undef openpty
26 int
27 rpl_openpty (int *amaster, int *aslave, char *name,
28              struct termios const *termp, struct winsize const *winp)
29 {
30   /* Cast away const, for implementations with weaker prototypes.  */
31   return openpty (amaster, aslave, name, (struct termios *) termp,
32                   (struct winsize *) winp);
33 }
34
35 #else /* AIX 5.1, HP-UX 11, IRIX 6.5, Solaris 10, mingw */
36
37 # include <fcntl.h>
38 # include <string.h>
39 # include <sys/ioctl.h>
40 # include <termios.h>
41 # include <unistd.h>
42 # if defined __sun || defined __hpux /* Solaris, HP-UX */
43 #  include <stropts.h>
44 # endif
45
46 int
47 openpty (int *amaster, int *aslave, char *name,
48          struct termios const *termp, struct winsize const *winp)
49 {
50   int master;
51   char *slave_name;
52   int slave;
53
54 # if HAVE__GETPTY /* IRIX */
55
56   slave_name = _getpty (&master, O_RDWR, 0622, 0);
57   if (slave_name == NULL)
58     return -1;
59
60 # else /* AIX 5.1, HP-UX 11, Solaris 10, mingw */
61
62 #  if HAVE_POSIX_OPENPT /* Solaris 10 */
63
64   master = posix_openpt (O_RDWR | O_NOCTTY);
65   if (master < 0)
66     return -1;
67
68 #  else /* AIX 5.1, HP-UX 11, Solaris 9, mingw */
69
70 #   ifdef _AIX /* AIX */
71
72   master = open ("/dev/ptc", O_RDWR | O_NOCTTY);
73   if (master < 0)
74     return -1;
75
76 #   else /* HP-UX 11, Solaris 9, mingw */
77
78   /* HP-UX, Solaris have /dev/ptmx.
79      HP-UX also has /dev/ptym/clone, but this should not be needed.
80      Linux also has /dev/ptmx, but Linux already has openpty().
81      MacOS X also has /dev/ptmx, but MacOS X already has openpty().
82      OSF/1 also has /dev/ptmx and /dev/ptmx_bsd, but OSF/1 already has
83      openpty().  */
84   master = open ("/dev/ptmx", O_RDWR | O_NOCTTY);
85   if (master < 0)
86     return -1;
87
88 #   endif
89
90 #  endif
91
92   /* If all this does not work, we could try to open, one by one:
93      - On MacOS X: /dev/pty[p-w][0-9a-f]
94      - On *BSD:    /dev/pty[p-sP-S][0-9a-v]
95      - On AIX:     /dev/ptyp[0-9a-f]
96      - On HP-UX:   /dev/pty[p-r][0-9a-f]
97      - On OSF/1:   /dev/pty[p-q][0-9a-f]
98      - On Solaris: /dev/pty[p-r][0-9a-f]
99    */
100 # endif
101
102   /* This call does not require a dependency to the 'grantpt' module,
103      because AIX, HP-UX, IRIX, Solaris all have the grantpt() function.  */
104   if (grantpt (master))
105     goto fail;
106
107   /* This call does not require a dependency to the 'unlockpt' module,
108      because AIX, HP-UX, IRIX, Solaris all have the unlockpt() function.  */
109   if (unlockpt (master))
110     goto fail;
111
112 # if !HAVE__GETPTY /* !IRIX */
113   slave_name = ptsname (master);
114   if (slave_name == NULL)
115     goto fail;
116 # endif
117
118   slave = open (slave_name, O_RDWR | O_NOCTTY);
119   if (slave == -1)
120     goto fail;
121
122 # if defined __sun || defined __hpux /* Solaris, HP-UX */
123   if (ioctl (slave, I_PUSH, "ptem") < 0
124       || ioctl (slave, I_PUSH, "ldterm") < 0
125 #  if defined __sun
126       || ioctl (slave, I_PUSH, "ttcompat") < 0
127 #  endif
128      )
129     {
130       close (slave);
131       goto fail;
132     }
133 # endif
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, slave_name);
145
146   return 0;
147
148  fail:
149   close (master);
150   return -1;
151 }
152
153 #endif