1753862 Members
7491 Online
108809 Solutions
New Discussion юеВ

Help using pty

 
Andreas Tsamis
Advisor

Help using pty

I have the following c code to change a password in hpux. I run (as
root) it but the password doesn't change. Do i do something wrong when
passing the argument to the master pty?

#include
#include
#include
#include
#include
#include
#include
#include
#include

void ErrorExit(char *msg)
{
perror(msg);
exit(EXIT_FAILURE);

}

int main( int argc, char *argv[] )
{
int slaveFd, len, stat,opened=0,infd;
pid_t child;
char ptyMaster[200],ptySlave[200],tempSlave[200];
char Buf[80];
DIR *dirp;
struct dirent *dp;
char passwordis[100];

if (argc < 2)
{
fputs("usage: pty-passwd user\n", stderr);
return EXIT_FAILURE;
}
if (strlen(argv[1]) > 8)
{
fputs("username too long\n", stderr);
return EXIT_FAILURE;
}
dirp=opendir("/dev/ptym");

while ((dp = readdir(dirp)) !=NULL) {
strcpy(ptyMaster,"/dev/ptym/");
strcat(ptyMaster,dp->d_name);
strcpy(ptySlave,"/dev/pty/");
strcpy(tempSlave,dp->d_name);
tempSlave[0] = 't';
strcat(ptySlave,tempSlave);
infd = open(ptyMaster, O_RDWR,0);
if (infd != -1) {
opened=1;
break;
}
}
closedir(dirp);
if (opened==0) {
fprintf(stderr, "Unable To Attach To Any PTY\n");
exit(-1);
}

if ((child = fork()) < 0)
ErrorExit("fork");

if (child > (pid_t) 0)
{
/* in parent */
printf("In Parent\n");
strcpy(passwordis,"welcom\n");
sleep(2);
write(infd, passwordis, strlen(passwordis));
sleep(3);
write(infd, passwordis, strlen(passwordis));
sleep(2);
wait(&stat);
return WEXITSTATUS(stat);
//waitpid(child,NULL,0);
}
else if (child == (pid_t) 0);
{
/* in child */
printf("In Child\n");
if (setsid() < 0)
ErrorExit("setsid");
if ( (slaveFd = open(ptySlave, O_RDWR,0)) < 0)
perror("open (slave)");
close(infd);
if (slaveFd != 0) dup2(slaveFd, 0);
if (slaveFd != 1) dup2(slaveFd, 1);
if (slaveFd != 2) dup2(slaveFd, 2);
close(0);
close(1);
close(2);
/* run passwd */
execlp("passwd", "passwd", argv[1], NULL);
return(-1);
}
return EXIT_SUCCESS;
}
15 REPLIES 15
Mike Stroyan
Honored Contributor

Re: Help using pty

You close file descriptors 0, 1, and 2 between the dup2() calls and the execlp() call. You meant to leave those open.

The business of readdir("/dev/ptym") is not necessary with recent HP-UX releases. You can open /dev/ptym/clone for a plain pty or /dev/ptmx for a streams pty and call ptsname to get the slave pty name. The details are discussed in pty(7) and ptm(7).

The ptm style takes a few more calls to set up termio, but has the advantage of being able to use grantpt() to fix up permissions of the slave pty device file. Otherwise you need to watch out for slave pty devices that you don't have permission to open.

infd = open("/dev/ptym/clone");
if (infd == -1) ErrorExit("no pty");
ptySlave = ptsname(infd);

int open_pty(void)
{
int enable = 1;
int Sfd;

/* Get a master pty */
#if OLD_PTY
Mfd = open("/dev/ptym/clone", O_RDWR);
#else
Mfd = open("/dev/ptmx", O_RDWR);
#endif
if ( Mfd == -1 ) {
perror("log: error opening Pty master");
exit(1);
}

#if OLD_PTY
/* enable pty traping of opens, closes, and ioctls */
ioctl(Mfd, TIOCTRAP, &enable);

Sfd = open(ptsname(Mfd), O_RDWR);
if (Sfd == -1) {
perror("log: error opening Pty slave");
exit(1);
}
#else
/* Change the slave pty to be owned by the real user and
* group of the login running log, mode rw-rw-rw-.
*/
grantpt(Mfd);
unlockpt(Mfd);
Sfd = open(ptsname(Mfd), O_RDWR);
if (Sfd == -1) {
perror("log: error opening Pty slave");
exit(1);
}
ioctl(Sfd, I_PUSH, "ptem");
ioctl(Sfd, I_PUSH, "ldterm");
#endif

return Sfd;
}
Andreas Tsamis
Advisor

Re: Help using pty

I tried to create the function open_pty and i get the following error when i compile in HPUX 11.11:
error 1588: "I_PUSH" undefined.
at this line
ioctl(Sfd, I_PUSH, "ptem");
Andreas Tsamis
Advisor

Re: Help using pty

if i ommit the ioctl calls with I_PUSH the program runs but the password doesn't change
Mike Stroyan
Honored Contributor

Re: Help using pty

You should use these includes to use the
/dev/ptmx interface.
#include
#include
#include
They are listed in "man ptm". That will
provide a definition for I_PUSH.

Did you also remove the close calls after
setting file descriptors 0, 1, and 2, to
use the slave pty?
Andreas Tsamis
Advisor

Re: Help using pty

I removed the close calls but still when the program runs it o/p on screen the two welcom messages exits but the password doesn't change.
Steve Lewis
Honored Contributor

Re: Help using pty

man getpwent

You should use the supported built-in system calls to read and write password file entries and not try to do it yourself. What if you used shadow passwords or trusted mode? Your program also will not set any password because you are not using crypt() to encrypt a given password and salt into the passwd.pw_passwd entry.





Andreas Tsamis
Advisor

Re: Help using pty

The password part will be part of a bigger program that will need to use ptys. The concept with ptys works if i use expect (i think it uses ptys also) in a script.
Mike Stroyan
Honored Contributor

Re: Help using pty

Andreas,

I confirmed that commenting out the close calls in your original code produced a program that worked to change a password when run as root.

You can check what is happening by using the tusc command to trace system calls. Get tusc from the download mentioned at
http://h20331.www2.hp.com/Hpsub/cache/286022-0-0-225-121.html
and run it as root like
tusc -fp a.out acctname
to see what system calls are made by your program and the passwd process. (That gives a way to see error messages written to stderr that are going to the slave pty.)
Andreas Tsamis
Advisor

Re: Help using pty

i tried tusc and it seems that it just waits indefenitely
This is part of tusc o/p

getdents(3, 0x400031c0, 8192) ............................ = 1512
open("/dev/ptym/.", O_RDWR, 0) ........................... ERR#21 EISDIR
open("/dev/ptym/..", O_RDWR, 0) .......................... ERR#21 EISDIR
open("/dev/ptym/ptyp0", O_RDWR, 0) ....................... ERR#16 EBUSY
open("/dev/ptym/ptyp1", O_RDWR, 0) ....................... = 4
close(3) ................................................. = 0
fork() ................................................... = 27568
In Child
ioctl(1, TCGETA, 0x7f7f0ef8) ............................. = 0
In Parent
write(1, "I n P a r e n t \n", 10) ..................... = 10
sigprocmask(SIG_BLOCK, 0x7f7f0c48, 0x7f7f0c68) ........... = 0
getitimer(ITIMER_REAL, 0x7f7f0c88) ....................... = 0
time(NULL) ............................................... = 1152515660
sigtimedwait(0x7f7f0c98, NULL, 0x7f7f0cb8) ............... [sleeping]
sigtimedwait(0x7f7f0c98, NULL, 0x7f7f0cb8) ............... ERR#11 EAGAIN
time(NULL) ............................................... = 1152515662
sigprocmask(SIG_SETMASK, 0x7f7f0c68, NULL) ............... = 0
write(4, "w e l c o m \n", 7) ............................ = 7
sigprocmask(SIG_BLOCK, 0x7f7f0c48, 0x7f7f0c68) ........... = 0
getitimer(ITIMER_REAL, 0x7f7f0c88) ....................... = 0
time(NULL) ............................................... = 1152515662
sigtimedwait(0x7f7f0c98, NULL, 0x7f7f0cb8) ............... [sleeping]
sigtimedwait(0x7f7f0c98, NULL, 0x7f7f0cb8) ............... ERR#11 EAGAIN
time(NULL) ............................................... = 1152515665
sigprocmask(SIG_SETMASK, 0x7f7f0c68, NULL) ............... = 0
write(4, "w e l c o m \n", 7) ............................ = 7
sigprocmask(SIG_BLOCK, 0x7f7f0c48, 0x7f7f0c68) ........... = 0
getitimer(ITIMER_REAL, 0x7f7f0c88) ....................... = 0
time(NULL) ............................................... = 1152515665
sigtimedwait(0x7f7f0c98, NULL, 0x7f7f0cb8) ............... [sleeping]
sigtimedwait(0x7f7f0c98, NULL, 0x7f7f0cb8) ............... ERR#11 EAGAIN
time(NULL) ............................................... = 1152515667
sigprocmask(SIG_SETMASK, 0x7f7f0c68, NULL) ............... = 0
wait(0x7f7f08a8) ......................................... [sleeping]