linux-c-programming.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Pipes and passwd programm problem
@ 2007-03-29  2:41 Nikola
  2007-03-29  3:35 ` Glynn Clements
  0 siblings, 1 reply; 2+ messages in thread
From: Nikola @ 2007-03-29  2:41 UTC (permalink / raw)
  To: linux-c-programming

Hi,

I would like to interface with passwd program in Debian Linux using 
pipes to be able to change password from a C program.

Problem is in reading output from passwd program.

I have observed interesting behavior with passwd program.

---------------------------

[nikola@host][~]$ passwd
Changing password for zip
(current) UNIX password:
[ENTER]
passwd: Authentication failure
[nikola@host][~]$


[nikola@host][~]$ passwd 1> /dev/null
(current) UNIX password:
[ENTER]
passwd: Authentication failure
[nikola@host][~]$


[nikola@host][~]$ passwd 2> /dev/null
Changing password for zip
[ENTER]
[nikola@host][~]$


---------------------------

Program is using both STDOUT and STDERR for output.


program.c
---------------------------

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>

#define BSIZE 500

int read_chars(FILE *rstream){
        char ch;

        while(!feof(rstream)){
                ch = fgetc(rstream);
                printf("%c",ch);
        }

        fflush(NULL);

        return 0;
}


int main(int argc, char **argv){


        int rfds[2];
        int stdout_wfds[2];
        int stderr_wfds[2];

        pid_t pid;


        if(argc < 3){
                fprintf(stderr,"Error: In argument count\n");
                exit(1);
        }


        pipe(rfds);
        pipe(stdout_wfds);
        pipe(stderr_wfds);


        pid = fork();
        if( pid == 0 ){ // child
                close(rfds[1]);
                close(stdout_wfds[0]);
                close(stderr_wfds[0]);


                dup2(rfds[0],STDIN_FILENO);
                dup2(stdout_wfds[1],STDOUT_FILENO);
                dup2(stderr_wfds[1],STDERR_FILENO);

                execlp("passwd","passwd",0);

        } else { // parent

                FILE *rstream_out,*rstream_err,*wstream;
                char buffer[BSIZE];

                wstream = fdopen(rfds[1],"w");
                rstream_out = fdopen(stdout_wfds[0],"r");
                rstream_err = fdopen(stderr_wfds[0],"r");


                // PROBLEM !!!!!!!!!!!!!!!!!!!
                // this is supposed to read 2 lines of passwd output
                // but seems it doesn't work
                read_chars(rstream_out);
                read_chars(rstream_err);


                close(rfds[1]);
                close(stdout_wfds[0]);
                close(stderr_wfds[0]);

                waitpid(pid,NULL,0);
        }

        return 0;
}

---------------------------


tnx in advance.
Nikola.



^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: Pipes and passwd programm problem
  2007-03-29  2:41 Pipes and passwd programm problem Nikola
@ 2007-03-29  3:35 ` Glynn Clements
  0 siblings, 0 replies; 2+ messages in thread
From: Glynn Clements @ 2007-03-29  3:35 UTC (permalink / raw)
  To: Nikola; +Cc: linux-c-programming


Nikola wrote:

> I would like to interface with passwd program in Debian Linux using 
> pipes to be able to change password from a C program.
> 
> Problem is in reading output from passwd program.
> 
> I have observed interesting behavior with passwd program.
> 
> ---------------------------
> 
> [nikola@host][~]$ passwd
> Changing password for zip
> (current) UNIX password:
> [ENTER]
> passwd: Authentication failure
> [nikola@host][~]$
> 
> 
> [nikola@host][~]$ passwd 1> /dev/null
> (current) UNIX password:
> [ENTER]
> passwd: Authentication failure
> [nikola@host][~]$
> 
> 
> [nikola@host][~]$ passwd 2> /dev/null
> Changing password for zip
> [ENTER]
> [nikola@host][~]$
> 
> 
> ---------------------------
> 
> Program is using both STDOUT and STDERR for output.

> int read_chars(FILE *rstream){
>         char ch;
> 
>         while(!feof(rstream)){
>                 ch = fgetc(rstream);
>                 printf("%c",ch);
>         }
> 
>         fflush(NULL);
> 
>         return 0;
> }

This function reads until EOF, which is a problem for your usage of
it. See below.

>         pipe(rfds);
>         pipe(stdout_wfds);
>         pipe(stderr_wfds);

Do you need the stdout and stderr to be separate? You could create one
pipe and assign it to both stdout and stderr.

>         if( pid == 0 ){ // child
>                 close(rfds[1]);
>                 close(stdout_wfds[0]);
>                 close(stderr_wfds[0]);
> 
> 
>                 dup2(rfds[0],STDIN_FILENO);
>                 dup2(stdout_wfds[1],STDOUT_FILENO);
>                 dup2(stderr_wfds[1],STDERR_FILENO);

At this point, you should close std{out,err}_wfds[1] and rfds[0]. 
dup2() copies the descriptor; it doesn't close the source.

>                 execlp("passwd","passwd",0);
> 
>         } else { // parent

Again, you should close std{out,err}_wfds[1] and rfds[0] here.

>                 // PROBLEM !!!!!!!!!!!!!!!!!!!
>                 // this is supposed to read 2 lines of passwd output
>                 // but seems it doesn't work
>                 read_chars(rstream_out);
>                 read_chars(rstream_err);

These functions read until EOF. That won't happen so long as any
process has the write end open. The child will keep its copies open
until it terminates (which won't happen until you've sent at least the
oldpassword, and also the new password if the old password is
correct), and the parent is also holding copies.

More generally, scripting an interactive program such as passwd is
inherently fragile. Scripting the passwd program is especially
fragile, as it typically uses PAM, and so the exact behaviour is
highly variable.

-- 
Glynn Clements <glynn@gclements.plus.com>

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2007-03-29  3:35 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-03-29  2:41 Pipes and passwd programm problem Nikola
2007-03-29  3:35 ` Glynn Clements

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).