[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