[LCP]InterProcess Communication

Steve Baker ice at mama.indstate.edu
Fri Nov 22 04:26:02 UTC 2002


"mehul radheshyam choube" <mrc_cprog at rediffmail.com> wrote:
>          I'm writing wrappers to an existing command-line
> based cvs commands The existing cvs login cmd goes like
> this
> $ cvs login
> (Logging in to mehul at 192.168.0.25)
> CVS password: (enter password here)
> $ messages..... eg login sucessful or not.
>
>          Basically my program needs to issue the cvs login
> command, wait for the password prompt, sends the password
> and wait for the login messages. My question is what kind
> of IPC should I use?

  Sorry for taking so long to get to this, I've been under the weather all
week.

  Normally I would recommend socketpair() for non-network bi-directional IPC,
but what you need is a little more involved.  The problem is with CVS and
other programs like it that require direct access to a tty when entering a
password.  CVS, passwd, et.al. will open /dev/tty directly and get access to
the current process groups tty, by-passing your pipes completely.

  What you need to do is run the program in a pseudo tty, and that is just a
little more complex.  The attached example program does what you want.  Note
that it uses two XOPEN_SOURCE extensions.  You can get around those by using
ioctl's, but I do not know which ones off-hand, besides, perhaps in another 30
years, use of ioctl's will finally be depreciated.  There is a considerable
dearth of information on how to do pseudo tty programming, or tty programming
in general.  You'd need to either buy a book or "use the source."

                                                                - Steve

P.S. In the interests of brevity and clarity I do no error checking. Very bad
     of me naturally.
---------------------
#define _XOPEN_SOURCE

#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <string.h>

char buf[1025];

int main(int argc, char **argv)
{
  struct termios ttyconf;
  struct winsize win;
  int n, pid, master, slave;

  /* save termios and window size of current session. */
  tcgetattr(0,&ttyconf);
  ioctl(0,TIOCGWINSZ,&win);

  master = open("/dev/ptmx", O_RDWR);
  /* These two calls require _XOPEN_SOURCE */
  grantpt(master);
  unlockpt(master);
  slave = open(ptsname(master), O_RDWR);

  if (!fork()) {
    ioctl(0,TIOCNOTTY,NULL); /* detach from orginal tty. */
    dup2(slave,0);
    dup2(slave,1);
    dup2(slave,2);
    close(master);
    close(slave);

    /* Make this the foreground process group leader. */
    pid = getpid();
    setpgid(pid,pid);
    tcsetpgrp(0,pid);
    /* Set termios and window size */
    tcsetattr(0,TCSANOW,&ttyconf);
    ioctl(0,TIOCSWINSZ,&win);

    execlp("cvs", "cvs", "login", NULL);
    perror("execlp");
    exit(1);
  }

  /* You must close slave in the master to get proper shutdown of the
   * descriptor when the child dies. */
  close(slave);

  while ((n=read(master,buf,1024)) > 0) {
    write(1,buf,n);
    if (n > 10 && !strncmp((buf+n-10),"password: ",10)) {
      break;
    }
  }
  printf("<< Sending <Enter> >>\n");
  write(master,"\n",1);
  while ((n=read(master,buf,1024)) > 0) {
    write(1,buf,n);
  }
  close(master);
  return 0;
}



More information about the linuxCprogramming mailing list