Unix Technical Forum

pseudo terminal(grantpt) problems

This is a discussion on pseudo terminal(grantpt) problems within the comp.unix.solaris forums, part of the Solaris Operating System category; --> Hi, I am using pseudo terminals to drive an executable(sftp) from my code. I open a pseudo terminal(using grantpt) ...


Go Back   Unix Technical Forum > Unix Operating Systems > Solaris Operating System > comp.unix.solaris

FAQ Members List Calendar Search Today's Posts Mark Forums Read
  #1 (permalink)  
Old 01-06-2008, 07:43 AM
Sanjeev
 
Posts: n/a
Default pseudo terminal(grantpt) problems

Hi,

I am using pseudo terminals to drive an executable(sftp) from my code.
I open a pseudo terminal(using grantpt) and fork. In the child the
slave pty is opened and the sftp program is exec'd. The parent reads
and writes to sftp by using the master file descriptor. Please see the
program below.

The problem is, sometimes when the parent writes to the master fd and
tries to read the output from the child using the same fd, it gets
whatever it just wrote. Apparently, the child did not get a chance to
read it.

The only way I was able to avoid this is by putting a sleep between
the parent's write and select statements.

Is there any other way that it can be avoided? Am I not setting any
relevant terminal options/modules?

Thanks,
Sanjeev

/************************************************** ******************
Usage : ./a.out /usr/bin/sftp <userid>@<host> <password>
************************************************** ******************/
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/filio.h>
#include <stropts.h>
void wait_for_response(int fdm);
fd_set readList;
main(int argc, char*argv[])
{
int fdm, fds, pid, nbytes, nread, count;
char *slave;
char Response[512];
if (argc < 4)
{
printf("usage: %s /usr/bin/sftp <username>@<host> <password>\n",
argv[0]);
exit(-1);
}
count = strlen(argv[3]);
if( (fdm = open("/dev/ptmx", O_RDWR)) < 0 ) {
perror ("Unable to get a free master pseudo tty.");
exit (-1);
}
if (grantpt (fdm)) {
perror ("grantpt");
exit (-1);
}
if (unlockpt(fdm)) {
perror ("unlockpt");
exit (-1);
}
if ((pid= fork()) == 0 ) { /* child */
if (setsid() < 0)
perror("setsid error");
slave = (char *) ptsname(fdm);
fds = open(slave, O_RDWR);
if (fds <=0){
perror("open");
exit (-1);
}
if(isastream(fds)) { /* Check if "fds" is a valid
file descriptor */
ioctl(fds, I_PUSH, "ptem"); /* push ptem */
ioctl(fds, I_PUSH, "ldterm"); /* push ldterm*/
}
close (fdm);
if (dup2(fds, 0) !=0)
{
perror("dup2 stdin");
exit (-1);
}
if (dup2(fds, 1) !=1)
{
perror("dup2 stdout");
exit (-1);
}
if (dup2(fds, 2) !=2)
{
perror("dup2 stderr");
exit (-1);
}
if (fds > 2) close (fds);
if(execl(argv[1], argv[1], argv[2], NULL) < 0)
{
perror("execl ");
exit (-1);
}
}
else if (pid >0) /*master */
{
ioctl(fdm, FIONREAD,&nbytes);

FD_ZERO(&readList);
FD_SET(fdm,&readList);
wait_for_response(fdm);
if (( nread = read(fdm, Response, 512)) <= 0) {
perror("read");
exit (-1);
}
Response[nread] = '\0';
printf("Response 1 is:%s", Response);
while (strstr(Response, "password") == NULL)
{
wait_for_response(fdm);
if (( nread = read(fdm, Response, 512)) <= 0) {
perror("read");
exit (-1);
}
Response[nread] = '\0';
printf("Response 2 is :%s", Response);
}

if ((write(fdm, argv[3], count) != count)){
perror("write");
exit (-1);
}
if ((write(fdm, "\n", 1) != 1)){
perror("write");
exit (-1);
}
wait_for_response(fdm);
if (( nread = read(fdm, Response, 512)) <= 0) {
perror("read");
exit (-1);
}
Response[nread] = '\0';
printf("Reponse 3 is: %s", Response);
if ((write(fdm, "put test.c\n", 11) != 11)){
perror("write");
exit (-1);
}
wait_for_response(fdm);
if (( nread = read(fdm, Response, 512)) <= 0) {
perror("read");
exit (-1);
}
Response[nread] = '\0';
printf("Reponse 4 is: %s", Response);
if ((write(fdm, "bye\n", 4) != 4))
perror("writen");
wait_for_response(fdm);
if (( nread = read(fdm, Response, 512)) <= 0) {
perror("read");
exit (-1);
}
Response[nread] = '\0';
printf("Reponse 5 is: %s", Response);
}
}

void wait_for_response(int fdm)
{
int selrc ;
sleep(10); /* to avoid select returning due to our own write */
selrc = select(fdm +1, &readList,0,0, NULL);
if (selrc < 1)
{
perror("select");
exit (-1);
}
}
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #2 (permalink)  
Old 01-06-2008, 07:43 AM
Casper H.S. Dik
 
Posts: n/a
Default Re: pseudo terminal(grantpt) problems

sanjvkoz@yahoo.com (Sanjeev) writes:

>I am using pseudo terminals to drive an executable(sftp) from my code.
>I open a pseudo terminal(using grantpt) and fork. In the child the
>slave pty is opened and the sftp program is exec'd. The parent reads
>and writes to sftp by using the master file descriptor. Please see the
>program below.


>The problem is, sometimes when the parent writes to the master fd and
>tries to read the output from the child using the same fd, it gets
>whatever it just wrote. Apparently, the child did not get a chance to
>read it.


Actually, the child does get to read it but the pseudo tty
echos the input.

It's just like typing to a pseudo terminal; I'm not typing this in an
xterm; each character that the xterm reads is send to the pseudo tty
and then xterm reads back my output; when typing, the output is typically
the echoed characters.

>The only way I was able to avoid this is by putting a sleep between
>the parent's write and select statements.


You should still see all your output; it is possible that your code
sends the password before sftp has switched off echo; but normally
the password should not be echoed.

>Is there any other way that it can be avoided? Am I not setting any
>relevant terminal options/modules?


Unset echo on the tty in the child.

Some other small remarks:


>#include <stdio.h>
>#include <unistd.h>
>#include <errno.h>
>#include <fcntl.h>
>#include <sys/ioctl.h>
>#include <sys/time.h>
>#include <sys/filio.h>
>#include <stropts.h>


Missing: #include <stdlib.h>


> slave = (char *) ptsname(fdm);


This case is wrong also; it the compiler from warning you that you
forgot to include <stdlib.h>; not that the above code would not work
as 64 bit program.

> fds = open(slave, O_RDWR);


> if (fds <=0){


Wrong check: should be fds < 0

Casper
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #3 (permalink)  
Old 01-06-2008, 07:46 AM
Sanjeev
 
Posts: n/a
Default Re: pseudo terminal(grantpt) problems

Casper H.S. Dik <Casper.Dik@Sun.COM> wrote in message news:<401b9eaf$0$328$e4fe514c@news.xs4all.nl>...
> Unset echo on the tty in the child.
>

Casper, thank you for the explanation. I turned off the echo on the
child and it works fine!

Thanks for your other comments about the code too.

Regards,
Sanjeev
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
Reply


Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On
Forum Jump


All times are GMT. The time now is 06:08 PM.


Powered by vBulletin® Version 3.6.5
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
SEO by vBSEO 3.2.0
www.UnixAdminTalk.com