- rewrote the code that searches the for a free pty/tty - it is much cleaner now, as we talked about on the mailing list some time ago. \n- started to apply our styling guide \n- some changes not worth mentioning here and there ;)

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@9534 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
assimil8or
2004-10-27 15:54:47 +00:00
parent 7b5e243a4d
commit ead4f89ebb
2 changed files with 301 additions and 326 deletions
+300 -313
View File
@@ -1,5 +1,6 @@
/* /*
* Copyright (c) 2003-4 Kian Duffy <[email protected]> * Copyright (c) 2003-4 Kian Duffy <[email protected]>
* Copyright (c) 2004 Daniel Furrer <[email protected]>
* Parts Copyright (C) 1998,99 Kazuho Okui and Takashi Murai. * Parts Copyright (C) 1998,99 Kazuho Okui and Takashi Murai.
* *
* Permission is hereby granted, free of charge, to any person obtaining * Permission is hereby granted, free of charge, to any person obtaining
@@ -28,6 +29,7 @@
* *
*/ */
#include <dirent.h>
#include <sys/param.h> #include <sys/param.h>
#include <sys/file.h> #include <sys/file.h>
#include <stdio.h> #include <stdio.h>
@@ -56,7 +58,7 @@ extern char **environ;
char spawn_alert_msg [] = \ char spawn_alert_msg [] = \
"alert --stop " \ "alert --stop " \
"'MuTerminal Error!!\n\ "'Haiku Terminal Error!!\n\
Cannot execute shell [%s].\n\ Cannot execute shell [%s].\n\
Check \"Shell\" in preferance panel.' "\ Check \"Shell\" in preferance panel.' "\
"'Exec /bin/sh' 'Abort'"; "'Exec /bin/sh' 'Abort'";
@@ -68,23 +70,23 @@ Check \"Shell\" in preferance panel.' "\
void void
Setenv (const char *var, const char *value) Setenv (const char *var, const char *value)
{ {
int envindex = 0; int envindex = 0;
const int len = strlen(var); const int len = strlen(var);
const int val_len = strlen (value); const int val_len = strlen (value);
while (environ [envindex] != NULL) { while (environ [envindex] != NULL) {
if (strncmp (environ [envindex], var, len) == 0) { if (strncmp (environ [envindex], var, len) == 0) {
/* found it */ /* found it */
environ[envindex] = (char *)malloc ((unsigned)len + val_len + 1); environ[envindex] = (char *)malloc ((unsigned)len + val_len + 1);
sprintf (environ [envindex], "%s%s", var, value); sprintf (environ [envindex], "%s%s", var, value);
return; return;
} }
envindex ++; envindex ++;
} }
environ [envindex] = (char *) malloc ((unsigned)len + val_len + 1); environ [envindex] = (char *) malloc ((unsigned)len + val_len + 1);
sprintf (environ [envindex], "%s%s", var, value); sprintf (environ [envindex], "%s%s", var, value);
environ [++envindex] = NULL; environ [++envindex] = NULL;
} }
/* /*
@@ -104,10 +106,10 @@ int cp_pipe[2]; /* this pipe is used for child to parent transfer */
/* handshake interface */ /* handshake interface */
typedef struct typedef struct
{ {
int status; /* status of child */ int status; /* status of child */
char msg[256]; /* error message */ char msg[256]; /* error message */
int row; /* terminal rows */ int row; /* terminal rows */
int col; /* Terminal columns */ int col; /* Terminal columns */
} handshake_t; } handshake_t;
/* status of handshake */ /* status of handshake */
@@ -118,356 +120,341 @@ typedef struct
/* global varriables */ /* global varriables */
pid_t sh_pid; pid_t sh_pid;
char tty_name[16]; char tty_name[B_PATH_NAME_LENGTH];
int pfd_num = 0;
int int
spawn_shell (int row, int col, const char *command, const char *coding) spawn_shell (int row, int col, const char *command, const char *coding)
{ {
int done = 0; int done = 0;
char *s; pid_t pgrp;
char *t = 0;
pid_t pgrp;
int master = 0; int master = 0;
int slave; int slave;
struct termios tio; struct termios tio;
struct winsize ws; struct winsize ws;
handshake_t handshake; handshake_t handshake;
char pty_name[16]; int i = 0;
time_t now_time_t;
int i = 0; struct tm *now_time;
time_t now_time_t; int now_hour;
struct tm *now_time;
int now_hour;
char *args[16]; char *args[16];
char com_line[256]; char com_line[256];
char *ptr; char *ptr;
char err_msg[256]; char err_msg[256];
signal (SIGTTOU, SIG_IGN); signal(SIGTTOU, SIG_IGN);
/*
* Get a psuedo-tty. We do this by cycling through all the possible
* names. The oparationg system will not allow us to open a master
* which is already in use, so we simply go until the open successed.
*/
for (s = PTYCHAR1; *s != 0; s++) {
for (t = PTYCHAR2; *t != 0; t++) {
sprintf (pty_name, PTYDEV, *s, *t);
if ((master = open (pty_name, O_RDWR)) >= 0)
goto out;
pfd_num++;
}
}
out:
/*
* If s and t are NULL, we ran out of pseudo ttys before we found
* one we can use
*/
if ((*s == 0) && (*t == 0)) {
printf ("don't found pesudo ttys.");
return -1;
}
/* Change "/dev/pt/XX (master) to "/dev/tt/XX" (slave). */
sprintf (pty_name,"%c%c", *s, *t);
sprintf (tty_name, TTYDEV, *s, *t);
/*
* Get the modes of the current terminal. We will duplicates these
* on the pseudo terminal.
*/
/* Create pipe that be use to handshake */
if ( pipe (pc_pipe) || pipe (cp_pipe)) {
printf ("Could not create handshake pipe.");
return -1;
}
/*
* If set prosess group ID is MuTerminal process ID, MuTerminal
* ignore SIGINT for exec Terminal.
*
* pgrp = getpid ();
* setpgid (0, pgrp);
*/
/* Fork a child process. */
if ((sh_pid=fork()) < 0) {
close (master);
return -1;
}
if (sh_pid == 0) {
/*
* Now in child process.
*/
/* close master pty and control tty. */
// close (tty);
// for (i = 0; i <= 2; i++)
// close (i);
/*
* Make our controlling tty the pseudo tty. This hapens because
* we cleared our original controlling terminal above.
*/
close (cp_pipe[0]);
close (pc_pipe[1]);
/* Set process session leader */
if ((pgrp = setsid()) < 0) {
handshake.status = PTY_NG;
sprintf (handshake.msg, "could not set session leader.");
write (cp_pipe[1], (char *)&handshake, sizeof (handshake));
exit (1);
}
/* change pty owner and asscess mode. */
chown (tty_name, getuid(), getgid());
chmod (tty_name, S_IRUSR | S_IWUSR);
/* open slave pty */
if ((slave = open (tty_name, O_RDWR)) < 0) {
handshake.status = PTY_NG;
sprintf (handshake.msg, "can't open tty (%s).", tty_name);
write (cp_pipe[1], (char *)&handshake, sizeof (handshake));
exit (1);
}
/* get tty termios (don't necessary). */
tcgetattr (slave, &tio);
/* set signal default */
signal (SIGCHLD, SIG_DFL);
signal (SIGHUP, SIG_DFL);
signal (SIGQUIT, SIG_DFL);
signal (SIGTERM, SIG_DFL);
signal (SIGINT, SIG_DFL);
signal (SIGTTOU, SIG_DFL);
/* /*
* Set Terminal interface. * Get a psuedo-tty. We do this by cycling through files in the
*/ * directory. The oparationg system will not allow us to open a master
* which is already in use, so we simply go until the open succeeds.
*/
tio.c_line = 0; DIR *dir;
dir = opendir("/dev/pt/");
struct dirent *dir_entry;
char pty_name[B_PATH_NAME_LENGTH];
while(NULL != (dir_entry = readdir(dir)))
{
if (dir_entry->d_name[0] == '.') // skip . and ..
continue;
sprintf(pty_name, "/dev/pt/%s", dir_entry->d_name);
printf("%s\n", pty_name);
master = open(pty_name, O_RDWR);
if (master >= 0)
break;
}
// If master is still < 0 then we haven't found a tty we can use
if (master < 0)
{
printf("didn't find any available pesudo ttys.");
return -1;
}
// Set the tty that corresponds to the pty we found
sprintf (tty_name, "/dev/tt/%s", dir_entry->d_name);
tio.c_lflag |= ECHOE; /*
* Get the modes of the current terminal. We will duplicates these
* on the pseudo terminal.
*/
/* input: nl->nl, cr->nl */ /* Create pipe that be use to handshake */
tio.c_iflag &= ~(INLCR|IGNCR); if ( pipe (pc_pipe) || pipe (cp_pipe)) {
tio.c_iflag |= ICRNL; printf ("Could not create handshake pipe.");
tio.c_iflag &= ~ISTRIP; return -1;
}
/* Fork a child process. */
if ((sh_pid = fork()) < 0) {
close(master);
return -1;
}
if (sh_pid == 0) {
/*
* Now in child process.
*/
/* output: cr->cr, nl in not retrun, no delays, ln->cr/ln */ /*
tio.c_oflag &= ~(OCRNL|ONLRET|NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY); * Make our controlling tty the pseudo tty. This hapens because
tio.c_oflag |= ONLCR; * we cleared our original controlling terminal above.
tio.c_oflag |= OPOST; */
close(cp_pipe[0]);
close(pc_pipe[1]);
/* Set process session leader */
if ((pgrp = setsid()) < 0) {
handshake.status = PTY_NG;
sprintf(handshake.msg, "could not set session leader.");
write(cp_pipe[1], (char *)&handshake, sizeof (handshake));
exit(1);
}
/* change pty owner and asscess mode. */
chown (tty_name, getuid(), getgid());
chmod (tty_name, S_IRUSR | S_IWUSR);
/* open slave pty */
if ((slave = open (tty_name, O_RDWR)) < 0) {
handshake.status = PTY_NG;
sprintf (handshake.msg, "can't open tty (%s).", tty_name);
write (cp_pipe[1], (char *)&handshake, sizeof (handshake));
exit (1);
}
/* get tty termios (don't necessary). */
tcgetattr (slave, &tio);
/* set signal default */
signal (SIGCHLD, SIG_DFL);
signal (SIGHUP, SIG_DFL);
signal (SIGQUIT, SIG_DFL);
signal (SIGTERM, SIG_DFL);
signal (SIGINT, SIG_DFL);
signal (SIGTTOU, SIG_DFL);
/*
* Set Terminal interface.
*/
tio.c_line = 0;
tio.c_lflag |= ECHOE;
/* input: nl->nl, cr->nl */
tio.c_iflag &= ~(INLCR|IGNCR);
tio.c_iflag |= ICRNL;
tio.c_iflag &= ~ISTRIP;
/* output: cr->cr, nl in not retrun, no delays, ln->cr/ln */
tio.c_oflag &= ~(OCRNL|ONLRET|NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY);
tio.c_oflag |= ONLCR;
tio.c_oflag |= OPOST;
/* baud rate is 19200 (equal beterm) */ /* baud rate is 19200 (equal beterm) */
tio.c_cflag &= ~(CBAUD); tio.c_cflag &= ~(CBAUD);
tio.c_cflag |= B19200; tio.c_cflag |= B19200;
tio.c_cflag &= ~CSIZE; tio.c_cflag &= ~CSIZE;
tio.c_cflag |= CS8; tio.c_cflag |= CS8;
tio.c_cflag |= CREAD; tio.c_cflag |= CREAD;
tio.c_cflag |= HUPCL; tio.c_cflag |= HUPCL;
tio.c_iflag &= ~(IGNBRK|BRKINT); tio.c_iflag &= ~(IGNBRK|BRKINT);
/* /*
* enable signals, canonical processing (erase, kill, etc), echo. * enable signals, canonical processing (erase, kill, etc), echo.
*/ */
tio.c_lflag |= ISIG|ICANON|ECHO|ECHOE|ECHONL; tio.c_lflag |= ISIG|ICANON|ECHO|ECHOE|ECHONL;
tio.c_lflag &= ~ECHOK; tio.c_lflag &= ~ECHOK;
tio.c_lflag &= ~IEXTEN; tio.c_lflag &= ~IEXTEN;
/* set control charactors. */ /* set control charactors. */
tio.c_cc[VINTR] = 'C' & 0x1f; /* '^C' */ tio.c_cc[VINTR] = 'C' & 0x1f; /* '^C' */
tio.c_cc[VQUIT] = CQUIT; /* '^\' */ tio.c_cc[VQUIT] = CQUIT; /* '^\' */
tio.c_cc[VERASE] = 0x08; /* '^H' */ tio.c_cc[VERASE] = 0x08; /* '^H' */
tio.c_cc[VKILL] = 'U' & 0x1f; /* '^U' */ tio.c_cc[VKILL] = 'U' & 0x1f; /* '^U' */
tio.c_cc[VEOF] = CEOF; /* '^D' */ tio.c_cc[VEOF] = CEOF; /* '^D' */
tio.c_cc[VEOL] = CEOL; /* '^@' */ tio.c_cc[VEOL] = CEOL; /* '^@' */
tio.c_cc[VMIN] = 4; tio.c_cc[VMIN] = 4;
tio.c_cc[VTIME] = 0; tio.c_cc[VTIME] = 0;
tio.c_cc[VEOL2] = CEOL; /* '^@' */ tio.c_cc[VEOL2] = CEOL; /* '^@' */
tio.c_cc[VSWTCH] = CSWTCH; /* '^@' */ tio.c_cc[VSWTCH] = CSWTCH; /* '^@' */
tio.c_cc[VSTART] = CSTART; /* '^S' */ tio.c_cc[VSTART] = CSTART; /* '^S' */
tio.c_cc[VSTOP] = CSTOP; /* '^Q' */ tio.c_cc[VSTOP] = CSTOP; /* '^Q' */
tio.c_cc[VSUSP] = CSUSP; /* '^@' */ tio.c_cc[VSUSP] = CSUSP; /* '^@' */
/* /*
* change control tty. * change control tty.
*/ */
dup2 (slave, 0); dup2 (slave, 0);
dup2 (slave, 1); dup2 (slave, 1);
dup2 (slave, 2); dup2 (slave, 2);
/* close old slave fd. */ /* close old slave fd. */
if (slave > 2) if (slave > 2)
close (slave); close (slave);
/* /*
* set terminal interface. * set terminal interface.
*/ */
if (tcsetattr (0, TCSANOW, &tio) == -1) { if (tcsetattr (0, TCSANOW, &tio) == -1) {
handshake.status = PTY_NG; handshake.status = PTY_NG;
sprintf (handshake.msg, "failed set terminal interface (TERMIOS)."); sprintf (handshake.msg, "failed set terminal interface (TERMIOS).");
write (cp_pipe[1], (char *)&handshake, sizeof (handshake)); write (cp_pipe[1], (char *)&handshake, sizeof (handshake));
exit (1); exit (1);
} }
/* /*
* set window size. * set window size.
*/ */
handshake.status = PTY_WS; handshake.status = PTY_WS;
write (cp_pipe[1], (char *)&handshake, sizeof (handshake)); write (cp_pipe[1], (char *)&handshake, sizeof (handshake));
read (pc_pipe[0], (char *)&handshake, sizeof (handshake)); read (pc_pipe[0], (char *)&handshake, sizeof (handshake));
if (handshake.status != PTY_WS) { if (handshake.status != PTY_WS) {
handshake.status = PTY_NG; handshake.status = PTY_NG;
sprintf (handshake.msg, "missmatch handshake."); sprintf (handshake.msg, "missmatch handshake.");
write (cp_pipe[1], (char *)&handshake, sizeof (handshake)); write (cp_pipe[1], (char *)&handshake, sizeof (handshake));
exit (1); exit (1);
} }
ws.ws_row = handshake.row; ws.ws_row = handshake.row;
ws.ws_col = handshake.col; ws.ws_col = handshake.col;
ioctl (0, TIOCSWINSZ, &ws); ioctl (0, TIOCSWINSZ, &ws);
/* /*
* Set process group ID to process, and Terminal Process group ID * Set process group ID to process, and Terminal Process group ID
* to this process group ID (equal process ID). * to this process group ID (equal process ID).
*/ */
pgrp = getpid (); pgrp = getpid();
setpgid (pgrp, pgrp); setpgid(pgrp, pgrp);
tcsetpgrp (0, pgrp); tcsetpgrp(0, pgrp);
/* mark the pipes as close on exec */ /* mark the pipes as close on exec */
fcntl( cp_pipe[1], F_SETFD, 1); fcntl( cp_pipe[1], F_SETFD, 1);
fcntl( pc_pipe[0], F_SETFD, 1); fcntl( pc_pipe[0], F_SETFD, 1);
/* pty open and set termios successful. */ /* pty open and set termios successful. */
handshake.status = PTY_OK; handshake.status = PTY_OK;
write (cp_pipe[1], (char *)&handshake, sizeof (handshake)); write (cp_pipe[1], (char *)&handshake, sizeof (handshake));
/* /*
* setenv TERM and TTY. * setenv TERM and TTY.
*/ */
Setenv ("TERM=", "xterm"); Setenv ("TERM=", "xterm");
Setenv ("TTY=",tty_name); Setenv ("TTY=",tty_name);
Setenv ("TTYPE=", coding); Setenv ("TTYPE=", coding);
/* /*
* If don't set command args, exec SHELL_COMMAND. * If don't set command args, exec SHELL_COMMAND.
*/ */
if (command == NULL) { if (command == NULL) {
command = SHELL_COMMAND; command = SHELL_COMMAND;
} }
memcpy (com_line, command, 256); memcpy (com_line, command, 256);
ptr = com_line; ptr = com_line;
/* /*
* split up the arguments in the command into an artv-like structure. * split up the arguments in the command into an artv-like structure.
*/ */
while (*ptr) { while (*ptr) {
/* Skip white space */ /* Skip white space */
while ((*ptr == ' ') || (*ptr == '\t')) while ((*ptr == ' ') || (*ptr == '\t'))
*ptr++ = 0; *ptr++ = 0;
args[i++] = ptr; args[i++] = ptr;
/* Skip over this word to next white space. */ /* Skip over this word to next white space. */
while ((*ptr != 0) && (*ptr != ' ') && (*ptr != '\t')) while ((*ptr != 0) && (*ptr != ' ') && (*ptr != '\t'))
ptr++; ptr++;
} }
args[i] = NULL; args[i] = NULL;
Setenv ("SHELL=", *args); Setenv ("SHELL=", *args);
/* /*
* Print Welcome MuTerm World! Message. * Print Welcome Message.
* (But, Only print message when MuTerminal coding is UTF8.) * (But, Only print message when MuTerminal coding is UTF8.)
*/ */
now_time_t = time(NULL); now_time_t = time(NULL);
now_time = localtime (&now_time_t); now_time = localtime (&now_time_t);
if (now_time->tm_hour >= 5 && now_time->tm_hour < 11) { if (now_time->tm_hour >= 5 && now_time->tm_hour < 11) {
now_hour = 0; now_hour = 0;
} else if (now_time->tm_hour >= 11 && now_time->tm_hour <= 18 ) { } else if (now_time->tm_hour >= 11 && now_time->tm_hour <= 18 ) {
now_hour = 1; now_hour = 1;
} else { } else {
now_hour = 2; now_hour = 2;
} }
execve (*args, args, environ); execve (*args, args, environ);
/* /*
* Exec failed. * Exec failed.
*/ */
sleep (1); sleep (1);
sprintf (err_msg, spawn_alert_msg, com_line); sprintf (err_msg, spawn_alert_msg, com_line);
if (system (err_msg) == 0) if (system (err_msg) == 0)
execl ("/bin/sh", "/bin/sh", "-login", NULL); execl ("/bin/sh", "/bin/sh", "-login", NULL);
exit (1); exit(1);
} }
/* /*
* In parent Process, Set up the input and output file pointers so * In parent Process, Set up the input and output file pointers so
* that they can write and read the pseudo terminal. * that they can write and read the pseudo terminal.
*/ */
/* close childs's side of the pipe */ /* close childs's side of the pipe */
close (cp_pipe[1]); close(cp_pipe[1]);
close (pc_pipe[0]); close(pc_pipe[0]);
/* /*
* close parent control tty. * close parent control tty.
*/ */
while (!done) { while (!done) {
read (cp_pipe[0], (char *)&handshake, sizeof (handshake)); read (cp_pipe[0], (char *)&handshake, sizeof (handshake));
switch (handshake.status) { switch (handshake.status) {
case PTY_OK: case PTY_OK:
done = 1; done = 1;
break; break;
case PTY_NG: case PTY_NG:
printf ("%s\n", handshake.msg); printf("%s\n", handshake.msg);
done = -1; done = -1;
break; break;
case PTY_WS: case PTY_WS:
handshake.row = row; handshake.row = row;
handshake.col = col; handshake.col = col;
handshake.status = PTY_WS; handshake.status = PTY_WS;
write (pc_pipe[1], (char *)&handshake, sizeof (handshake)); write(pc_pipe[1], (char *)&handshake, sizeof (handshake));
break; break;
} }
} }
return (done > 0) ? master : -1; return (done > 0) ? master : -1;
} }
+1 -13
View File
@@ -1,5 +1,6 @@
/* /*
* Copyright (c) 2003-4 Kian Duffy <[email protected]> * Copyright (c) 2003-4 Kian Duffy <[email protected]>
* Copyright (c) 2004 Daniel Furrer <[email protected]>
* Parts Copyright (C) 1998,99 Kazuho Okui and Takashi Murai. * Parts Copyright (C) 1998,99 Kazuho Okui and Takashi Murai.
* *
* Permission is hereby granted, free of charge, to any person obtaining * Permission is hereby granted, free of charge, to any person obtaining
@@ -31,19 +32,6 @@
#ifndef SPAWN_H #ifndef SPAWN_H
#define SPAWN_H #define SPAWN_H
/*
* allow for mobility of the pty master/slave directories
*/
#define PTYDEV "/dev/pt/%c%c"
#define TTYDEV "/dev/tt/%c%c"
#define PTYCHAR1 "pqrs"
#define PTYCHAR2 "0123456789abcdef"
#define TTYFORMAT "/dev/tt/%d"
#define PTYFORMAT "/dev/pt/%d"
#define MAXPTTYS 16 * 4 #define MAXPTTYS 16 * 4
#ifndef CEOF #ifndef CEOF