Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner AT cygwin DOT com Mail-Followup-To: cygwin AT cygwin DOT com Delivered-To: mailing list cygwin AT cygwin DOT com Message-ID: <950B6B3FADEC484C8D0AE17EEE55E1FA2E02F1@draco.analogic.com> From: "Hirsch, Matthew" To: "'cygwin AT cygwin DOT com'" Subject: PTY read/write problems Date: Tue, 22 Jul 2003 16:21:48 -0400 MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----_=_NextPart_000_01C3508E.E11E8E00" Note-from-DJ: This may be spam ------_=_NextPart_000_01C3508E.E11E8E00 Content-Type: text/plain Hi list, I'm having trouble sending data back and forth between two processes over a pseudo terminal. I'm able to send data from the slave tty to the master pty without any problem. However, no data can be read from the slave side of the pty (tty). I've attached an example program that demonstrates my problem. I compiled it with gcc ptyrw.c -g -o ptyrw -Wall I have cygwin version 1.3.22-1 (Curr in setup as of yesterday). I've attempted to follow the suggestions made in earlier discussions of pseudo terminals (http://sources.redhat.com/ml/cygwin/2002-11/msg00064.html for example). Has anyone written an example of a working pty/tty connection under Cygwin? I would appreciate it very much if someone could set me straight on this. The output I'm getting with my test program is as follows: $ ./ptyrw MASTER: Master Alive: My PID: 232 << Master writing to Slave >> *Max Read Size: 2147483647 MASTER: Created master pty: 3 MASTER: Associated Slave: /dev/tty0 MASTER: Forking Slave... MASTER: Preparing to write: Sleeping for 2 to let slave get set up SLAVE: Slave Alive: My PID: 128 SLAVE: Setting Session ID SLAVE: Opening slave end of pty SLAVE: Preparing to read, sleeping for 5 while master writes MASTER: Writing "Master Send" MASTER: Wrote 15 bytes: "Master Send" MASTER: Sleeping for 10 while slave finishes SLAVE: Attempting to read from fd 4 READERROR: Data did not become available in 3 seconds SLAVE: Read Error SLAVE: Quitting... MASTER: Quitting... Whereas in this direction things work as expected: $ ./ptyrw 1 MASTER: Master Alive: My PID: 1124 << Slave writing to Master >> *Max Read Size: 2147483647 MASTER: Created master pty: 3 MASTER: Associated Slave: /dev/tty0 MASTER: Forking Slave... MASTER: Preparing to read, sleeping for 5 while slave writes SLAVE: Slave Alive: My PID: 1896 SLAVE: Setting Session ID SLAVE: Opening slave end of pty SLAVE: Wrote 15 bytes: "Slave Send" SLAVE: Sleeping for 10 while master finishes MASTER: Attempting to read from fd 3 MASTER: Read 7 bytes: "Slave S" MASTER: Sleeping for 10 while slave finishes SLAVE: Quitting... MASTER: Quitting... The fact that read returns data in blocks of 7 bytes or less seems a bit cumbersome but not out of spec. Thank you very much for any suggestions. Matt Hirsch ------_=_NextPart_000_01C3508E.E11E8E00 Content-Type: application/octet-stream; name="ptyrw.c" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="ptyrw.c" #include =0A= #include =0A= #include =0A= #include =0A= //#include =0A= #include /*O_RDWR*/=0A= #include =0A= #include =0A= #include =0A= #include =0A= #include =0A= =0A= #define MAXLEN 15=0A= =0A= int ptym_open(char *pts_name);=0A= int ptys_open(int pty, char *pts_name);=0A= int writepty(int pty, char *data, int len);=0A= int plainread(int fd, char *data, int len);=0A= void masterquit(int pty, char* vec);=0A= void slavequit(int tty, char *vec);=0A= =0A= int main(int argc, char *argv[])=0A= {=0A= char *testvec1;=0A= char *testvec2;=0A= char pts_name[20];=0A= =0A= int pty=3D0, tty=3D0;=0A= pid_t slaveproc;=0A= int direction;=0A= int chars1;=0A= int chars2;=0A= =0A= printf("MASTER: Master Alive: My PID: %d\n", getpid());=0A= =0A= /* change direction by adding a command line argument */=0A= =0A= direction =3D (argc =3D=3D 2);=0A= /* direction =3D 1 =3D> slave to master*/=0A= /* direction =3D 0 =3D> master to slave*/=0A= printf("<< %s writing to %s = >>\n",direction?"Slave":"Master",direction?"Master":"Slave");=0A= printf("*Max Read Size: %ld\n",SSIZE_MAX);=0A= =0A= if ((pty =3D ptym_open(pts_name)) < 0){=0A= fprintf(stderr, "MASTER: Error Creating pty\n");=0A= return 1;=0A= }=0A= printf("MASTER: Created master pty: %d\nMASTER: Associated Slave: = %s\n",pty,pts_name);=0A= printf("MASTER: Forking Slave...\n");=0A= =0A= if ((slaveproc =3D fork()) < 0){=0A= fprintf(stderr, "fork error\n");=0A= close(pty);=0A= return(1);=0A= }else if (slaveproc =3D=3D 0){ /*this is the slave, open the tty, = etc*/=0A= printf("SLAVE: Slave Alive: My PID: %d\n", getpid());=0A= printf("SLAVE: Setting Session ID\n");=0A= if(setsid() < 0){=0A= printf("SLAVE: Error setting Session ID: %s :bailing = out.\n",strerror(errno));=0A= return 1;=0A= }=0A= =0A= printf("SLAVE: Opening slave end of pty\n");=0A= if((tty =3D ptys_open(pty, pts_name))<0){=0A= printf("SLAVE: Error opening slave pty %s: %s\nSLAVE: = Quitting...\n",pts_name,strerror(errno));=0A= return 1;=0A= }=0A= =0A= testvec1 =3D (char*)calloc(MAXLEN,sizeof(char)); /* = allocate mem*/=0A= =0A= if(testvec1 =3D=3D NULL){=0A= fprintf(stderr, "SLAVE: memory allocation error\nSLAVE: = Quitting...\n");=0A= close(tty);=0A= return 1;=0A= }=0A= if(direction){=0A= strcpy(testvec1, "Slave Send");=0A= =0A= if((chars1 =3D writepty(tty,testvec1,MAXLEN)) < 0){=0A= printf("SLAVE: Write Error: %s\n",strerror(errno));=0A= slavequit(tty,testvec1);=0A= return 1;=0A= }=0A= =0A= printf("SLAVE: Wrote %d bytes: \"%s\"\n",chars1,testvec1);=0A= }else{=0A= printf("SLAVE: Preparing to read, sleeping for 5 while master = writes\n");=0A= sleep(5);=0A= printf("SLAVE: Attempting to read from fd %d\n",tty);=0A= if((chars1 =3D plainread(tty,testvec1,MAXLEN)) < 0){=0A= printf("SLAVE: Read Error\n");=0A= slavequit(tty, testvec1);=0A= return 1;=0A= }=0A= printf("SLAVE: Read %d bytes: \"%s\"\n", chars1, testvec1);=0A= } /* direction */=0A= printf("SLAVE: Sleeping for 10 while master finishes\n");=0A= sleep(10);=0A= slavequit(pty, testvec1);=0A= return 0;=0A= }else{ /*master*/=0A= testvec2 =3D (char*)calloc(MAXLEN,sizeof(char)); /* = allocate mem*/=0A= =0A= if(testvec2 =3D=3D NULL){=0A= fprintf(stderr, "MASTER: memory allocation = error\n");=0A= close(pty);=0A= return 1;=0A= }=0A= if(!direction){=0A= strcpy(testvec2, "Master Send");=0A= printf("MASTER: Preparing to write: Sleeping for 2 to let slave get = set up\n");=0A= sleep(2);=0A= }=0A= if(direction){=0A= printf("MASTER: Preparing to read, sleeping for 5 while slave = writes\n");=0A= sleep(5); /*give slave time to write*/=0A= printf("MASTER: Attempting to read from fd %d\n",pty);=0A= if((chars2 =3D plainread(pty,testvec2, MAXLEN)) < 0){=0A= printf("MASTER: Read Error: \"%s\"\n",strerror(errno));=0A= masterquit(pty, testvec2);=0A= return 1;=0A= }=0A= printf("MASTER: Read %d bytes: \"%s\"\n",chars2,testvec2);=0A= }else{=0A= printf("MASTER: Writing \"%s\"\n",testvec2);=0A= if((chars2 =3D writepty(pty, testvec2, MAXLEN))<0){=0A= printf("MASTER: Write Error: %s\n",strerror(errno));=0A= masterquit(pty, testvec2);=0A= return 1;=0A= }=0A= testvec2[chars2] =3D '\0'; /* show what we wrote */=0A= printf("MASTER: Wrote %d bytes: \"%s\"\n",chars2,testvec2);=0A= }=0A= printf("MASTER: Sleeping for 10 while slave finishes\n");=0A= sleep(10);=0A= masterquit(pty, testvec2);=0A= return 0;=0A= }=0A= }=0A= =0A= int ptym_open(char *pts_name)=0A= {=0A= char *ptr;=0A= int pty;=0A= =0A= if(!pts_name)=0A= exit(1);=0A= if ((pty =3D open("/dev/ptmx", O_RDWR)) < 0) {=0A= fprintf(stderr,"Unable to open /dev/ptmx");=0A= return -1;=0A= }=0A= =0A= if (grantpt(pty) =3D=3D -1) {=0A= fprintf(stderr,"grantpt");=0A= return -2;=0A= }=0A= =0A= if (unlockpt(pty) =3D=3D -1) {=0A= fprintf(stderr,"unlockpt");=0A= return -3;=0A= }=0A= =0A= ptr =3D (char*)ptsname(pty);=0A= if(!ptr){=0A= fprintf(stderr,"ptsname");=0A= return -4;=0A= }=0A= =0A= strcpy(pts_name,ptr);=0A= =0A= return pty;=0A= }=0A= =0A= int ptys_open(int pty, char *pts_name)=0A= {=0A= int tty;=0A= =0A= if ((tty =3D open(pts_name, O_RDWR)) < 0){=0A= close(pty);=0A= return -5;=0A= }=0A= return tty;=0A= }=0A= =0A= int writepty(int pty, char *data, int len)=0A= {=0A= int written=3D0;=0A= =0A= if((written =3D write(pty,data,len))<0)=0A= return -1;=0A= return written;=0A= }=0A= =0A= int plainread(int fd, char *data, int len)=0A= {=0A= struct timeval timeout;=0A= fd_set rfds;=0A= int selresult, check;=0A= =0A= FD_ZERO(&rfds); /* make file descriptor set to watch */=0A= FD_SET(fd, &rfds);=0A= =0A= timeout.tv_sec=3D3; /* set timeout to 3 seconds */=0A= timeout.tv_usec=3D0;=0A= =0A= selresult =3D select(fd+1,&rfds,NULL,NULL,&timeout); /* check fd, wait = for 3s */=0A= if(selresult < 0){=0A= printf("READERROR: %s\n",strerror(errno));=0A= return -1;=0A= }else if (selresult){=0A= check =3D read(fd,data,len);=0A= if(check > 0)=0A= return check;=0A= else{=0A= printf("READERROR: %s\n",strerror(errno));=0A= return -1;=0A= }=0A= }else{ /* selresult =3D=3D 0 */=0A= printf("READERROR: Data did not become available in 3 seconds\n");=0A= return -1;=0A= }=0A= }=0A= =0A= void masterquit(int pty, char* vec)=0A= {=0A= printf("MASTER: Quitting...\n");=0A= =0A= close(pty);=0A= free(vec);=0A= =0A= }=0A= =0A= void slavequit(int tty, char *vec)=0A= {=0A= printf("SLAVE: Quitting...\n");=0A= =0A= close(tty);=0A= free(vec);=0A= =0A= }=0A= ------_=_NextPart_000_01C3508E.E11E8E00 Content-Type: text/plain; charset=us-ascii -- Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple Problem reports: http://cygwin.com/problems.html Documentation: http://cygwin.com/docs.html FAQ: http://cygwin.com/faq/ ------_=_NextPart_000_01C3508E.E11E8E00--