From ead4f89ebbbd2f428d2a6a99827a30e955bf7737 Mon Sep 17 00:00:00 2001 From: assimil8or Date: Wed, 27 Oct 2004 15:54:47 +0000 Subject: [PATCH] - 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 --- src/apps/terminal/MYOB/spawn.cpp | 613 +++++++++++++++---------------- src/apps/terminal/MYOB/spawn.h | 14 +- 2 files changed, 301 insertions(+), 326 deletions(-) diff --git a/src/apps/terminal/MYOB/spawn.cpp b/src/apps/terminal/MYOB/spawn.cpp index b721abe90a..370e82eaa7 100644 --- a/src/apps/terminal/MYOB/spawn.cpp +++ b/src/apps/terminal/MYOB/spawn.cpp @@ -1,5 +1,6 @@ /* * Copyright (c) 2003-4 Kian Duffy + * Copyright (c) 2004 Daniel Furrer * Parts Copyright (C) 1998,99 Kazuho Okui and Takashi Murai. * * Permission is hereby granted, free of charge, to any person obtaining @@ -28,6 +29,7 @@ * */ +#include #include #include #include @@ -56,7 +58,7 @@ extern char **environ; char spawn_alert_msg [] = \ "alert --stop " \ -"'MuTerminal Error!!\n\ +"'Haiku Terminal Error!!\n\ Cannot execute shell [%s].\n\ Check \"Shell\" in preferance panel.' "\ "'Exec /bin/sh' 'Abort'"; @@ -68,23 +70,23 @@ Check \"Shell\" in preferance panel.' "\ void Setenv (const char *var, const char *value) { - int envindex = 0; - const int len = strlen(var); - const int val_len = strlen (value); + int envindex = 0; + const int len = strlen(var); + const int val_len = strlen (value); - while (environ [envindex] != NULL) { - if (strncmp (environ [envindex], var, len) == 0) { - /* found it */ - environ[envindex] = (char *)malloc ((unsigned)len + val_len + 1); - sprintf (environ [envindex], "%s%s", var, value); - return; - } - envindex ++; - } - - environ [envindex] = (char *) malloc ((unsigned)len + val_len + 1); - sprintf (environ [envindex], "%s%s", var, value); - environ [++envindex] = NULL; + while (environ [envindex] != NULL) { + if (strncmp (environ [envindex], var, len) == 0) { + /* found it */ + environ[envindex] = (char *)malloc ((unsigned)len + val_len + 1); + sprintf (environ [envindex], "%s%s", var, value); + return; + } + envindex ++; + } + + environ [envindex] = (char *) malloc ((unsigned)len + val_len + 1); + sprintf (environ [envindex], "%s%s", var, value); + environ [++envindex] = NULL; } /* @@ -104,10 +106,10 @@ int cp_pipe[2]; /* this pipe is used for child to parent transfer */ /* handshake interface */ typedef struct { - int status; /* status of child */ - char msg[256]; /* error message */ - int row; /* terminal rows */ - int col; /* Terminal columns */ + int status; /* status of child */ + char msg[256]; /* error message */ + int row; /* terminal rows */ + int col; /* Terminal columns */ } handshake_t; /* status of handshake */ @@ -118,356 +120,341 @@ typedef struct /* global varriables */ pid_t sh_pid; -char tty_name[16]; -int pfd_num = 0; +char tty_name[B_PATH_NAME_LENGTH]; int spawn_shell (int row, int col, const char *command, const char *coding) { - int done = 0; - char *s; - char *t = 0; - pid_t pgrp; + int done = 0; + pid_t pgrp; - int master = 0; - int slave; - struct termios tio; - struct winsize ws; + int master = 0; + int slave; + struct termios tio; + struct winsize ws; - handshake_t handshake; + handshake_t handshake; - char pty_name[16]; - - int i = 0; - time_t now_time_t; - struct tm *now_time; - int now_hour; + int i = 0; + time_t now_time_t; + struct tm *now_time; + int now_hour; - char *args[16]; - char com_line[256]; - char *ptr; + char *args[16]; + char com_line[256]; + 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 */ - tio.c_iflag &= ~(INLCR|IGNCR); - tio.c_iflag |= ICRNL; - tio.c_iflag &= ~ISTRIP; + /* Create pipe that be use to handshake */ + if ( pipe (pc_pipe) || pipe (cp_pipe)) { + printf ("Could not create handshake pipe."); + 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); - tio.c_oflag |= ONLCR; - tio.c_oflag |= OPOST; + /* + * 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. + */ + + 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) */ - tio.c_cflag &= ~(CBAUD); - tio.c_cflag |= B19200; + /* baud rate is 19200 (equal beterm) */ + tio.c_cflag &= ~(CBAUD); + tio.c_cflag |= B19200; - tio.c_cflag &= ~CSIZE; - tio.c_cflag |= CS8; - tio.c_cflag |= CREAD; + tio.c_cflag &= ~CSIZE; + tio.c_cflag |= CS8; + tio.c_cflag |= CREAD; - tio.c_cflag |= HUPCL; - tio.c_iflag &= ~(IGNBRK|BRKINT); + tio.c_cflag |= HUPCL; + tio.c_iflag &= ~(IGNBRK|BRKINT); - /* - * enable signals, canonical processing (erase, kill, etc), echo. - */ - tio.c_lflag |= ISIG|ICANON|ECHO|ECHOE|ECHONL; - tio.c_lflag &= ~ECHOK; + /* + * enable signals, canonical processing (erase, kill, etc), echo. + */ + tio.c_lflag |= ISIG|ICANON|ECHO|ECHOE|ECHONL; + tio.c_lflag &= ~ECHOK; - tio.c_lflag &= ~IEXTEN; + tio.c_lflag &= ~IEXTEN; - /* set control charactors. */ - tio.c_cc[VINTR] = 'C' & 0x1f; /* '^C' */ - tio.c_cc[VQUIT] = CQUIT; /* '^\' */ - tio.c_cc[VERASE] = 0x08; /* '^H' */ - tio.c_cc[VKILL] = 'U' & 0x1f; /* '^U' */ - tio.c_cc[VEOF] = CEOF; /* '^D' */ - tio.c_cc[VEOL] = CEOL; /* '^@' */ - tio.c_cc[VMIN] = 4; - tio.c_cc[VTIME] = 0; - tio.c_cc[VEOL2] = CEOL; /* '^@' */ - tio.c_cc[VSWTCH] = CSWTCH; /* '^@' */ - tio.c_cc[VSTART] = CSTART; /* '^S' */ - tio.c_cc[VSTOP] = CSTOP; /* '^Q' */ - tio.c_cc[VSUSP] = CSUSP; /* '^@' */ + /* set control charactors. */ + tio.c_cc[VINTR] = 'C' & 0x1f; /* '^C' */ + tio.c_cc[VQUIT] = CQUIT; /* '^\' */ + tio.c_cc[VERASE] = 0x08; /* '^H' */ + tio.c_cc[VKILL] = 'U' & 0x1f; /* '^U' */ + tio.c_cc[VEOF] = CEOF; /* '^D' */ + tio.c_cc[VEOL] = CEOL; /* '^@' */ + tio.c_cc[VMIN] = 4; + tio.c_cc[VTIME] = 0; + tio.c_cc[VEOL2] = CEOL; /* '^@' */ + tio.c_cc[VSWTCH] = CSWTCH; /* '^@' */ + tio.c_cc[VSTART] = CSTART; /* '^S' */ + tio.c_cc[VSTOP] = CSTOP; /* '^Q' */ + tio.c_cc[VSUSP] = CSUSP; /* '^@' */ - /* - * change control tty. - */ + /* + * change control tty. + */ - dup2 (slave, 0); - dup2 (slave, 1); - dup2 (slave, 2); + dup2 (slave, 0); + dup2 (slave, 1); + dup2 (slave, 2); - /* close old slave fd. */ - if (slave > 2) - close (slave); + /* close old slave fd. */ + if (slave > 2) + close (slave); - /* - * set terminal interface. - */ - if (tcsetattr (0, TCSANOW, &tio) == -1) { - handshake.status = PTY_NG; - sprintf (handshake.msg, "failed set terminal interface (TERMIOS)."); - write (cp_pipe[1], (char *)&handshake, sizeof (handshake)); - exit (1); - } + /* + * set terminal interface. + */ + if (tcsetattr (0, TCSANOW, &tio) == -1) { + handshake.status = PTY_NG; + sprintf (handshake.msg, "failed set terminal interface (TERMIOS)."); + write (cp_pipe[1], (char *)&handshake, sizeof (handshake)); + exit (1); + } - /* - * set window size. - */ + /* + * set window size. + */ - handshake.status = PTY_WS; - write (cp_pipe[1], (char *)&handshake, sizeof (handshake)); - read (pc_pipe[0], (char *)&handshake, sizeof (handshake)); + handshake.status = PTY_WS; + write (cp_pipe[1], (char *)&handshake, sizeof (handshake)); + read (pc_pipe[0], (char *)&handshake, sizeof (handshake)); - if (handshake.status != PTY_WS) { - handshake.status = PTY_NG; - sprintf (handshake.msg, "missmatch handshake."); - write (cp_pipe[1], (char *)&handshake, sizeof (handshake)); - exit (1); - } + if (handshake.status != PTY_WS) { + handshake.status = PTY_NG; + sprintf (handshake.msg, "missmatch handshake."); + write (cp_pipe[1], (char *)&handshake, sizeof (handshake)); + exit (1); + } - ws.ws_row = handshake.row; - ws.ws_col = handshake.col; + ws.ws_row = handshake.row; + ws.ws_col = handshake.col; - ioctl (0, TIOCSWINSZ, &ws); + ioctl (0, TIOCSWINSZ, &ws); - /* - * Set process group ID to process, and Terminal Process group ID - * to this process group ID (equal process ID). - */ + /* + * Set process group ID to process, and Terminal Process group ID + * to this process group ID (equal process ID). + */ - pgrp = getpid (); - setpgid (pgrp, pgrp); - tcsetpgrp (0, pgrp); + pgrp = getpid(); + setpgid(pgrp, pgrp); + tcsetpgrp(0, pgrp); - /* mark the pipes as close on exec */ - fcntl( cp_pipe[1], F_SETFD, 1); - fcntl( pc_pipe[0], F_SETFD, 1); + /* mark the pipes as close on exec */ + fcntl( cp_pipe[1], F_SETFD, 1); + fcntl( pc_pipe[0], F_SETFD, 1); - /* pty open and set termios successful. */ - handshake.status = PTY_OK; - write (cp_pipe[1], (char *)&handshake, sizeof (handshake)); + /* pty open and set termios successful. */ + handshake.status = PTY_OK; + write (cp_pipe[1], (char *)&handshake, sizeof (handshake)); - /* - * setenv TERM and TTY. - */ - Setenv ("TERM=", "xterm"); - Setenv ("TTY=",tty_name); - Setenv ("TTYPE=", coding); + /* + * setenv TERM and TTY. + */ + Setenv ("TERM=", "xterm"); + Setenv ("TTY=",tty_name); + Setenv ("TTYPE=", coding); - /* - * If don't set command args, exec SHELL_COMMAND. - */ - if (command == NULL) { - command = SHELL_COMMAND; - } + /* + * If don't set command args, exec SHELL_COMMAND. + */ + if (command == NULL) { + command = SHELL_COMMAND; + } - memcpy (com_line, command, 256); - ptr = com_line; + memcpy (com_line, command, 256); + 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) { - /* Skip white space */ - while ((*ptr == ' ') || (*ptr == '\t')) - *ptr++ = 0; - args[i++] = ptr; + while (*ptr) { + /* Skip white space */ + while ((*ptr == ' ') || (*ptr == '\t')) + *ptr++ = 0; + args[i++] = ptr; - /* Skip over this word to next white space. */ - while ((*ptr != 0) && (*ptr != ' ') && (*ptr != '\t')) - ptr++; - } + /* Skip over this word to next white space. */ + while ((*ptr != 0) && (*ptr != ' ') && (*ptr != '\t')) + ptr++; + } - args[i] = NULL; + args[i] = NULL; - Setenv ("SHELL=", *args); + Setenv ("SHELL=", *args); - /* - * Print Welcome MuTerm World! Message. - * (But, Only print message when MuTerminal coding is UTF8.) - */ - now_time_t = time(NULL); - now_time = localtime (&now_time_t); + /* + * Print Welcome Message. + * (But, Only print message when MuTerminal coding is UTF8.) + */ + now_time_t = time(NULL); + now_time = localtime (&now_time_t); - if (now_time->tm_hour >= 5 && now_time->tm_hour < 11) { - now_hour = 0; - } else if (now_time->tm_hour >= 11 && now_time->tm_hour <= 18 ) { - now_hour = 1; - } else { - now_hour = 2; - } + if (now_time->tm_hour >= 5 && now_time->tm_hour < 11) { + now_hour = 0; + } else if (now_time->tm_hour >= 11 && now_time->tm_hour <= 18 ) { + now_hour = 1; + } else { + now_hour = 2; + } - execve (*args, args, environ); + execve (*args, args, environ); - /* - * Exec failed. - */ - sleep (1); - sprintf (err_msg, spawn_alert_msg, com_line); + /* + * Exec failed. + */ + sleep (1); + sprintf (err_msg, spawn_alert_msg, com_line); - if (system (err_msg) == 0) - execl ("/bin/sh", "/bin/sh", "-login", NULL); + if (system (err_msg) == 0) + execl ("/bin/sh", "/bin/sh", "-login", NULL); - exit (1); - } + exit(1); + } - /* - * In parent Process, Set up the input and output file pointers so - * that they can write and read the pseudo terminal. - */ + /* + * In parent Process, Set up the input and output file pointers so + * that they can write and read the pseudo terminal. + */ - /* close childs's side of the pipe */ - close (cp_pipe[1]); - close (pc_pipe[0]); + /* close childs's side of the pipe */ + close(cp_pipe[1]); + close(pc_pipe[0]); - /* - * close parent control tty. - */ + /* + * close parent control tty. + */ - while (!done) { - read (cp_pipe[0], (char *)&handshake, sizeof (handshake)); + while (!done) { + read (cp_pipe[0], (char *)&handshake, sizeof (handshake)); - switch (handshake.status) { - case PTY_OK: - done = 1; - break; + switch (handshake.status) { + case PTY_OK: + done = 1; + break; - case PTY_NG: - printf ("%s\n", handshake.msg); - done = -1; - break; + case PTY_NG: + printf("%s\n", handshake.msg); + done = -1; + break; - case PTY_WS: - handshake.row = row; - handshake.col = col; - handshake.status = PTY_WS; - write (pc_pipe[1], (char *)&handshake, sizeof (handshake)); - break; - } - } + case PTY_WS: + handshake.row = row; + handshake.col = col; + handshake.status = PTY_WS; + write(pc_pipe[1], (char *)&handshake, sizeof (handshake)); + break; + } + } - return (done > 0) ? master : -1; + return (done > 0) ? master : -1; } diff --git a/src/apps/terminal/MYOB/spawn.h b/src/apps/terminal/MYOB/spawn.h index e3ada6f64c..5941b1940f 100644 --- a/src/apps/terminal/MYOB/spawn.h +++ b/src/apps/terminal/MYOB/spawn.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2003-4 Kian Duffy + * Copyright (c) 2004 Daniel Furrer * Parts Copyright (C) 1998,99 Kazuho Okui and Takashi Murai. * * Permission is hereby granted, free of charge, to any person obtaining @@ -31,19 +32,6 @@ #ifndef 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 #ifndef CEOF