#include #include #include #include //#include #include /*O_RDWR*/ #include #include #include #include #include #define MAXLEN 15 int ptym_open(char *pts_name); int ptys_open(int pty, char *pts_name); int writepty(int pty, char *data, int len); int plainread(int fd, char *data, int len); void masterquit(int pty, char* vec); void slavequit(int tty, char *vec); int main(int argc, char *argv[]) { char *testvec1; char *testvec2; char pts_name[20]; int pty=0, tty=0; pid_t slaveproc; int direction; int chars1; int chars2; printf("MASTER: Master Alive: My PID: %d\n", getpid()); /* change direction by adding a command line argument */ direction = (argc == 2); /* direction = 1 => slave to master*/ /* direction = 0 => master to slave*/ printf("<< %s writing to %s >>\n",direction?"Slave":"Master",direction?"Master":"Slave"); printf("*Max Read Size: %ld\n",SSIZE_MAX); if ((pty = ptym_open(pts_name)) < 0){ fprintf(stderr, "MASTER: Error Creating pty\n"); return 1; } printf("MASTER: Created master pty: %d\nMASTER: Associated Slave: %s\n",pty,pts_name); printf("MASTER: Forking Slave...\n"); if ((slaveproc = fork()) < 0){ fprintf(stderr, "fork error\n"); close(pty); return(1); }else if (slaveproc == 0){ /*this is the slave, open the tty, etc*/ printf("SLAVE: Slave Alive: My PID: %d\n", getpid()); printf("SLAVE: Setting Session ID\n"); if(setsid() < 0){ printf("SLAVE: Error setting Session ID: %s :bailing out.\n",strerror(errno)); return 1; } printf("SLAVE: Opening slave end of pty\n"); if((tty = ptys_open(pty, pts_name))<0){ printf("SLAVE: Error opening slave pty %s: %s\nSLAVE: Quitting...\n",pts_name,strerror(errno)); return 1; } testvec1 = (char*)calloc(MAXLEN,sizeof(char)); /* allocate mem*/ if(testvec1 == NULL){ fprintf(stderr, "SLAVE: memory allocation error\nSLAVE: Quitting...\n"); close(tty); return 1; } if(direction){ strcpy(testvec1, "Slave Send"); if((chars1 = writepty(tty,testvec1,MAXLEN)) < 0){ printf("SLAVE: Write Error: %s\n",strerror(errno)); slavequit(tty,testvec1); return 1; } printf("SLAVE: Wrote %d bytes: \"%s\"\n",chars1,testvec1); }else{ printf("SLAVE: Preparing to read, sleeping for 5 while master writes\n"); sleep(5); printf("SLAVE: Attempting to read from fd %d\n",tty); if((chars1 = plainread(tty,testvec1,MAXLEN)) < 0){ printf("SLAVE: Read Error\n"); slavequit(tty, testvec1); return 1; } printf("SLAVE: Read %d bytes: \"%s\"\n", chars1, testvec1); } /* direction */ printf("SLAVE: Sleeping for 10 while master finishes\n"); sleep(10); slavequit(pty, testvec1); return 0; }else{ /*master*/ testvec2 = (char*)calloc(MAXLEN,sizeof(char)); /* allocate mem*/ if(testvec2 == NULL){ fprintf(stderr, "MASTER: memory allocation error\n"); close(pty); return 1; } if(!direction){ strcpy(testvec2, "Master Send"); printf("MASTER: Preparing to write: Sleeping for 2 to let slave get set up\n"); sleep(2); } if(direction){ printf("MASTER: Preparing to read, sleeping for 5 while slave writes\n"); sleep(5); /*give slave time to write*/ printf("MASTER: Attempting to read from fd %d\n",pty); if((chars2 = plainread(pty,testvec2, MAXLEN)) < 0){ printf("MASTER: Read Error: \"%s\"\n",strerror(errno)); masterquit(pty, testvec2); return 1; } printf("MASTER: Read %d bytes: \"%s\"\n",chars2,testvec2); }else{ printf("MASTER: Writing \"%s\"\n",testvec2); if((chars2 = writepty(pty, testvec2, MAXLEN))<0){ printf("MASTER: Write Error: %s\n",strerror(errno)); masterquit(pty, testvec2); return 1; } testvec2[chars2] = '\0'; /* show what we wrote */ printf("MASTER: Wrote %d bytes: \"%s\"\n",chars2,testvec2); } printf("MASTER: Sleeping for 10 while slave finishes\n"); sleep(10); masterquit(pty, testvec2); return 0; } } int ptym_open(char *pts_name) { char *ptr; int pty; if(!pts_name) exit(1); if ((pty = open("/dev/ptmx", O_RDWR)) < 0) { fprintf(stderr,"Unable to open /dev/ptmx"); return -1; } if (grantpt(pty) == -1) { fprintf(stderr,"grantpt"); return -2; } if (unlockpt(pty) == -1) { fprintf(stderr,"unlockpt"); return -3; } ptr = (char*)ptsname(pty); if(!ptr){ fprintf(stderr,"ptsname"); return -4; } strcpy(pts_name,ptr); return pty; } int ptys_open(int pty, char *pts_name) { int tty; if ((tty = open(pts_name, O_RDWR)) < 0){ close(pty); return -5; } return tty; } int writepty(int pty, char *data, int len) { int written=0; if((written = write(pty,data,len))<0) return -1; return written; } int plainread(int fd, char *data, int len) { struct timeval timeout; fd_set rfds; int selresult, check; FD_ZERO(&rfds); /* make file descriptor set to watch */ FD_SET(fd, &rfds); timeout.tv_sec=3; /* set timeout to 3 seconds */ timeout.tv_usec=0; selresult = select(fd+1,&rfds,NULL,NULL,&timeout); /* check fd, wait for 3s */ if(selresult < 0){ printf("READERROR: %s\n",strerror(errno)); return -1; }else if (selresult){ check = read(fd,data,len); if(check > 0) return check; else{ printf("READERROR: %s\n",strerror(errno)); return -1; } }else{ /* selresult == 0 */ printf("READERROR: Data did not become available in 3 seconds\n"); return -1; } } void masterquit(int pty, char* vec) { printf("MASTER: Quitting...\n"); close(pty); free(vec); } void slavequit(int tty, char *vec) { printf("SLAVE: Quitting...\n"); close(tty); free(vec); }