1
/* This software is subject to the terms of the Common Public License
2
You must accept the terms of this license to use this software.
4
Copyright (C) 2002, International Business Machines Corporation
5
and others. All Rights Reserved.
7
Further information about Common Public License Version 0.5 is obtained
8
from url http://oss.software.ibm.com/developer/opensource/license-cpl.html
10
#include "../../../config.h"
12
#include "iterm/unix/ttyio.h"
15
#include <sys/ioctl.h>
16
#include <sys/types.h>
33
#if defined(HAVE_LIBUTEMPTER)
38
* ConcreteIO definitin, which is for pseudo tty base communication
43
/* file descriptor of this object */
48
/* child process id */
50
/* flag if this file descriptor is closed or not */
53
#if defined(HAVE_LIBUTEMPTER)
54
#define write_utmp(tty_name,fd) addToUtmp(tty_name,NULL,fd);
55
#define delete_utmp(tty_name) removeFromUtmp();
57
static void write_utmp(char *tty_name)
66
p = rindex(tty_name,'/') + 1;
67
if( '0' <= *p && *p <= '9')
72
line = tty_name + strlen("/dev/");
81
memset(&entry,0,sizeof(entry));
82
entry.ut_type = DEAD_PROCESS;
83
strncpy(entry.ut_id,id,sizeof(id));
86
pw = getpwuid(getuid());
87
entry.ut_type = USER_PROCESS;
88
entry.ut_pid = getpid();
89
strncpy(entry.ut_line, line, sizeof(entry.ut_line));
90
strncpy(entry.ut_user, pw->pw_name, sizeof(entry.ut_user));
92
host = getenv("DISPLAY");
94
strncpy(entry.ut_host, host, sizeof(entry.ut_host));
96
entry.ut_tv.tv_sec = time(NULL);
97
entry.ut_tv.tv_usec = 0;
102
static void delete_utmp(char *tty_name)
110
p = rindex(tty_name,'/') + 1;
111
if( '0' <= *p && *p <= '9')
116
line = rindex(p,'/') + 1;
124
memset(&entry,0,sizeof(entry));
125
entry.ut_type = USER_PROCESS;
126
strncpy(entry.ut_id,id,sizeof(id));
128
utp = getutxid(&entry);
131
utp->ut_type = DEAD_PROCESS;
132
memset(utp->ut_user,0,sizeof(entry.ut_user));
133
entry.ut_tv.tv_sec = time(NULL);
134
entry.ut_tv.tv_usec = 0;
142
static int open_master(char *slave_name)
147
if( (fd = open("/dev/ptmx",O_RDWR)) < 0 )
150
if( grantpt(fd) < 0 )
156
if( unlockpt(fd) < 0 )
162
if ( (ptys = (char *)ptsname(fd)) == NULL )
168
strcpy(slave_name,ptys);
172
static int open_slave(int master_fd, char *slave_name)
176
if( (fd = open(slave_name,O_RDWR)) < 0 )
182
if ( ioctl(fd,I_FIND,"ptem") == 0)
183
if ( ioctl(fd,I_PUSH,"ptem") < 0 )
190
if ( ioctl(fd,I_FIND,"ldterm") == 0)
191
if ( ioctl(fd,I_PUSH,"ldterm") < 0 )
198
if ( ioctl(fd,I_FIND,"ttcompat") == 0)
199
if ( ioctl(fd,I_PUSH,"ttcompat") < 0 )
209
static int get_slave_fd(int master_fd, char *slave_name)
216
if( (fd = open_slave(master_fd,slave_name)) < 0 )
222
static int set_window_size(int fd, int width, int height)
224
struct winsize wsize;
226
wsize.ws_col = width;
227
wsize.ws_row = height;
229
if(ioctl(fd,TIOCSWINSZ,&wsize))
235
static int dup_fds(int slave_fd)
238
if (dup2(slave_fd,STDIN_FILENO) != STDIN_FILENO)
241
if (dup2(slave_fd,STDOUT_FILENO) != STDOUT_FILENO)
244
if (dup2(slave_fd,STDERR_FILENO) != STDERR_FILENO)
247
if (slave_fd > STDERR_FILENO)
253
static pid_t child; /* child process id */
254
static char *tty_name;
255
static int tty_read(TerminalIO *tio,char *buf,int size)
259
if(child == 0 || tio == NULL ||
260
tio->concrete_io == NULL || tio->concrete_io->closed)
262
ret = read(tio->concrete_io->fd,buf,size);
264
tio->concrete_io->closed = 1;
268
static int tty_write(TerminalIO *tio,char *buf,int size)
272
if(child == 0 || tio == NULL ||
273
tio->concrete_io == NULL || tio->concrete_io->closed)
275
ret = write(tio->concrete_io->fd,buf,size);
277
tio->concrete_io->closed = 1;
281
static int tty_tell_window_size(TerminalIO *tio,int width, int height)
283
if(tio == NULL || tio->concrete_io == NULL)
285
return set_window_size(tio->concrete_io->fd,width,height);
288
/* to kill child process propery, need to catch signal ;-) */
289
static void finish_child(int signal)
295
if(pid == child || pid == ECHILD)
298
delete_utmp(tty_name);
301
} while((pid = waitpid(child,NULL,WNOHANG)) > 0);
307
TerminalIO* TtyTerminalIO_new(int width,int height,
308
char *program_name, char *argv[])
313
struct Concrete_IO *cio;
317
/* so that TIOCSWINSZ || TIOCSIZE doesn't block */
318
signal(SIGTTOU,SIG_IGN);
320
if ( (master_fd = open_master(slave_name)) < 0 )
323
if ( (tio = malloc(sizeof(TerminalIO))) == NULL )
326
if ( (cio = malloc(sizeof(struct Concrete_IO))) == NULL )
329
strcpy(cio->slave_name,slave_name);
330
tty_name = cio->slave_name;
332
signal(SIGCHLD,finish_child);
333
if ( (pid = fork()) < 0 )
338
child = cio->child = pid;
340
tio->concrete_io = cio;
341
tio->read = tty_read;
342
tio->write = tty_write;
343
tio->tell_window_size = tty_tell_window_size;
344
tio->concrete_io->closed = 0;
351
#if defined(HAVE_LIBUTEMPTER)
352
write_utmp(cio->slave_name,master_fd);
354
write_utmp(cio->slave_name);
356
if ( (fd = get_slave_fd(master_fd,slave_name)) < 0)
359
if ( set_window_size(fd,width,height) < 0 )
362
if ( dup_fds(fd) < 0 )
365
chown(slave_name,getuid(),getgid());
368
signal(SIGINT,SIG_DFL);
369
signal(SIGQUIT,SIG_DFL);
370
signal(SIGCHLD,SIG_DFL);
371
execvp(program_name,argv);
379
void TtyTerminalIO_destroy(TerminalIO *tio)
383
if(!tio->concrete_io->closed)
384
delete_utmp(tio->concrete_io->slave_name);
385
if(tio->concrete_io != NULL)
386
free(tio->concrete_io);
392
* Obtain associated file descriptor
394
int TtyTerminalIO_get_associated_fd(TerminalIO *tio)
396
return tio->concrete_io->fd;