ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/ptytty.C
Revision: 1.60
Committed: Mon Jan 23 12:37:59 2006 UTC (18 years, 4 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.59: +12 -10 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.55 // This file is part of libptytty. Do not make local modifications.
2     // http://software.schmorp.de/pkg/libptytty
3    
4     /*----------------------------------------------------------------------*
5 pcg 1.11 * File: ptytty.C
6 pcg 1.1 *----------------------------------------------------------------------*
7     *
8     * All portions of code are copyright by their respective author/s.
9     * Copyright (c) 1999-2001 Geoff Wing <gcw@pobox.com>
10 root 1.30 * Copyright (c) 2004-2006 Marc Lehmann <pcg@goof.com>
11 root 1.58 * Copyright (c) 2006 Emanuele Giaquinta <e.giaquinta@glauco.it>
12 pcg 1.1 *
13     * This program is free software; you can redistribute it and/or modify
14     * it under the terms of the GNU General Public License as published by
15     * the Free Software Foundation; either version 2 of the License, or
16     * (at your option) any later version.
17     *
18     * This program is distributed in the hope that it will be useful,
19     * but WITHOUT ANY WARRANTY; without even the implied warranty of
20     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21     * GNU General Public License for more details.
22     *
23     * You should have received a copy of the GNU General Public License
24     * along with this program; if not, write to the Free Software
25     * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26     *---------------------------------------------------------------------*/
27    
28 root 1.55 #include "../config.h"
29 root 1.54
30     #include "ptytty.h"
31 pcg 1.1
32 root 1.40 #include <cstdlib>
33     #include <cstring>
34 root 1.59 #include <csignal>
35 root 1.40
36     #include <sys/types.h>
37     #include <sys/socket.h>
38     #include <unistd.h>
39     #include <fcntl.h>
40 root 1.31
41 pcg 1.1 #ifdef HAVE_SYS_IOCTL_H
42     # include <sys/ioctl.h>
43     #endif
44 ayin 1.53 #if defined(HAVE_DEV_PTMX) && defined(HAVE_SYS_STROPTS_H)
45 pcg 1.1 # include <sys/stropts.h> /* for I_PUSH */
46     #endif
47 pcg 1.10 #ifdef HAVE_ISASTREAM
48     # include <stropts.h>
49     #endif
50 root 1.31 #if defined(HAVE_PTY_H)
51 root 1.22 # include <pty.h>
52 root 1.31 #elif defined(HAVE_LIBUTIL_H)
53 root 1.16 # include <libutil.h>
54 root 1.31 #elif defined(HAVE_UTIL_H)
55 root 1.17 # include <util.h>
56 pcg 1.1 #endif
57 ayin 1.53 #ifdef TTY_GID_SUPPORT
58     #include <grp.h>
59     #endif
60 pcg 1.1
61 root 1.16 #include <cstdio>
62    
63 root 1.36 /////////////////////////////////////////////////////////////////////////////
64    
65 pcg 1.1 /* ------------------------------------------------------------------------- *
66     * GET PSEUDO TELETYPE - MASTER AND SLAVE *
67     * ------------------------------------------------------------------------- */
68     /*
69     * Returns pty file descriptor, or -1 on failure
70     * If successful, ttydev is set to the name of the slave device.
71     * fd_tty _may_ also be set to an open fd to the slave device
72     */
73 ayin 1.53 #if defined(UNIX98_PTY)
74     static int
75     get_pty (int *fd_tty, char **ttydev)
76 pcg 1.1 {
77 pcg 1.4 int pfd;
78 pcg 1.1
79 ayin 1.53 # if defined(HAVE_GETPT)
80 ayin 1.44 pfd = getpt();
81 ayin 1.53 # elif defined(HAVE_POSIX_OPENPT)
82 ayin 1.44 pfd = posix_openpt (O_RDWR);
83     # else
84 ayin 1.53 pfd = open (CLONE_DEVICE, O_RDWR | O_NOCTTY, 0);
85 ayin 1.44 # endif
86     if (pfd >= 0)
87     {
88     if (grantpt (pfd) == 0 /* change slave permissions */
89     && unlockpt (pfd) == 0)
90     { /* slave now unlocked */
91     *ttydev = strdup (ptsname (pfd)); /* get slave's name */
92     return pfd;
93     }
94 root 1.45
95 ayin 1.44 close (pfd);
96     }
97 root 1.45
98 ayin 1.44 return -1;
99     }
100 ayin 1.53 #elif defined(HAVE_OPENPTY)
101     static int
102     get_pty (int *fd_tty, char **ttydev)
103 ayin 1.44 {
104     int pfd;
105     int res;
106 ayin 1.51 char tty_name[32];
107 ayin 1.44
108     res = openpty (&pfd, fd_tty, tty_name, NULL, NULL);
109 root 1.27 if (res != -1)
110 pcg 1.4 {
111 pcg 1.6 *ttydev = strdup (tty_name);
112 pcg 1.4 return pfd;
113 pcg 1.1 }
114 root 1.45
115 ayin 1.44 return -1;
116     }
117 ayin 1.53 #elif defined(HAVE__GETPTY)
118     static int
119     get_pty (int *fd_tty, char **ttydev)
120 ayin 1.44 {
121     int pfd;
122    
123 pcg 1.6 *ttydev = _getpty (&pfd, O_RDWR | O_NONBLOCK | O_NOCTTY, 0622, 0);
124 pcg 1.4 if (*ttydev != NULL)
125     return pfd;
126 root 1.45
127 ayin 1.44 return -1;
128     }
129 ayin 1.53 #elif defined(HAVE_DEV_PTC)
130     static int
131     get_pty (int *fd_tty, char **ttydev)
132 ayin 1.44 {
133     int pfd;
134 pcg 1.4
135 pcg 1.6 if ((pfd = open ("/dev/ptc", O_RDWR | O_NOCTTY, 0)) >= 0)
136 pcg 1.4 {
137 root 1.16 *ttydev = strdup (ttyname (pfd));
138 pcg 1.4 return pfd;
139 pcg 1.1 }
140 root 1.45
141 ayin 1.44 return -1;
142     }
143 ayin 1.53 #elif defined(HAVE_DEV_CLONE)
144     static int
145     get_pty (int *fd_tty, char **ttydev)
146 ayin 1.44 {
147     int pfd;
148    
149 pcg 1.6 if ((pfd = open ("/dev/ptym/clone", O_RDWR | O_NOCTTY, 0)) >= 0)
150 pcg 1.4 {
151 root 1.16 *ttydev = strdup (ptsname (pfd));
152 pcg 1.4 return pfd;
153 pcg 1.1 }
154 root 1.45
155 ayin 1.44 return -1;
156     }
157 ayin 1.53 #else
158     /* Based on the code in openssh/openbsd-compat/bsd-openpty.c */
159     static int
160     get_pty (int *fd_tty, char **ttydev)
161 ayin 1.44 {
162 root 1.45 int pfd;
163 ayin 1.53 int i;
164     char pty_name[32];
165     char tty_name[32];
166     const char *majors = "pqrstuvwxyzabcde";
167     const char *minors = "0123456789abcdef";
168     for (i = 0; i < 256; i++)
169     {
170     snprintf(pty_name, 32, "/dev/pty%c%c", majors[i / 16], minors[i % 16]);
171     snprintf(tty_name, 32, "/dev/tty%c%c", majors[i / 16], minors[i % 16]);
172     if ((pfd = open (pty_name, O_RDWR | O_NOCTTY, 0)) == -1)
173 root 1.45 {
174 ayin 1.53 snprintf(pty_name, 32, "/dev/ptyp%d", i);
175     snprintf(tty_name, 32, "/dev/ttyp%d", i);
176     if ((pfd = open (pty_name, O_RDWR | O_NOCTTY, 0)) == -1)
177     continue;
178 root 1.45 }
179 ayin 1.53 if (access (tty_name, R_OK | W_OK) == 0)
180 root 1.45 {
181 ayin 1.53 *ttydev = strdup (tty_name);
182     return pfd;
183     }
184 root 1.45
185 ayin 1.53 close (pfd);
186 root 1.45 }
187 ayin 1.44 }
188 pcg 1.1 #endif
189 root 1.45
190 pcg 1.1 /*----------------------------------------------------------------------*/
191     /*
192     * Returns tty file descriptor, or -1 on failure
193     */
194 root 1.16 static int
195     get_tty (char *ttydev)
196 pcg 1.1 {
197 pcg 1.4 return open (ttydev, O_RDWR | O_NOCTTY, 0);
198 pcg 1.1 }
199    
200     /*----------------------------------------------------------------------*/
201     /*
202     * Make our tty a controlling tty so that /dev/tty points to us
203     */
204 root 1.16 static int
205 root 1.36 control_tty (int fd_tty)
206 pcg 1.1 {
207 pcg 1.4 setsid ();
208 root 1.16
209 ayin 1.53 #if defined(HAVE_DEV_PTMX) && defined(I_PUSH)
210 pcg 1.4 /*
211     * Push STREAMS modules:
212     * ptem: pseudo-terminal hardware emulation module.
213     * ldterm: standard terminal line discipline.
214     * ttcompat: V7, 4BSD and XENIX STREAMS compatibility module.
215     *
216 pcg 1.6 * After we push the STREAMS modules, the first open () on the slave side
217 pcg 1.4 * (i.e. the next section between the dashes giving us "tty opened OK")
218     * should make the "ptem" (or "ldterm" depending upon either which OS
219     * version or which set of manual pages you have) module give us a
220 pcg 1.6 * controlling terminal. We must already have close ()d the master side
221 pcg 1.4 * fd in this child process before we push STREAMS modules on because the
222 pcg 1.6 * documentation is really unclear about whether it is any close () on
223     * the master side or the last close () - i.e. a proper STREAMS dismantling
224     * close () - on the master side which causes a hang up to be sent
225 pcg 1.4 * through - Geoff Wing
226     */
227 root 1.47 # ifdef HAVE_ISASTREAM
228 pcg 1.4 if (isastream (fd_tty) == 1)
229 root 1.47 # endif
230 pcg 1.1 {
231 pcg 1.4 ioctl (fd_tty, I_PUSH, "ptem");
232     ioctl (fd_tty, I_PUSH, "ldterm");
233     ioctl (fd_tty, I_PUSH, "ttcompat");
234 pcg 1.1 }
235 root 1.47 #endif
236 root 1.45
237     ioctl (fd_tty, TIOCSCTTY, NULL);
238    
239     int fd = open ("/dev/tty", O_WRONLY);
240 pcg 1.4 if (fd < 0)
241 root 1.56 return -1; /* fatal */
242 root 1.45
243 pcg 1.4 close (fd);
244    
245     return 0;
246 pcg 1.1 }
247 root 1.16
248 root 1.36 void
249 root 1.54 ptytty::close_tty ()
250 root 1.36 {
251     if (tty < 0)
252     return;
253    
254     close (tty);
255     tty = -1;
256     }
257    
258     bool
259 root 1.54 ptytty::make_controlling_tty ()
260 root 1.36 {
261     return control_tty (tty) >= 0;
262     }
263    
264     void
265 root 1.54 ptytty::set_utf8_mode (bool on)
266 root 1.36 {
267     #ifdef IUTF8
268     if (pty < 0)
269     return;
270    
271     struct termios tio;
272    
273     if (tcgetattr (pty, &tio) != -1)
274     {
275     tcflag_t new_cflag = tio.c_iflag;
276    
277     if (on)
278     new_cflag |= IUTF8;
279     else
280     new_cflag &= ~IUTF8;
281    
282     if (new_cflag != tio.c_iflag)
283     {
284     tio.c_iflag = new_cflag;
285     tcsetattr (pty, TCSANOW, &tio);
286     }
287     }
288     #endif
289     }
290    
291 root 1.16 static struct ttyconf {
292     gid_t gid;
293     mode_t mode;
294    
295     ttyconf ()
296     {
297     #ifdef TTY_GID_SUPPORT
298     struct group *gr = getgrnam ("tty");
299    
300     if (gr)
301     { /* change group ownership of tty to "tty" */
302     mode = S_IRUSR | S_IWUSR | S_IWGRP;
303     gid = gr->gr_gid;
304     }
305     else
306     #endif /* TTY_GID_SUPPORT */
307     {
308     mode = S_IRUSR | S_IWUSR | S_IWGRP | S_IWOTH;
309 ayin 1.48 gid = 0;
310 root 1.16 }
311     }
312     } ttyconf;
313    
314 root 1.54 ptytty_unix::ptytty_unix ()
315 root 1.16 {
316     name = 0;
317 root 1.35 #if UTMP_SUPPORT
318     cmd_pid = 0;
319     #endif
320 root 1.16 }
321    
322 root 1.54 ptytty_unix::~ptytty_unix ()
323 root 1.16 {
324 root 1.43 #if UTMP_SUPPORT
325 root 1.35 logout ();
326 root 1.43 #endif
327 root 1.16 put ();
328     }
329    
330     void
331 root 1.54 ptytty_unix::put ()
332 root 1.16 {
333 ayin 1.49 chmod (name, RESTORE_TTY_MODE);
334     chown (name, 0, ttyconf.gid);
335 root 1.16
336     close_tty ();
337 root 1.50
338     if (pty >= 0)
339     close (pty);
340    
341 root 1.16 free (name);
342    
343     pty = tty = -1;
344     name = 0;
345     }
346    
347     bool
348 root 1.54 ptytty_unix::get ()
349 root 1.16 {
350     /* get master (pty) */
351     if ((pty = get_pty (&tty, &name)) < 0)
352     return false;
353    
354     fcntl (pty, F_SETFL, O_NONBLOCK);
355    
356     /* get slave (tty) */
357     if (tty < 0)
358     {
359     #ifndef NO_SETOWNER_TTYDEV
360 ayin 1.49 chown (name, getuid (), ttyconf.gid); /* fail silently */
361     chmod (name, ttyconf.mode);
362     # ifdef HAVE_REVOKE
363     revoke (name);
364     # endif
365 root 1.16 #endif
366    
367     if ((tty = get_tty (name)) < 0)
368     {
369     put ();
370     return false;
371     }
372     }
373    
374     return true;
375     }
376    
377 root 1.59 /////////////////////////////////////////////////////////////////////////////
378     // helper/proxy support
379    
380 root 1.40 #if PTYTTY_HELPER
381    
382 root 1.59 static int sock_fd = -1, lock_fd = -1;
383 root 1.56 static int helper_pid, owner_pid;
384 root 1.40
385     struct command
386     {
387     enum { get, login, destroy } type;
388    
389 root 1.54 ptytty *id;
390 root 1.40
391     bool login_shell;
392     int cmd_pid;
393     char hostname[512]; // arbitrary, but should be plenty
394     };
395    
396 root 1.54 struct ptytty_proxy : ptytty
397 root 1.40 {
398 root 1.54 ptytty *id;
399 root 1.40
400 root 1.54 ptytty_proxy ()
401     : id(0)
402     {
403     }
404    
405     ~ptytty_proxy ();
406 root 1.40
407     bool get ();
408     void login (int cmd_pid, bool login_shell, const char *hostname);
409     };
410    
411 root 1.59 #if PTYTTY_REENTRANT
412     # define NEED_TOKEN do { char ch; read (lock_fd, &ch, 1); } while (0)
413     # define GIVE_TOKEN do { char ch; write (lock_fd, &ch, 1); } while (0)
414     #else
415     # define NEED_TOKEN (void)0
416     # define GIVE_TOKEN (void)0
417     #endif
418    
419 root 1.40 bool
420 root 1.54 ptytty_proxy::get ()
421 root 1.40 {
422 root 1.59 NEED_TOKEN;
423    
424 root 1.40 command cmd;
425    
426     cmd.type = command::get;
427    
428     write (sock_fd, &cmd, sizeof (cmd));
429    
430     if (read (sock_fd, &id, sizeof (id)) != sizeof (id))
431 root 1.56 ptytty_fatal ("protocol error while creating pty using helper process, aborting.\n");
432 root 1.40
433     if (!id)
434 root 1.59 {
435     GIVE_TOKEN;
436     return false;
437     }
438 root 1.40
439 root 1.56 if ((pty = recv_fd (sock_fd)) < 0
440     || (tty = recv_fd (sock_fd)) < 0)
441     ptytty_fatal ("protocol error while reading pty/tty fds from helper process, aborting.\n");
442 root 1.40
443 root 1.59 GIVE_TOKEN;
444 root 1.40 return true;
445     }
446    
447     void
448 root 1.54 ptytty_proxy::login (int cmd_pid, bool login_shell, const char *hostname)
449 root 1.40 {
450 root 1.59 NEED_TOKEN;
451    
452 root 1.40 command cmd;
453    
454     cmd.type = command::login;
455     cmd.id = id;
456     cmd.cmd_pid = cmd_pid;
457     cmd.login_shell = login_shell;
458     strncpy (cmd.hostname, hostname, sizeof (cmd.hostname));
459    
460     write (sock_fd, &cmd, sizeof (cmd));
461 root 1.59
462     GIVE_TOKEN;
463 root 1.40 }
464    
465 root 1.54 ptytty_proxy::~ptytty_proxy ()
466 root 1.40 {
467 root 1.54 if (id)
468     {
469 root 1.59 NEED_TOKEN;
470    
471 root 1.54 command cmd;
472 root 1.40
473 root 1.54 cmd.type = command::destroy;
474     cmd.id = id;
475 root 1.40
476 root 1.54 write (sock_fd, &cmd, sizeof (cmd));
477 root 1.59
478     GIVE_TOKEN;
479 root 1.54 }
480 root 1.40 }
481    
482     static
483     void serve ()
484     {
485     command cmd;
486 root 1.54 vector<ptytty *> ptys;
487 root 1.40
488 root 1.59 for (;;)
489 root 1.40 {
490 root 1.59 GIVE_TOKEN;
491    
492     if (read (sock_fd, &cmd, sizeof (command)) != sizeof (command))
493     break;
494    
495 root 1.40 if (cmd.type == command::get)
496     {
497     // -> id ptyfd ttyfd
498 root 1.54 cmd.id = new ptytty_unix;
499 root 1.40
500     if (cmd.id->get ())
501     {
502     write (sock_fd, &cmd.id, sizeof (cmd.id));
503     ptys.push_back (cmd.id);
504    
505 root 1.56 ptytty::send_fd (sock_fd, cmd.id->pty);
506     ptytty::send_fd (sock_fd, cmd.id->tty);
507 root 1.40 }
508     else
509     {
510     delete cmd.id;
511     cmd.id = 0;
512     write (sock_fd, &cmd.id, sizeof (cmd.id));
513     }
514     }
515     else if (cmd.type == command::login)
516     {
517 root 1.43 #if UTMP_SUPPORT
518 root 1.59 if (find (ptys.begin (), ptys.end (), cmd.id) != ptys.end ())
519 root 1.40 {
520     cmd.hostname[sizeof (cmd.hostname) - 1] = 0;
521     cmd.id->login (cmd.cmd_pid, cmd.login_shell, cmd.hostname);
522     }
523 root 1.43 #endif
524 root 1.40 }
525     else if (cmd.type == command::destroy)
526     {
527 root 1.56 vector<ptytty *>::iterator pty = find (ptys.begin (), ptys.end (), cmd.id);
528 root 1.40
529 root 1.56 if (pty != ptys.end ())
530 root 1.40 {
531 root 1.42 delete *pty;
532 root 1.40 ptys.erase (pty);
533     }
534     }
535     else
536     break;
537 root 1.59
538     NEED_TOKEN;
539 root 1.40 }
540    
541     // destroy all ptys
542 root 1.56 for (vector<ptytty *>::iterator i = ptys.end (); i-- > ptys.begin (); )
543 root 1.40 delete *i;
544     }
545    
546 root 1.56 void
547     ptytty::use_helper ()
548 root 1.40 {
549 root 1.59 #ifndef PTYTTY_NO_PID_CHECK
550 root 1.56 int pid = getpid ();
551 root 1.59 #endif
552 root 1.56
553 root 1.59 if (sock_fd >= 0
554     #ifndef PTYTTY_NO_PID_CHECK
555     && pid == owner_pid
556     #endif
557     )
558 root 1.56 return;
559    
560 root 1.59 #ifndef PTYTTY_NO_PID_CHECK
561 root 1.56 owner_pid = pid;
562 root 1.59 #endif
563 root 1.56
564 root 1.40 int sv[2];
565    
566     if (socketpair (AF_UNIX, SOCK_STREAM, 0, sv))
567 root 1.56 ptytty_fatal ("could not create socket to communicate with pty/sessiondb helper, aborting.\n");
568 root 1.40
569 root 1.59 #ifdef PTYTTY_REENTRANT
570     int lv[2];
571    
572     if (socketpair (AF_UNIX, SOCK_STREAM, 0, lv))
573     ptytty_fatal ("could not create socket to communicate with pty/sessiondb helper, aborting.\n");
574     #endif
575    
576 root 1.56 helper_pid = fork ();
577 root 1.40
578 root 1.56 if (helper_pid < 0)
579     ptytty_fatal ("could not create pty/sessiondb helper process, aborting.\n");
580 root 1.40
581 root 1.56 if (helper_pid)
582 root 1.40 {
583 root 1.54 // client, process
584 root 1.40 sock_fd = sv[0];
585     close (sv[1]);
586     fcntl (sock_fd, F_SETFD, FD_CLOEXEC);
587 root 1.59 #ifdef PTYTTY_REENTRANT
588     lock_fd = lv[0];
589     close (lv[1]);
590     fcntl (lock_fd, F_SETFD, FD_CLOEXEC);
591     #endif
592 root 1.40 }
593     else
594     {
595     // server, pty-helper
596     sock_fd = sv[1];
597 root 1.59 #ifdef PTYTTY_REENTRANT
598     lock_fd = lv[1];
599     #endif
600 root 1.40
601 root 1.56 chdir ("/");
602    
603 root 1.59 signal (SIGHUP, SIG_IGN);
604     signal (SIGTERM, SIG_IGN);
605     signal (SIGINT, SIG_IGN);
606     signal (SIGPIPE, SIG_IGN);
607    
608 root 1.41 for (int fd = 0; fd < 1023; fd++)
609 root 1.59 if (fd != sock_fd && fd != lock_fd)
610 root 1.41 close (fd);
611 root 1.40
612     serve ();
613     _exit (EXIT_SUCCESS);
614     }
615     }
616 root 1.50
617 root 1.40 #endif
618    
619 root 1.54 ptytty *
620 root 1.56 ptytty::create ()
621 root 1.39 {
622 root 1.40 #if PTYTTY_HELPER
623 root 1.59 if (helper_pid
624     # ifndef PTYTTY_NO_PID_CHECK
625     && getpid () == owner_pid
626     # endif
627     )
628 root 1.41 // use helper process
629 root 1.54 return new ptytty_proxy;
630 root 1.40 else
631     #endif
632 root 1.54 return new ptytty_unix;
633 root 1.39 }
634    
635 root 1.56 void
636     ptytty::init ()
637     {
638     uid_t uid = getuid ();
639     gid_t gid = getgid ();
640    
641     // before doing anything else, check for setuid/setgid operation,
642     // start the helper process and drop privileges
643     if (uid != geteuid ()
644     || gid != getegid ())
645     {
646     #if PTYTTY_HELPER
647     use_helper ();
648     #else
649     ptytty_warn ("running setuid/setgid without pty helper compiled in, continuing unprivileged.\n");
650     #endif
651    
652     drop_privileges ();
653     }
654     }
655    
656     void
657     ptytty::drop_privileges ()
658     {
659     uid_t uid = getuid ();
660     gid_t gid = getgid ();
661    
662     // drop privileges
663     #if HAVE_SETRESUID
664     setresgid (gid, gid, gid);
665     setresuid (uid, uid, uid);
666     #elif HAVE_SETREUID
667     setregid (gid, gid);
668     setreuid (uid, uid);
669     #elif HAVE_SETUID
670     setgid (gid);
671     setuid (uid);
672     #endif
673    
674     if (uid != geteuid ()
675     || gid != getegid ())
676     ptytty_fatal ("unable to drop privileges, aborting.\n");
677     }
678 root 1.16
679 root 1.59 /////////////////////////////////////////////////////////////////////////////
680     // C API
681    
682     #ifndef PTYTTY_NO_C_API
683    
684 root 1.60 typedef void *PTYTTY;
685    
686 root 1.59 #define DEFINE_METHOD(retval, name, args1, args2) \
687     extern "C" retval ptytty_ ## name args1 \
688     { return ((struct ptytty *)ptytty)->name args2; }
689    
690 root 1.60 DEFINE_METHOD(int,pty,(PTYTTY ptytty),)
691     DEFINE_METHOD(int,tty,(PTYTTY ptytty),)
692     DEFINE_METHOD(int,get,(PTYTTY ptytty),())
693     DEFINE_METHOD(void,login,(PTYTTY ptytty, int cmd_pid, bool login_shell, const char *hostname),(cmd_pid,login_shell,hostname))
694    
695     DEFINE_METHOD(void,close_tty,(PTYTTY ptytty),())
696     DEFINE_METHOD(int,make_controlling_tty,(PTYTTY ptytty),())
697     DEFINE_METHOD(void,set_utf8_mode,(PTYTTY ptytty, int on),(on))
698 root 1.59
699     #define DEFINE_STATIC(retval, name, args) \
700     extern "C" retval ptytty_ ## name args \
701     { return ptytty::name args; }
702    
703     DEFINE_STATIC(void,drop_privileges,())
704     DEFINE_STATIC(void,use_helper,())
705     DEFINE_STATIC(void,init,())
706    
707 root 1.60 DEFINE_STATIC(PTYTTY ,create,())
708 root 1.59
709 root 1.60 void ptytty_delete (PTYTTY ptytty)
710 root 1.59 {
711     delete (struct ptytty *)ptytty;
712     }
713    
714     // send_fd, recv_fd not exposed
715    
716     #endif