* added forkpty() and login_tty() to bsd compatibility, a test for forkpty().

* added a TODO questioning the closing master and slave in openpty() when applying window size fails.
* added TIOCSCTTY as a TTY ioctl code, the caller become controlling TTY. Review comments are welcome.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@36105 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Jérôme Duval 2010-04-10 13:48:28 +00:00
parent ba51713c8f
commit 1590c69933
6 changed files with 124 additions and 1 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright 2008, Haiku, Inc. All Rights Reserved.
* Copyright 2008-2010, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _BSD_PTY_H_
@ -13,6 +13,9 @@ __BEGIN_DECLS
extern int openpty(int* master, int* slave, char* name,
struct termios* termAttrs, struct winsize* windowSize);
extern int login_pty(int fd);
extern pid_t forkpty(int* master, char* name,
struct termios* termAttrs, struct winsize* windowSize);
__END_DECLS

View File

@ -180,6 +180,7 @@ struct termios {
#define TCVTIME (TCGETA + 14) /* pass in bigtime_t, old value saved */
#define TIOCGPGRP (TCGETA + 15) /* Gets the process group ID of the TTY device */
#define TIOCSPGRP (TCGETA + 16) /* Sets the process group ID ('pgid' in BeOS) */
#define TIOCSCTTY (TCGETA + 17) /* Become controlling TTY */
/* Event codes. Returned from TCWAITEVENT */
#define EV_RING 0x0001

View File

@ -1652,6 +1652,24 @@ tty_ioctl(tty_cookie* cookie, uint32 op, void* buffer, size_t length)
tty->settings->pgrp_id = groupID;
return error;
}
// become controlling TTY
case TIOCSCTTY:
{
TRACE(("tty: become controlling tty\n"));
pid_t processID = getpid();
pid_t sessionID = getsid(processID);
// Only session leaders can become controlling tty
if (processID != sessionID)
return B_NOT_ALLOWED;
// Check if already controlling tty
if (team_get_controlling_tty() == tty->index)
return B_OK;
tty->settings->session_id = sessionID;
tty->settings->pgrp_id = sessionID;
team_set_controlling_tty(tty->index);
return B_OK;
}
// get and set window size

View File

@ -1,5 +1,6 @@
/*
* Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de. All rights reserved.
* Copyright 2010, Jérôme Duval, korli@users.berlios.de. All rights reserved.
* Distributed under the terms of the MIT License.
*/
@ -31,6 +32,8 @@ openpty(int* _master, int* _slave, char* name, struct termios* termAttrs,
if (termAttrs != NULL && tcsetattr(master, TCSANOW, termAttrs) != 0
|| windowSize != NULL
&& ioctl(master, TIOCSWINSZ, windowSize, sizeof(winsize)) != 0) {
// TODO we should either close master and slaves and return -1
// or we do nothing!
close(slave);
close(master);
}
@ -43,3 +46,47 @@ openpty(int* _master, int* _slave, char* name, struct termios* termAttrs,
return 0;
}
int
login_tty(int fd)
{
setsid();
if (ioctl(fd, TIOCSCTTY, NULL) != 0)
return -1;
dup2(fd, 0);
dup2(fd, 1);
dup2(fd, 2);
close(fd);
return 0;
}
pid_t
forkpty(int* _master, char* name, struct termios* termAttrs,
struct winsize* windowSize)
{
int master, slave;
if (openpty(&master, &slave, name, termAttrs, windowSize) != 0)
return -1;
int pid = fork();
if (pid < 0) {
close(master);
close(slave);
return -1;
}
// child
if (pid == 0) {
close(master);
return login_tty(slave);
}
// parent
close (slave);
*_master = master;
return pid;
}

View File

@ -0,0 +1,7 @@
SubDir HAIKU_TOP src tests libs bsd ;
UseHeaders [ FDirName $(HAIKU_TOP) headers compatibility bsd ] : true ;
SimpleTest forkpty_test : forkpty.c : libbsd.so ;

View File

@ -0,0 +1,47 @@
/* from http://jwz.livejournal.com/817438.html */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pty.h>
static int
do_fork(void)
{
int fd = -1;
pid_t pid;
if ((pid = forkpty(&fd, NULL, NULL, NULL)) < 0)
perror("forkpty");
else if (!pid)
{
printf ("0123456789\n");
/* #### Uncommenting this makes it work! */
/* sleep(20); */
exit (0);
}
return fd;
}
int
main (int argc, char **argv)
{
char s[1024];
int n;
int fd = do_fork();
/* On 10.4, this prints the whole 10 character line, 1 char per second.
On 10.5, it prints 1 character and stops.
*/
do {
n = read (fd, s, 1);
if (n > 0) fprintf (stderr, "%c", *s);
sleep (1);
} while (n > 0);
return 0;
}