home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Source Code 1992 March
/
Source_Code_CD-ROM_Walnut_Creek_March_1992.iso
/
usenet
/
altsrcs
/
2
/
2395
/
sm.c
Wrap
C/C++ Source or Header
|
1990-12-28
|
6KB
|
344 lines
/*
* This code is in the public domain.
*
* Written By: John F Haugh II, 12/21/90
*/
#include <sys/types.h>
#include <sys/termio.h>
#include <stdio.h>
#include <signal.h>
#include <time.h>
#include <fcntl.h>
#include <errno.h>
#define MAXSESSIONS 16
int childpids[MAXSESSIONS];
int writepid;
int masters[MAXSESSIONS];
int nsessions;
int current = -1;
int caught = 0;
struct termio sanetty;
struct termio rawtty;
void exit ();
void _exit ();
char *getlogin ();
char *getenv ();
struct passwd *getpwnam ();
void
murder (sig)
int sig;
{
int pid;
int i;
pid = wait ((int *) 0);
/*
* See what children have died recently.
*/
for (i = 0;pid != -1 && i < nsessions;i++) {
if (pid == childpids[i]) {
childpids[i] = -1;
close (masters[i]);
masters[i] = -1;
}
}
signal (sig, murder);
}
void
catch (sig)
int sig;
{
caught = 1;
signal (sig, catch);
}
/*
* reader - read characters from the pty and write to the screen
*/
int
reader (fd)
int fd;
{
char c;
int cnt;
signal (SIGINT, SIG_IGN);
signal (SIGQUIT, SIG_IGN);
while (1) {
if ((cnt = read (fd, &c, 1)) == -1) {
if (errno != EINTR)
return -1;
if (caught)
return 0;
else
continue;
}
if (cnt == 0)
return -1;
write (1, &c, 1);
}
}
/*
* writer - write characters read from the keyboard down the pty
*/
writer (fd)
int fd;
{
char c;
int cnt;
int zflg = 0;
signal (SIGINT, SIG_IGN);
signal (SIGQUIT, SIG_IGN);
signal (SIGHUP, _exit);
while (1) {
errno = 0;
if ((cnt = read (0, &c, 1)) == 0)
continue;
if (cnt == -1) {
if (errno == EINTR && caught)
continue;
else
exit (0);
}
if (c == ('z' & 037)) {
if (! zflg++)
continue;
} else if (zflg) {
kill (getppid (), SIGUSR1);
exit (0);
}
zflg = 0;
if (write (fd, &c, 1) != 1)
break;
}
exit (0);
}
usage ()
{
fprintf (stderr, "usage: ptymgr\n");
exit (1);
}
session ()
{
char mastername[BUFSIZ];
char slavename[BUFSIZ];
char *digits = "0123456789abcdef";
char *letters = "pqrs";
char *shell;
int i;
int pty;
int ptys = 64;
for (i = 0;i < nsessions && masters[i] != -1;i++)
;
if (i == MAXSESSIONS)
return -1;
if (i == nsessions)
nsessions++;
current = i;
for (pty = 0;pty < ptys;pty++) {
sprintf (mastername, "/dev/pty%c%c",
letters[pty >> 4], digits[pty & 0xf]);
if ((masters[i] = open (mastername, O_RDWR)) != -1)
break;
}
if (masters[i] == -1) {
fprintf (stderr, "Can't find a pty\n");
return -1;
}
/*
* Let's make a child process ...
*/
switch (childpids[i] = fork ()) {
case -1:
perror ("fork");
exit (1);
case 0:
close (0);
close (1);
for (i = 0;i < nsessions;i++)
close (masters[i]);
setpgrp ();
signal (SIGINT, SIG_DFL);
signal (SIGQUIT, SIG_DFL);
signal (SIGCLD, SIG_DFL);
signal (SIGHUP, SIG_DFL);
signal (SIGUSR1, SIG_DFL);
sprintf (slavename, "/dev/tty%c%c",
letters[pty >> 4], digits[pty & 0xf]);
if (open (slavename, O_RDWR) == -1) {
fprintf (stderr, "can't open %s\n", slavename);
_exit (-1);
}
close (2);
dup (0);
dup (0);
ioctl (0, TCSETAF, &sanetty);
if (! (shell = getenv ("SHELL")))
shell = "/bin/sh";
execl (shell, strrchr (shell, '/') + 1, 0);
_exit (-1);
}
}
main (argc, argv)
int argc;
char **argv;
{
char buf[BUFSIZ];
char *cp;
int i;
int pid;
for (i = 0;i < MAXSESSIONS;i++) {
childpids[i] = -1;
masters[i] = -1;
}
ioctl (0, TCGETA, &sanetty);
rawtty = sanetty;
/*
* Let's have our own little process group
*/
setpgrp ();
rawtty.c_oflag &= ~OPOST;
rawtty.c_lflag = 0;
rawtty.c_cc[VMIN] = 1;
rawtty.c_cc[VTIME] = 1;
signal (SIGCLD, murder);
signal (SIGUSR1, catch);
while (1) {
printf ("pty-> ");
fflush (stdout);
while (errno = 0, gets (buf) == 0) {
if (errno == EINTR)
continue;
else
exit (0);
}
if (! buf[0])
continue;
/*
* Get the command
*/
if (strcmp (buf, "quit") == 0 || strcmp (buf, "exit") == 0) {
exit (0);
} else if (strcmp (buf, "create") == 0) {
session ();
continue;
} else if (strcmp (buf, "current") == 0) {
printf ("current session is %d\n", current);
continue;
} else if (strncmp (buf, "set", 3) == 0) {
i = strtol (buf + 3, &cp, 10);
if (buf[3] != '\0' && *cp == '\0')
current = i;
else
printf ("eh?\n");
continue;
} else if (strcmp (buf, "active") == 0) {
for (i = 0;i < nsessions;i++)
if (masters[i] != -1)
printf ("%d ", i);
putchar ('\n');
continue;
} else if (strcmp (buf, "jobs") == 0) {
int pids = 0;
strcpy (buf, "ps -fp ");
for (i = 0;i < nsessions;i++) {
if (childpids[i] != -1) {
if (pids++)
strcat (buf, ",");
sprintf (buf + strlen (buf), "%d",
childpids[i]);
}
}
if (pids)
system (buf);
continue;
} else if (strncmp (buf, "connect", 7) != 0) {
printf ("eh?\n");
continue;
}
i = strtol (buf + 2, &cp, 10);
if (*cp == '\0' && buf[2]) {
if (masters[i] != -1)
current = i;
else
current = -1;
}
if (current == -1) {
printf ("no current session\n");
continue;
}
/*
* Let's make a process to read from the child ...
*/
switch (writepid = fork ()) {
case -1:
kill (childpids[current], SIGKILL);
perror ("fork");
break;
case 0:
writer (masters[current]);
exit (1);
}
ioctl (0, TCSETAF, &rawtty);
if (reader (masters[current]) == -1) {
close (masters[current]);
masters[current] = -1;
childpids[current] = -1;
current = -1;
if (writepid > 0)
kill (writepid, SIGTERM);
}
ioctl (0, TCSETA, &sanetty);
}
exit (0);
}