Как использовать два канала для управления двоичным файлом ftp? - PullRequest
0 голосов
/ 22 сентября 2018

Я использую два канала для чтения из стандартного вывода программы ftp и записи в стандартный ввод программы ftp.Но выходная часть не работает, что я не могу понять, почему.Похоже, что стандартный вывод из ftp bin не будет сразу проходить через канал для чтения. Пожалуйста, помогите мне проверить мой код, большое спасибо.И вот мой код:

#define _GNU_SOURCE  
#include <arpa/inet.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <errno.h>
#include <pthread.h>
#include <stdarg.h> 
#include <stdio.h>  
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/sysinfo.h>
#include <sys/wait.h>
#include <sys/ioctl.h>
#include <termios.h> 
#include <unistd.h>

typedef unsigned char UCHAR;

#define MAXBUFSIZE 1024 
#define BUFSIZE 10240 
typedef struct dev_info
{
    UCHAR   ip[4];
    UCHAR   id[16];
    uint8_t state;
} dev_info;

char filename[64];
char fullname[128];
char ip_own[16]={0};
time_t timer;
struct tm *tblock;
char proname[256] = {0};
char buf_error[BUFSIZE]={0};
static char buf[BUFSIZE];
FILE *file_r, *file_w;

void erroroutput(char * str, const char * _func, const int  _line)
{
    memset(buf_error, 0x00, BUFSIZE);
    sprintf(buf_error, "[%s:%d]%s: %s\n",_func, _line, str,strerror(errno));
    printf("%s",buf_error);
}

int checkchar(char c)
{
    if(c<=8)
        return -1;
    if((13<c)&(c<=31))
        return -1;
    if(c>=127)
        return -1;
    return 0;
}

pid_t rw_popen(char* cmd, FILE **rfile, FILE **wfile)
{
    int pipefd[2],pipefd2[2];
    pid_t pid;
    short int flags=0;
    if (pipe(pipefd) < 0)
    {
        erroroutput("pipe create error",__func__, __LINE__);
        return -1;
    }
    if (pipe(pipefd2) < 0)
    {
        erroroutput("pipe create error",__func__, __LINE__);
        return -1;
    }
    pid = fork();
    if (pid < 0)
    {
        fprintf(stdout, "[%s:%d]fail to fork!\n",__func__, __LINE__);
        return -1;
    }

    if (0 == pid)
    {
        close(pipefd[0]);
        dup2(pipefd[1], 1);
        close(pipefd[1]);
        dup2(pipefd2[0], 0);

        close(pipefd2[0]);
        close(pipefd[1]);
        char *argv[] = { "/bin/sh", "-c", cmd, NULL };
        fprintf(stderr,"[%s:%d](pid):=%d\n",__func__, __LINE__,pid);
        if (execvp("/bin/sh", argv) < 0) 
        {
            fprintf(stderr, "[%s:%d]fail to execvp!\n",__func__, __LINE__);
            exit(1);
        }
        fprintf(stderr, "[%s:%d]got here!\n",__func__, __LINE__);
        exit(0);
    }else
    {
        close(pipefd[1]);
        *rfile = fdopen(pipefd[0], "r");
        if(*rfile==NULL)
            fprintf(stderr,"[%s:%d]*rfile==NULL\n",__func__, __LINE__);
        close(pipefd2[0]);
        *wfile = fdopen(pipefd2[1], "w");
        if(*wfile==NULL)
            fprintf(stderr,"[%s:%d]*wfile==NULL\n",__func__, __LINE__);

        return pid;
    }
}

void rw_pclose(pid_t pid, FILE *rfile, FILE *wfile) {
    int status;
    waitpid(pid, &status, 0);
    fclose(rfile);
    fclose(wfile);
}

int waitc(char cc, FILE ** file_rr, char* buff,uint16_t len,char* fc,...)
{
    int c,i=0;
    va_list argp;  
    int argnum = 0;  
    char *para[10];  
    va_start(argp, fc);
    para[argnum]=fc;
    argnum++;
    while (1)  
    {  
        para[argnum] = va_arg(argp, char *);  

        if (strcmp(para[argnum],"") == 0)
            break;    
        argnum++;  
    }  
    va_end(argp);
    do
    {
        c=fgetc(*file_rr);
        if(feof(*file_rr))
        {
            fprintf(stderr, "[%s:%d]Got eof!\n",__func__, __LINE__);
            //return -1;
        }
        if(checkchar(c)<0)
            break;/**/
        putc(c,stdout);
        buff[i]=c;
        i++;
        for(int k=0;k<argnum;k++)
        {
            if(strstr(buff,para[k])!=NULL)
            {
                fprintf(stderr, "[%s:%d]Fail ! %s%d\n",__func__, __LINE__,para[k],k);
                return -1;
            }
        }
        if(i>=len)
        return -2;
    }
    while((char)c!=cc);
    return 0;
}/**/

int loginftp(char* addr, char * user ,char * passw)
{

    pid_t pid;
    char cmd[256];
    memset(cmd,0,sizeof(cmd));
    strcat(cmd,"ftp ");
    strcat(cmd,addr);
    strcat(cmd,"\n");
    fprintf(stderr, "[%s:%d]%s\n",__func__, __LINE__,cmd);

    pid = rw_popen(cmd, &file_r, &file_w);
    fprintf(stderr, "[%s:%d]pid=%d\n",__func__, __LINE__,pid);
    if (pid)
    {
        fputs("anonymous\n",file_w);
        fflush(file_w);
        memset(buf,0,BUFSIZE);
        waitc(':',&file_r,buf,BUFSIZE,"xxxxx","");

        fputs("anonymous\n",file_w);
        fflush(file_w);
        memset(buf,0,BUFSIZE);
        waitc(':',&file_r,buf,BUFSIZE,"xxxxx","");

        fputs("quit\n",file_w);
        fflush(file_w);
        memset(buf,0,BUFSIZE);
        waitc(':',&file_r,buf,BUFSIZE,"xxxxx","");

        int c[2]={0};
        c[0]=0x04;
        fputc(c[0],file_w);
        fflush(file_w);
//_rw_pclose2:
_rw_pclose1:
        rw_pclose(pid, file_r, file_w);
    }
    fprintf(stderr, "[%s:%d]got here!\n",__func__, __LINE__);
    return 0;
}

int main ( int argc, char * argv[] )
{
    //strcpy(proname, argv[0]);
    int ret;
    ret=loginftp("ftp.sjtu.edu.cn","anonymous","anonymous");
    fprintf(stderr, "[%s:%d]ret:%d\n",__func__, __LINE__,ret);
}

Мой make-файл:

CC  = gcc
LD  = ld
AR  = ar
RANLIB  = ranlib
STRIP   = strip

CFLAGS  = -Wall -Wshadow -Wno-trigraphs -pipe
LDFLAGS = -lm -lpthread -g

BIN = unifyctrl
SRCS    = $(wildcard *.c)
OBJS    = $(SRCS:.c=.o)

all: $(BIN)

$(OBJS): %.o: %.c
    $(CC) -c -g $(CFLAGS) $< -o $@

$(BIN): $(OBJS)
    $(CC)  $(OBJS) $(LDFLAGS) -o $(BIN)
    $(STRIP) $(BIN)
clean:
    rm -rf *.o
    rm -rf $(BIN)
    rm -rf *.o *.bak *.c.bak a

Первый результат моего кода должен быть таким: Подключен к ftp-tel.sjtu.edu.cn,220 (vsFTPd 3.0.2) Имя (ftp.sjtu.edu.cn:d01): но я получил только это: Пароль:

...