Commit 4ea99ec4 by O'Reilly Media, Inc.

Initial commit

parents
9781565923218
\ No newline at end of file
The ptysh-linux.c and ptysh-sysv.c files
are what is contained in the ptysh.tar.gz file.
## Example files for the title:
# Using and Managing PPP, by Andrew Sun
[![Using and Managing PPP, by Andrew Sun](http://akamaicovers.oreilly.com/images/9781565923218/cat.gif)](https://www.safaribooksonline.com/)
The following applies to example files from material published by O’Reilly Media, Inc. Content from other publishers may include different rules of usage. Please refer to any additional usage rights explained in the actual example files or refer to the publisher’s website.
O'Reilly books are here to help you get your job done. In general, you may use the code in O'Reilly books in your programs and documentation. You do not need to contact us for permission unless you're reproducing a significant portion of the code. For example, writing a program that uses several chunks of code from our books does not require permission. Answering a question by citing our books and quoting example code does not require permission. On the other hand, selling or distributing a CD-ROM of examples from O'Reilly books does require permission. Incorporating a significant amount of example code from our books into your product's documentation does require permission.
We appreciate, but do not require, attribution. An attribution usually includes the title, author, publisher, and ISBN.
If you think your use of code examples falls outside fair use or the permission given here, feel free to contact us at <permissions@oreilly.com>.
Please note that the examples are not production code and have not been carefully testing. They are provided "as-is" and come with no warranty of any kind.
logo.png

2.82 KB

/*
ptysh.c "Pseudo Terminal Shell"
For Linux Slackware 3.4
Compile with "cc -o ptysh ptysh.c"
Author: Andrew Sun
Revision: January 17, 1996, January 10, 1998, June 1, 1998
Description:
This program enables the /bin/sh command interpreter to
emulate a "terminal device". Tip, cu, the UUCP environment,
and PPP normally interact with serial interfaces via terminal
device files, such as /dev/cua1. Rather than limiting these
applications to physical serial interfaces, "ptysh" enables them
to interact with the shell (/bin/sh), and with TCP/IP communication
programs, including telnet and rlogin.
Usage:
Once ptysh is active, an application accessing the serial pty
device /dev/ttyr0 will interact with /bin/sh. At this point,
an application's chat script can "exec telnet" or "exec rlogin"
to establish communications over a network.
*/
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/termio.h>
#include <sys/types.h>
#include <sys/time.h>
main(argc,argv)
int argc;
char *argv[];
{
int shellpid;
char iobuf12[2000], iobuf21[2000];
char *iobuf12p, *iobuf21p;
int iofdcnt, iowrcnt, iordcnt12, iordcnt21;
int fd1m, fd2m, fd2s;
fd_set readfds, writefds;
for (;;) {
/* Create serial interface ptys */
if ( (fd1m = open("/dev/ptyr0",O_RDWR)) < 0 ) {
perror("open serial pty master /dev/ptyr0");
exit(1);
}
printf("serial pty: %s\n", "/dev/ttyr0");
/* Detect "open" for serial pty slave */
FD_ZERO (&readfds);
FD_ZERO (&writefds);
FD_SET (fd1m, &readfds);
/* FD_SET (fd1m, &writefds); */ /* Remove this if wait for open fails */
while ( select (64, &readfds , &writefds, (fd_set *) 0, NULL) < 1 )
;
/* Create shell ptys */
if ( (fd2m = open("/dev/ptyr1",O_RDWR)) < 0 ) {
perror("open shell pty master /dev/ptyr1");
exit(1);
}
/* printf("shell pty: %s\n", "/dev/ttyr1"); */
/* Invoke /bin/sh as a subprocess */
if (! (shellpid = fork()) ) {
close (fd1m);
close (fd2m);
setsid();
if ( (fd2s = open("/dev/ttyr1",O_RDWR)) < 0 ) {
perror("open shell pty slave /dev/ttyr1");
exit(1);
}
dup2 (fd2s, 0); /* stdin */
dup2 (fd2s, 1); /* stdout */
dup2 (fd2s, 2); /* stderr */
system ("stty sane");
execl ("/bin/sh", "sh", (char *) 0);
}
iordcnt12 = 0; /* I/O read character count, fd1m to fd2m */
iordcnt21 = 0; /* I/O read character count, fd2m to fd1m */
for (;;) {
FD_ZERO ( &readfds );
FD_ZERO ( &writefds );
if (iordcnt12) {
FD_SET (fd2m, &writefds);
} else {
FD_SET (fd1m, &readfds);
}
if (iordcnt21) {
FD_SET (fd1m, &writefds);
} else {
FD_SET (fd2m, &readfds);
}
iofdcnt = select (64, &readfds, &writefds, (fd_set *) 0, NULL);
if ( iofdcnt < 0 )
if ( errno == EINTR ) continue;
else {
perror("select"); exit(1);
}
if ( FD_ISSET (fd1m, &readfds) ) {
/* Read from fd1m data to be written to fd2m */
iobuf12p = iobuf12;
iordcnt12 = read (fd1m, iobuf12, 2000);
if ( iordcnt12 <= 0 ) break;
}
if ( FD_ISSET (fd1m, &writefds) ) {
/* Write to fd1m with data read from fd2m */
iowrcnt = write (fd1m, iobuf21p, iordcnt21);
if ( iowrcnt <= 0 ) break;
iordcnt21 -= iowrcnt;
iobuf21p += iowrcnt;
}
if ( FD_ISSET (fd2m, &readfds) ) {
/* Read from fd2m data to be written to fd1m */
iobuf21p = iobuf21;
iordcnt21 = read (fd2m, iobuf21, 2000);
if ( iordcnt21 <= 0 ) break;
}
if ( FD_ISSET (fd2m, &writefds) ) {
/* Write to fd2m with data read from fd1m */
iowrcnt = write (fd2m, iobuf12p, iordcnt12);
if ( iowrcnt <= 0 ) break;
iordcnt12 -= iowrcnt;
iobuf12p += iowrcnt;
}
}
close (fd1m);
close (fd2m);
sleep(3); /* Delay for pty close */
wait(NULL);
}
}
/*
ptysh.c "Pseudo Terminal Shell"
For UNIX System V variants (Sun Microsystem's Solaris 2.5).
Compile with "cc -o ptysh ptysh.c"
Author: Andrew Sun
Revision: January 10, 1998
Description:
This program enables the /bin/sh command interpreter to
emulate a "terminal device". Tip, cu, the UUCP environment,
and PPP normally interact with serial interfaces via terminal
device files, such as /dev/cua/b. Rather than limiting these
applications to physical serial interfaces, "ptysh" enables them
to interact with the shell (/bin/sh), and with TCP/IP communication
programs, including telnet and rlogin.
Usage:
Once ptysh is active, an application accessing the serial pty
device it reports will interact with /bin/sh. At this point,
an application's chat script can "exec telnet" or "exec rlogin"
to establish communications over a network.
*/
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stropts.h>
#include <poll.h>
char *ptsname(int fildes);
main(argc,argv)
int argc;
char *argv[];
{
int shellpid;
char iobuf12[2000], iobuf21[2000];
char *iobuf12p, *iobuf21p;
int iofdcnt, iowrcnt, iordcnt12, iordcnt21;
int fd1m, fd1s, fd2m, fd2s;
char *slavename;
struct pollfd fds[2];
unsigned long nfds;
int timeout;
for (;;) {
/* Create serial interface ptys */
if ( (fd1m = open("/dev/ptmx", O_RDWR)) < 0 ) {
perror("open serial pty master"); exit(1);
}
grantpt(fd1m); unlockpt(fd1m);
if ( (slavename = ptsname(fd1m)) == NULL ) {
perror("can't determine serial pty"); exit(1);
}
printf("serial pty: %s\n", slavename);
if ( (fd1s = open(slavename,O_RDWR)) < 0 ) {
perror("open serial pty slave"); exit(1);
}
ioctl(fd1s, I_PUSH, "ptem");
ioctl(fd1s, I_PUSH, "ldterm");
/* Detect "open" for serial pty slave */
fds[0].fd = fd1m;
fds[0].events = POLLIN;
nfds = 1; timeout = -1;
poll(fds, nfds, timeout);
close (fd1s); /* Application has serial pty slave now */
/* Create shell ptys */
if ( (fd2m = open("/dev/ptmx", O_RDWR)) < 0 ) {
perror("open shell pty master"); exit(1);
}
grantpt(fd2m); unlockpt(fd2m);
if ( (slavename = ptsname(fd2m)) == NULL ) {
perror("can't determine shell pty"); exit(1);
}
/* printf("shell pty: %s\n", slavename); */
/* Invoke /bin/sh as a subprocess */
if (! (shellpid = fork()) ) {
close (fd1m);
close (fd2m);
setsid();
if ( (fd2s = open(slavename,O_RDWR)) < 0 ) {
perror("open shell pty slave"); exit(1);
}
ioctl(fd2s, I_PUSH, "ptem");
ioctl(fd2s, I_PUSH, "ldterm");
dup2 (fd2s, 0); /* stdin */
dup2 (fd2s, 1); /* stdout */
dup2 (fd2s, 2); /* stderr */
system ("stty sane");
execl ("/bin/sh", "sh", (char *) 0);
}
iordcnt12 = 0; /* I/O read character count, fd1m to fd2m */
iordcnt21 = 0; /* I/O read character count, fd2m to fd1m */
for (;;) {
fds[0].fd = fd1m; fds[1].fd = fd2m;
fds[0].events = fds[1].events = 0;
nfds = 2; timeout = -1;
if (iordcnt12) {
fds[1].events |= POLLOUT;
} else {
fds[0].events |= POLLIN;
}
if (iordcnt21) {
fds[0].events |= POLLOUT;
} else {
fds[1].events |= POLLIN;
}
iofdcnt = poll(fds, nfds, timeout);
if ( iofdcnt < 0 )
if ( errno == EINTR ) continue;
else {
perror("poll"); exit(1);
}
if ( fds[0].revents & POLLIN ) {
/* Read from fd1m data to be written to fd2m */
iobuf12p = iobuf12;
iordcnt12 = read (fd1m, iobuf12, 2000);
if ( iordcnt12 <= 0 ) break;
}
if ( fds[0].revents & POLLOUT ) {
/* Write to fd1m with data read from fd2m */
iowrcnt = write (fd1m, iobuf21p, iordcnt21);
if ( iowrcnt <= 0 ) break;
iordcnt21 -= iowrcnt;
iobuf21p += iowrcnt;
}
if ( fds[1].revents & POLLIN ) {
/* Read from fd2m data to be written to fd1m */
iobuf21p = iobuf21;
iordcnt21 = read (fd2m, iobuf21, 2000);
if ( iordcnt21 <= 0 ) break;
}
if ( fds[1].revents & POLLOUT ) {
/* Write to fd2m with data read from fd1m */
iowrcnt = write (fd2m, iobuf12p, iordcnt12);
if ( iowrcnt <= 0 ) break;
iordcnt12 -= iowrcnt;
iobuf12p += iowrcnt;
}
}
close (fd1m);
close (fd2m);
sleep(3); /* Delay for pty close */
wait();
}
}
File added
/*
ptysh.c "Pseudo Terminal Shell" v2
"Using & Managing PPP," O'Reilly & Associates, March 1999
http://www.oreilly.com/
This example is for LINUX variants with the 2.0 series kernel.
It assumes BSD style pty device names in the form of /dev/ptyXX and
/dev/ttyXX. The example is also compatible with LINUX 2.2 series
kernels with BSD style ptys enabled. Compile with "gcc -o ptysh ptysh.c"
Author: Andrew Sun
Revision: January 17, 1996, January 10, 1998, June 1, 1998
Revision: September 11, 2000, Version 2 update,
Link dynamically allocated pty to user specified symbolic link
Description:
This program enables the /bin/sh command interpreter to
emulate a "terminal device". Tip, cu, the UUCP environment,
and PPP normally interact with serial interfaces via terminal
device files, such as /dev/ttyS0. Rather than limiting these
applications to physical serial interfaces, "ptysh" enables them
to interact with the shell (/bin/sh), and with TCP/IP communication
programs, including telnet and rlogin.
Usage:
Once ptysh is active, ptysh maintains a user specified symbolic
link to a pseudo terminal. Applications accessing the symbolic
link as a serial device will interact with /bin/sh. At this point,
an application's chat script can "exec telnet," "exec rlogin,"
or invoke an alternate utility to establish communications over a network.
Security note:
This ptysh requires setuid root privileges to set ownership and
permissions of slave pty devices.
*/
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <signal.h>
char *ptyalias;
void exitreq(int sig)
{
unlink(ptyalias);
exit(0);
}
main(int argc, char *argv[])
{
int shellpid;
uid_t uid; /* Our real UID */
char iobuf12[2000], iobuf21[2000];
char *iobuf12p, *iobuf21p;
int iofdcnt, iowrcnt, iordcnt12, iordcnt21;
int fd1m, fd1s, fd2m, fd2s;
char mastername[12], slavename[12];
struct stat statbuf;
fd_set readfds, writefds;
void (*sigvold)();
seteuid( uid=getuid() ); /* Run unprivileged */
/* Command line options */
if (argc < 2 ) {
fprintf(stderr, "Usage: %s /dev/ptyalias\n", argv[0]);
exit(1);
}
ptyalias = argv[1];
/* Pty alias file must not already exist */
if ( lstat(ptyalias, &statbuf) >= 0) {
fprintf(stderr, "File %s exists\n", ptyalias);
exit(1);
}
/* Set signal handling */
sigvold = signal(SIGINT, SIG_IGN);
if ( sigvold == SIG_DFL ) {
signal(SIGINT, exitreq);
}
signal(SIGTERM, exitreq);
signal(SIGHUP, SIG_IGN);
for (;;) {
/* Create serial interface ptys */
if ( (fd1m = getpty(mastername)) < 0 ) {
perror("open serial pty master"); exit(1);
}
strcpy(slavename, mastername);
slavename[5] = 't';
/* printf("serial pty: %s\n", slavename); */
seteuid(0);
if ( (fd1s = open(slavename, O_RDWR)) < 0 ) {
perror("open serial pty slave"); exit(1);
}
fchown(fd1s, uid, -1);
fchmod(fd1s, S_IRUSR | S_IWUSR);
seteuid(uid);
/* Symlink pty slave */
if (symlink(slavename, ptyalias) < 0 ) {
perror("symlink"); exit(1);
}
/* Detect "open" for serial pty slave */
FD_ZERO (&readfds);
FD_ZERO (&writefds);
FD_SET (fd1m, &readfds);
/* FD_SET (fd1m, &writefds); */ /* Remove this if wait for open fails */
while ( select (64, &readfds , &writefds, (fd_set *) 0, NULL) < 1 )
;
close (fd1s); /* Application has serial pty slave now */
/* Create shell ptys */
if ( (fd2m = getpty(mastername)) < 0 ) {
perror("open shell pty master"); exit(1);
}
strcpy(slavename, mastername);
slavename[5] = 't';
/* printf("shell pty: %s\n", slavename); */
/* Invoke /bin/sh as a subprocess */
if (! (shellpid = fork()) ) {
close (fd1m);
close (fd2m);
setsid();
seteuid(0);
if ( (fd2s = open(slavename, O_RDWR)) < 0 ) {
perror("open shell pty slave"); exit(1);
}
fchown(fd2s, uid, -1);
fchmod(fd2s, S_IRUSR | S_IWUSR);
setuid(uid);
dup2 (fd2s, 0); /* stdin */
dup2 (fd2s, 1); /* stdout */
dup2 (fd2s, 2); /* stderr */
system ("stty sane");
execl ("/bin/sh", "sh", (char *) 0);
}
iordcnt12 = 0; /* I/O read character count, fd1m to fd2m */
iordcnt21 = 0; /* I/O read character count, fd2m to fd1m */
for (;;) {
FD_ZERO ( &readfds );
FD_ZERO ( &writefds );
if (iordcnt12) {
FD_SET (fd2m, &writefds);
} else {
FD_SET (fd1m, &readfds);
}
if (iordcnt21) {
FD_SET (fd1m, &writefds);
} else {
FD_SET (fd2m, &readfds);
}
iofdcnt = select (64, &readfds, &writefds, (fd_set *) 0, NULL);
if ( iofdcnt < 0 )
if ( errno == EINTR ) continue;
else {
perror("select"); exit(1);
}
if ( FD_ISSET (fd1m, &readfds) ) {
/* Read from fd1m data to be written to fd2m */
iobuf12p = iobuf12;
iordcnt12 = read (fd1m, iobuf12, 2000);
if ( iordcnt12 <= 0 ) break;
}
if ( FD_ISSET (fd1m, &writefds) ) {
/* Write to fd1m with data read from fd2m */
iowrcnt = write (fd1m, iobuf21p, iordcnt21);
if ( iowrcnt <= 0 ) break;
iordcnt21 -= iowrcnt;
iobuf21p += iowrcnt;
}
if ( FD_ISSET (fd2m, &readfds) ) {
/* Read from fd2m data to be written to fd1m */
iobuf21p = iobuf21;
iordcnt21 = read (fd2m, iobuf21, 2000);
if ( iordcnt21 <= 0 ) break;
}
if ( FD_ISSET (fd2m, &writefds) ) {
/* Write to fd2m with data read from fd1m */
iowrcnt = write (fd2m, iobuf12p, iordcnt12);
if ( iowrcnt <= 0 ) break;
iordcnt12 -= iowrcnt;
iobuf12p += iowrcnt;
}
}
close (fd1m);
close (fd2m);
if (unlink(ptyalias) < 0) {
perror("unlink"); exit(1);
}
sleep(3); /* Delay for pty close */
wait(NULL);
}
}
/* Search and allocate a master pty */
int getpty( char ptyname[] )
{
char *p1, *p2, *p;
struct stat statbuf;
int fd;
int i;
strcpy( ptyname, "/dev/ptyXX" );
p1 = &ptyname[8]; p2 = &ptyname[9];
for( p = "pqrstuvwxyz"; *p; p++) {
*p1 = *p; *p2 = '0';
if ( stat(ptyname, &statbuf) < 0 ) { break; }
for( i=0; i<16; i++ ) {
*p2 = "0123456789abcdef"[i];
fd = open( ptyname, O_RDWR );
if ( fd >= 0 ) { return fd; }
}
}
return -1;
}
/*
ptysh.c "Pseudo Terminal Shell" v2
"Using & Managing PPP," O'Reilly & Associates, March 1999
http://www.oreilly.com/
This example is for UNIX System V variants (Sun Microsystem's Solaris 2.6).
Compile with "cc -o ptysh ptysh.c"
Author: Andrew Sun
Revision: January 10, 1998
Revision: July 13, 1999, Link dynamic pty to user specified symbolic link
Revision: July 15, 1999, Trap handle SIGINT only if initially set to default
Description:
This program enables the /bin/sh command interpreter to
emulate a "terminal device". Tip, cu, the UUCP environment,
and PPP normally interact with serial interfaces via terminal
device files, such as /dev/cua/b. Rather than limiting these
applications to physical serial interfaces, "ptysh" enables them
to interact with the shell (/bin/sh), and with TCP/IP communication
programs, including telnet and rlogin.
Usage:
Once ptysh is active, ptysh maintains a user specified symbolic
link to a pseudo terminal. Applications accessing the symbolic
link as a serial device will interact with /bin/sh. At this point,
an application's chat script can "exec telnet," "exec rlogin,"
or invoke an alternate utility to establish communications over a network.
*/
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stropts.h>
#include <poll.h>
#include <signal.h>
char *ptsname(int fildes);
char *ptyalias;
void exitreq(sig)
int sig;
{
unlink(ptyalias);
exit(0);
}
main(argc,argv)
int argc;
char *argv[];
{
int shellpid;
char iobuf12[2000], iobuf21[2000];
char *iobuf12p, *iobuf21p;
int iofdcnt, iowrcnt, iordcnt12, iordcnt21;
int fd1m, fd1s, fd2m, fd2s;
char *slavename;
struct stat statbuf;
struct pollfd fds[2];
unsigned long nfds;
int timeout;
void (*sigvold)();
/* Command line options */
if (argc < 2 ) {
fprintf(stderr, "Usage: %s /dev/ptyalias\n", argv[0]);
exit(1);
}
ptyalias = argv[1];
/* Pty alias file must not already exist */
if ( lstat(ptyalias, &statbuf) >= 0) {
fprintf(stderr, "File %s exists\n", ptyalias);
exit(1);
}
/* Set signal handling */
sigvold = signal(SIGINT, SIG_IGN);
if ( sigvold == SIG_DFL ) {
signal(SIGINT, exitreq);
}
signal(SIGTERM, exitreq);
signal(SIGHUP, SIG_IGN);
for (;;) {
/* Create serial interface ptys */
if ( (fd1m = open("/dev/ptmx", O_RDWR)) < 0 ) {
perror("open serial pty master"); exit(1);
}
grantpt(fd1m); unlockpt(fd1m);
if ( (slavename = ptsname(fd1m)) == NULL ) {
perror("can't determine serial pty"); exit(1);
}
/* printf("serial pty: %s\n", slavename); */
if ( (fd1s = open(slavename,O_RDWR)) < 0 ) {
perror("open serial pty slave"); exit(1);
}
ioctl(fd1s, I_PUSH, "ptem");
ioctl(fd1s, I_PUSH, "ldterm");
/* Symlink pty slave */
if (symlink(slavename, ptyalias) < 0 ) {
perror("symlink"); exit(1);
}
/* Detect "open" for serial pty slave */
fds[0].fd = fd1m;
fds[0].events = POLLIN;
nfds = 1; timeout = -1;
poll(fds, nfds, timeout);
close (fd1s); /* Application has serial pty slave now */
/* Create shell ptys */
if ( (fd2m = open("/dev/ptmx", O_RDWR)) < 0 ) {
perror("open shell pty master"); exit(1);
}
grantpt(fd2m); unlockpt(fd2m);
if ( (slavename = ptsname(fd2m)) == NULL ) {
perror("can't determine shell pty"); exit(1);
}
/* printf("shell pty: %s\n", slavename); */
/* Invoke /bin/sh as a subprocess */