Thread: Pipelines - please help, 6 hours and I am losing my mind.

  1. #1
    Registered User
    Join Date
    Apr 2012
    Location
    UK
    Posts
    7

    Pipelines - please help, 6 hours and I am losing my mind.

    Good afternoon. I am quite new to C and was playing around with attempting to write my own C based program (compiling w/ gcc via cygwin) to communicate with an FTP server (FileZilla Server version 0.9.41 beta) on 127.0.0.1:21.

    I can not seem to be able to read and spit out any output from the FTP server via the program pipelines.

    My (what will be an eyesore) code:

    ================================================
    Code:
    #include <stdio.h>
    #include <time.h>
    #include <Windows.h>
    #include <unistd.h>
    #include <string.h>
    
    
    //define variables//
    char username[20];
    char password[20];
    char out[50];
    
    
    int main()
    //main function starts here//
    {
    //obtain user input to apply to FT protocol//
    printf("Username to use?\n");
    scanf("%s",username);
    printf("Password to use?\n");
    scanf("%s",password);
    //start a write pipeline to ftp from bash shell//
    FILE *ftp=popen("ftp","w");
    // input the user info and open connection//
         fprintf(ftp,"o 127.0.0.1 21 \n%s\n",username);
        fprintf(ftp,"%s",password);
          
          
          
          //Start read pipe: //
    FILE*ftpread=popen("ftp","r");
    //obtain any output from FTP//
        fscanf(ftpread,"%s",out);
      
         //Program sticks, does not pick up the ftp "bad user/password" (530) output//
         
         //start a write pipeline to ftp from bash shell, for more input if connected//
    FILE *ftp3=popen("ftp","w");
    // input the user info and open connection//
        
          
         //Close pipes here?//
          pclose(ftp); pclose(ftpread); pclose(ftp3);
          
         getchar();
         return EXIT_SUCCESS;
        
        
    
    
    
    
    }
    ==================================================

    Braces for n00b flame!

    Thanks for any help!

  2. #2
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Code:
    //Program sticks, does not pick up the ftp "bad user/password" (530) output//
    Betcha because that is the ftp process's stderr, not stdout, and popen() reads from the later.

    If you are using the cygwin bash shell, you should be able to get around that by appending 2>&1 to the ftp command. 2 is stderr, 1 is stdout, >& redirects one into the other.

    Code:
    FILE *ftpread = popen("ftp 2>&1","r");
    Last edited by MK27; 04-04-2012 at 10:34 AM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  3. #3
    Registered User
    Join Date
    Mar 2011
    Posts
    546
    you are spawning two unrelated instances of ftp. the read and write pipes are not connected in any way. thats why you don't get any input from the second instance of ftp.
    one solution is to fork into two proceses. one that writes to FTP, and the other that reads from the FTP, while redirecting the standard in and out properly. here's something that worked for me on Linux (no guarantees on cygwin/windows).

    then the catch is how to coordinate input to ftp with output from ftp. you will need to connect the child and parent with some other interprocess communication mechanism.

    Code:
    #include <stdio.h>
    #include <string.h>
    #include <errno.h>
    #include <assert.h>
    #include <unistd.h>
    
    int main(int argc,char *argv[])
    {
    	FILE *inp;
    	FILE *pftp;
    	int   p[2];
    	int   status;
    	int   fd;
    	char  buf[1024];
    	pid_t pid;
    	
    	memset(buf,0,sizeof(buf));
    
    	// create a pipe
    	// p[0] is read side of pipe
    	// p[1] is write side of pipe
    	status = pipe(p);
    	if (status != 0) {
    		perror("pipe");
    		return 1;
    	}
    	
    	pid = fork();
    	if (pid == -1) {
    		perror("fork");
    		return 1;
    	}
    	else if (pid == 0) {
    		// child - receives output from ftp
    		
    		// open a FILE * to the pipe
    		inp = fdopen(p[0],"r");
                    if (inp == 0) {
                         perror("fdopen");
                          return 1;
                     }
    		
    		// get output of FTP
    		fgets(buf,sizeof(buf),inp);
    		
    		// print it to console
    		printf("***%s***\n",buf);
    	}
    	else {
    		// parent : sends input to ftp
    		
    		// redirect standard out to write side of pipe
    		fd = dup2(p[1],STDOUT_FILENO);
    		if (fd == -1) {
    			perror("dup2");
    			return 1;
    		}
    		// close unused side of pipe
    		close(p[0]);
    		
    		// open writeable file to ftp process
    		pftp = popen("ftp","w");
    		if (pftp == 0) {
    			perror("popen");
    			return 1;
    		}
    		
    		// write something to ftp
    		fprintf(pftp,"hello world");
    	}
    	
    	
    	return 0;
    }

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    FILE *ftp=popen("ftp","w");
    ...
    FILE*ftpread=popen("ftp","r");

    You now have TWO copies of the ftp program running.

    Read the manual page for YOUR version of popen() to see if it supports the "r+" mode for reading AND writing.


    Otherwise, you'll have to use pipe and exec() to arrange proper 2-way communication between two processes.


    > FILE *ftp3=popen("ftp","w");
    Make that 3
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Registered User
    Join Date
    Apr 2012
    Location
    UK
    Posts
    7

    Question

    Quote Originally Posted by dmh2000 View Post
    you are spawning two unrelated instances of ftp. the read and write pipes are not connected in any way. thats why you don't get any input from the second instance of ftp.
    one solution is to fork into two proceses. one that writes to FTP, and the other that reads from the FTP, while redirecting the standard in and out properly. here's something that worked for me on Linux (no guarantees on cygwin/windows).

    then the catch is how to coordinate input to ftp with output from ftp. you will need to connect the child and parent with some other interprocess communication mechanism.
    Thanks for your help and a code example.
    Any recommended white papers on the topic of using pipes and forks from a basic level? I keep running in to some very advanced stuff pretty quickly via google.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 6
    Last Post: 03-18-2012, 10:11 PM
  2. Array of struct pointers - Losing my mind
    By drucillica in forum C Programming
    Replies: 5
    Last Post: 11-12-2005, 11:50 PM
  3. losing weight
    By Shadow in forum A Brief History of Cprogramming.com
    Replies: 20
    Last Post: 10-21-2002, 05:43 AM
  4. Don't know if I'm losing my mind...
    By Invincible in forum C++ Programming
    Replies: 19
    Last Post: 05-26-2002, 11:27 PM
  5. Lost source... losing mind...
    By doubleanti in forum A Brief History of Cprogramming.com
    Replies: 6
    Last Post: 10-27-2001, 12:31 AM

Tags for this Thread