Example #1
0
/*
 * FtpAccess - return a handle for a data stream
 *
 * return 1 if successful, 0 otherwise
 */
GLOBALDEF int FtpAccess (const char *path, int typ, int mode, netbuf *nControl,
    netbuf **nData) {
    char buf[256];
    int dir;
    if ((path == NULL) &&
        ((typ == FTPLIB_FILE_WRITE) || (typ == FTPLIB_FILE_READ))) {
        sprintf(nControl->response,
            "Missing path argument for file transfer\n");
        return 0;
    }
    sprintf(buf, "TYPE %c", mode);
    if (!FtpSendCmd(buf, '2', nControl))
        return 0;
    switch (typ) {
        case FTPLIB_DIR:
            strcpy(buf, "NLST");
            dir = FTPLIB_READ;
            break;
        case FTPLIB_DIR_VERBOSE:
            strcpy(buf, "LIST");
            dir = FTPLIB_READ;
            break;
        case FTPLIB_FILE_READ:
            strcpy(buf, "RETR");
            dir = FTPLIB_READ;
            break;
        case FTPLIB_FILE_WRITE:
            strcpy(buf, "STOR");
            dir = FTPLIB_WRITE;
            break;
        default:
            sprintf(nControl->response, "Invalid open type %d\n", typ);
            return 0;
    }
    if (path != NULL) {
        int i = strlen(buf);
        buf[i++] = ' ';
        if ((strlen(path) + i) >= sizeof (buf))
            return 0;
        strcpy(&buf[i], path);
    }
    if (FtpOpenPort(nControl, nData, mode, dir) == -1)
        return 0;
    if (!FtpSendCmd(buf, '1', nControl)) {
        FtpClose(*nData);
        *nData = NULL;
        return 0;
    }
    (*nData)->ctrl = nControl;
    nControl->data = *nData;
    if (nControl->cmode == FTPLIB_PORT) {
        if (!FtpAcceptConnection(*nData, nControl)) {
            FtpClose(*nData);
            *nData = NULL;
            nControl->data = NULL;
            return 0;
        }
    }
    return 1;
}
Example #2
0
/*
 * FtpClose - close a data connection
 */
GLOBALDEF int FtpClose(netbuf *nData)
{
	netbuf *ctrl;
	switch (nData->dir)
	{
		case FTPLIB_WRITE:
			/* potential problem - if buffer flush fails, how to notify user? */
			if (nData->buf != NULL)
				writeline(NULL, 0, nData);
		case FTPLIB_READ:
			if (nData->buf)
				free(nData->buf);
			shutdown(nData->handle,2);
			net_close(nData->handle);
			ctrl = nData->ctrl;
			free(nData);
			if (ctrl)
			{
				ctrl->data = NULL;
				return(readresp('2', ctrl));
			}
			return 1;
		case FTPLIB_CONTROL:
			if (nData->data)
			{
				nData->ctrl = NULL;
				FtpClose(nData);
			}
			net_close(nData->handle);
			free(nData);
			return 0;
	}
	return 1;
}
Example #3
0
/*
 * FtpXfer - issue a command and transfer data
 *
 * return 1 if successful, 0 otherwise
 */
static int FtpXfer(const char *localfile, const char *path,
                   netbuf *nControl, int typ, int mode)
{
    int l,c;
    char *dbuf;
    FILE *local = NULL;
    netbuf *nData;
    int rv=1;
    int writeResult = 0;

    if (localfile != NULL)
      {
          char ac[4] = "w";
          if (typ == FTPLIB_FILE_WRITE)
              ac[0] = 'r';
          if (mode == FTPLIB_IMAGE)
              ac[1] = 'b';
          local = fopen(localfile, ac);
          if (local == NULL)
            {
                strncpy(nControl->response, strerror(errno),
                        sizeof(nControl->response));
                return 0;
            }
      }
    if (local == NULL)
        local = (typ == FTPLIB_FILE_WRITE) ? stdin : stdout;
    if (!FtpAccess(path, typ, mode, nControl, &nData))
        return 0;
    dbuf = malloc(FTPLIB_BUFSIZ);
    if (typ == FTPLIB_FILE_WRITE)
      {
          while ((l = fread(dbuf, 1, FTPLIB_BUFSIZ, local)) > 0)
              if ((c = FtpWrite(dbuf, l, nData)) < l)
                {
                    if (ftplib_debug > 1)
                        printf("short write: passed %d, wrote %d\n", l, c);
                    rv = 0;
                    break;
                }
      }
    else
      {
          while ((l = FtpRead(dbuf, FTPLIB_BUFSIZ, nData)) > 0) {
              writeResult = (nData->writercb) ? nData->writercb(nData, dbuf, l, nData->writerarg) : fwrite(dbuf, 1, l, local);
              if (writeResult <= 0)
                {
                    perror("localstore write");
                    rv = 0;
                    break;
                }
          }
      }
    free(dbuf);
    fflush(local);
    if (localfile != NULL)
        fclose(local);
    FtpClose(nData);
    return rv;
}
Example #4
0
STATUS FtpRetr (FTP * con , char * command ,
		       char *in , char * out)
{
  FILE *o;
  struct stat st;
  char buffer[FTPBUFSIZ];
  register int size;
  
  FtpFilenameChecker(&in,&out);

  if ( FtpTestFlag(con,FTP_REST) && stat(out,&st)==0)
    {
      con -> seek = st.st_size;
      if ((o=Ftpfopen(out,"a+"))==NULL)
	return EXIT(con,LQUIT);
    }
  else
    {
      con -> seek = 0;
      if ((o=Ftpfopen(out,"w+"))==NULL)
	return EXIT(con,LQUIT);
    }
  
  if ( FtpError(FtpData(con,command,in,"r")))
    {

      if (con->seek==0) return EXIT(con,con->err_no);
      
      con -> seek = 0;
      fclose(o);
      
      if ( FtpError(FtpData(con,command,in,"r")) )
	{
	  return EXIT(con,con->err_no);
	}
      
      if ((o=Ftpfopen(out,"w+"))==NULL)
	return EXIT(con,LQUIT);
    }
  
  
  fseek(o,con->seek,0);
  
  while((size=FtpReadBlock(con,buffer,FTPBUFSIZ))>0)
    {
      if (write(fileno(o),buffer,size)!=size)
	{
	  Ftpfclose(o);
	  return EXIT(con,LQUIT);
	}
    }

  Ftpfclose(o);
  return FtpClose(con);
}
Example #5
0
/*
 * FtpXfer - issue a command and transfer data
 *
 * return 1 if successful, 0 otherwise
 */
static int FtpXfer(const char *localfile, const char *path,
    netbuf *nControl, int typ, int mode)
{
    int l,c;
    char *dbuf;
    FILE *local = NULL;
    netbuf *nData;

    if (localfile != NULL)
    {
    local = fopen(localfile, (typ == FTPLIB_FILE_WRITE) ? "r" : "w");
    if (local == NULL)
    {
        strncpy(nControl->response, strerror(errno),
                    sizeof(nControl->response));
        return 0;
    }
    }
    if (local == NULL)
    local = (typ == FTPLIB_FILE_WRITE) ? stdin : stdout;
    if (!FtpAccess(path, typ, mode, nControl, &nData))
    return 0;
    dbuf = malloc(FTPLIB_BUFSIZ);
    if (typ == FTPLIB_FILE_WRITE)
    {
    while ((l = fread(dbuf, 1, FTPLIB_BUFSIZ, local)) > 0)
        if ((c = FtpWrite(dbuf, l, nData)) < l)
        printf("short write: passed %d, wrote %d\n", l, c);
    }
    else
    {
        while ((l = FtpRead(dbuf, FTPLIB_BUFSIZ, nData)) > 0)
        if (fwrite(dbuf, 1, l, local) <= 0)
        {
        perror("localfile write");
        break;
        }
    }
    free(dbuf);
    fflush(local);
    if (localfile != NULL)
    fclose(local);
    return FtpClose(nData);
}
Example #6
0
int main(int argc, char *argv[])
{
    int files_processed = 0;
    int opt;

    invocation = argv[0];
    optind = 1;
    if (strstr(argv[0],"send") != NULL)
	action = FTP_SEND;
    else if (strstr(argv[0],"get") != NULL)
	action = FTP_GET;
    else if (strstr(argv[0],"dir") != NULL)
	action = FTP_DIR;
    else if (strstr(argv[0],"list") != NULL)
	action = FTP_LIST;
    else if (strstr(argv[0],"rm") != NULL)
	action = FTP_RM;
    if ((action == 0) && (argc > 2))
    {
	if ( argc < 3 )		/* command + site */
	{
	    usage();
	    exit( EX_SYNTAX );
	}
	if (strcmp(argv[1],"send") == 0)
	    action = FTP_SEND;
    	else if (strcmp(argv[1],"get") == 0)
	    action = FTP_GET;
    	else if (strcmp(argv[1],"dir") == 0)
	    action = FTP_DIR;
	else if (strcmp(argv[1],"list") == 0)
	    action = FTP_LIST;
    	else if (strcmp(argv[1],"rm") == 0)
	    action = FTP_RM;
	if (action)
	    optind++;
    }
    if (action == 0)
    {
	usage();
	exit(EX_SYNTAX);
    }

    FtpInit();

    //    while (argv[optind] != NULL)
    while ( optind < argc )
    {
	if (argv[optind][0] != '-')
	{
	    if (host == NULL)
		host = argv[optind++];
	    else
	    {
		process_file(argv[optind++]);
		files_processed++;
	    }
	    continue;
	}
	opt = getopt(argc,argv,"abil:m:p:r:s:v:w");
	switch (opt)
	{
	  case '?' :
	    fprintf(stderr,"Invalid option: %c\n", opt);
	    usage();
	    exit(EX_SYNTAX);
	  case ':' :
	    usage();
	    exit(EX_SYNTAX);
	  case 'a' : mode = 'A'; break;
	  case 'b' : strippath = !strippath; break;
	  case 'i' : mode = 'I'; break;
	  case 'l' : user = optarg; break;
	  case 'm' : set_umask(optarg); break;
	  case 'p' : pass = optarg; break;
	  case 'r' : change_directory(optarg); break;
	  case 's' : site_cmd(optarg); break;
	  case 'v' :
	    if (opt == ':')
		ftplib_debug++;
	    else
		ftplib_debug = atoi(optarg);
	    break;
	  case 'w' : wildcard = !wildcard; break;
	  default :
	    usage();
	    exit(EX_SYNTAX);
	}
    }

    if (files_processed == 0)
    {
	ftp_connect();
	if ((action == FTP_DIR) || (action == FTP_LIST))
	    process_file(NULL);
	else
	{
	    char fnm[256];
	    do
	    {
	        char *nl;
		if (isatty(fileno(stdin)))
		    printf("file> ");
		if (fgets(fnm, sizeof(fnm), stdin) == NULL)
		    break;
		if ((nl = strchr(fnm,'\n')) != NULL)
		    *nl = '\0';
		process_file(fnm);
	    }
	    while (1);
	}
    }
    if (conn)
	FtpClose(conn);
    return 0;
}
Example #7
0
void process_file(char *fnm)
{
    int sts=0;
    fsz_t fsz;
    struct REMFILE *filelist = NULL;
    struct REMFILE rem;

    ftp_connect();
    FtpClearCallback(conn);
    if ((action == FTP_SEND) || (action == FTP_GET) || (action == FTP_RM))
    {
	if (action == FTP_SEND)
	{
	    struct stat info;
	    if (stat(fnm,&info) == -1)
	    {
	    	perror(fnm);
		return;
	    }
	    if (S_ISDIR(info.st_mode))
	    {
		if (!FtpMkdir(fnm, conn))
		    fprintf(stderr,"mkdir %s failed\n%s",fnm,FtpLastResponse(conn));
		else
		    if (ftplib_debug)
			fprintf(stderr,"Directory %s created\n",fnm);
		return;
	    }
            fsz = info.st_size;
	}
        else
        {
	    if (!wildcard)
	    {
		struct REMFILE *f;
		f = (struct REMFILE *) malloc(sizeof(struct REMFILE));
		memset(f,0,sizeof(struct REMFILE));
		f->next = filelist;
		filelist = f;
		f->fnm = strdup(fnm);
	    } else {
		netbuf *dir;
		char *buf;
		if (!FtpAccess(fnm, FTPLIB_DIR, FTPLIB_ASCII, conn, &dir))
		{
		    fprintf(stderr,"error requesting directory of %s\n%s\n",
			    fnm, FtpLastResponse(conn));
		    return;
		}
		buf = malloc(DIRBUF_SIZE);
		while (FtpRead(buf, DIRBUF_SIZE, dir) > 0)
		{
		    struct REMFILE *f;
		    char *p;
		    f = (struct REMFILE *) malloc(sizeof(struct REMFILE));
		    memset(f,0,sizeof(struct REMFILE));
		    f->next = filelist;
		    p = strchr(buf,'\n');
		    if (p)
			*p = '\0';
		    f->fnm = strdup(buf);
		    filelist = f;
		}
		free(buf);
		FtpClose(dir);
	    }
        }
    }
    switch (action)
    {
      case FTP_DIR :
	sts = FtpDir(NULL, fnm, conn);
	break;
      case FTP_LIST :
	sts = FtpNlst(NULL, fnm, conn);
	break;
      case FTP_SEND :
	rem.next = NULL;
	rem.fnm = fnm;
	rem.fsz = fsz;
	fsz /= 100;
	if (fsz > 100000)
	    fsz = 100000;
        if (ftplib_debug && fsz)
        {
	    FtpCallbackOptions opt;
	    opt.cbFunc = log_progress;
	    opt.cbArg = &rem;
	    opt.idleTime = 1000;
	    opt.bytesXferred = fsz;
	    FtpSetCallback(&opt,conn);
        }
	sts = FtpPut(fnm,strippath ? basename(fnm) : fnm,mode,conn);
	if (ftplib_debug && sts)
	    printf("%s sent\n",fnm);
	break;
      case FTP_GET :
	while (filelist)
	{
	    struct REMFILE *f = filelist;
	    filelist = f->next;
#if defined(__UINT64_MAX)
	    if (!FtpSizeLong(f->fnm, &fsz, mode, conn))
#else
	    if (!FtpSize(f->fnm, &fsz, mode, conn))
#endif
		fsz = 0;
	    f->fsz = fsz;
	    fsz /= 100;
	    if (fsz > 100000)
		fsz = 100000;
	    if ( fsz == 0 )
		fsz = 32768;
	    if (ftplib_debug)
	    {
		FtpCallbackOptions opt;
		opt.cbFunc = log_progress;
		opt.cbArg = f;
		opt.idleTime = 1000;
		opt.bytesXferred = fsz;
		FtpSetCallback(&opt,conn);
	    }
	    sts = FtpGet(f->fnm,f->fnm,mode,conn);
	    if (ftplib_debug && sts)
		printf("%s retrieved\n",f->fnm);
	    free(f->fnm);
	    free(f);
	}
	break;
      case FTP_RM :
	while (filelist)
	{
	    struct REMFILE *f = filelist;
	    filelist = f->next;
	    sts = FtpDelete(f->fnm,conn);
	    if (ftplib_debug && sts)
		printf("%s deleted\n", f->fnm);
	    free(f->fnm);
	    free(f);
	}
	break;
    }
    if (!sts)
	printf("ftp error\n%s\n",FtpLastResponse(conn));
    return;
}
Example #8
0
long FtpFileDownload( void *fs, char *url, char *dest, char *fullpath, long length )
{
	long	dataread, datatotal=0;

	if ( fs )
	{
		void	*fp;
		FILE	*ff;
		char	*buffer=NULL;

		if ( fs && !IsStopped() )
		{
			if ( !(ff = fopen( dest, "wb+" )) )
			{
				StatusSetf( "Cannot open local file %s for writing.", dest );
				return -2;
			}
	
			fp = (void*)FtpOpen( fs, fullpath, 'R' );
			if ( fp ) 
			{
				if ( !length )
					length = FtpFileGetSize( url );

				StatusSetID( IDS_DOWNLOADING, fullpath );

				buffer = (char*)malloc( 1024*4 );

				if ( length && buffer )
				{
					long writesize;

					dataread = 1;
					while( dataread>0 && buffer && !IsStopped() )
					{
						//sprintf( msg, "Downloading %s...%d KB (%.2f%%)", fullpath, (datatotal)/1024, (100*((datatotal)/(float)length)) );
						StatusSetID( IDS_DOWNLOADINGKB, fullpath, (datatotal)/1024, (100*((datatotal)/(float)length))  );
	
						dataread = NetRead( fp, buffer, 1024*1 );
						datatotal+= dataread;
						if ( dataread ){
							writesize = fwrite( buffer, 1, dataread, ff );
							if ( writesize == 0 ){
								dataread = 0;
								datatotal = -2;
							}
						}
					}
					free( buffer );
				}
				FtpClose( fp );
			} else 
			{
				const char *msg = NetworkErr( NULL );
				if ( !msg ) msg = "Maybe path does not exist?";
				ErrorMsg( "Cannot open ftp file %s\nbecause ...\n%s", fullpath, msg ); 
				datatotal = -1;
			}
			fclose( ff );
		}

		if ( IsStopped() )
		{
			StatusSetID( IDS_DOWNLOADSTOP );
			remove( dest );
			datatotal = -1;
		}

	}
	return datatotal;
}
Example #9
0
int PostProc_UploadLogs( char *uploadloglocation, int deletelog, int compressed_logs, char **files , long fileCount )
{
	char	newfilename[256];
	char	sourcepath[256];

	if ( files && fileCount )
	{
		char	*source, *p;
		long	count=0, filenum, perc, doftp=FALSE, ret;
		LLStructRecPtr next = gFopenHistoryPtr;
		char	server[128];
		char	ftppath[256],
				file[128];
		char	name[64];
		char	passwd[32];
		char	msg[256];
		void	*fs;

		if ( IsURL( uploadloglocation ) )
		{
			ExtractUserFromURL( uploadloglocation, server, name, passwd, ftppath );
			fs = (void*)FtpServerOpen( server, name, passwd );
			if ( fs ){
				doftp = TRUE;
				sprintf( msg, "FTP: %s@%s/%s", name,server,ftppath );
				StatusSet( msg );
			} else {
				FtpServerOpenError( server );
				return 1;
			}
		} else
			StatusSetID( IDS_COPYINGFILE, "." );

		// upload log files.....
		if ( fs )
		{
			count = 0;
			filenum = fileCount;

			// go through all logs.....
			while( files[count] && !IsStopped() )
			{
				perc = ((100*count)/filenum);
				StatusWindowSetProgress( perc, NULL );

				PathFromFullPath( files[count], sourcepath );
				source = files[count];
				if ( strstr( source, sourcepath ) )
				{
					source += strlen( sourcepath );
				}

				// Upload LOGS
				if ( doftp )
				{
					long upstatus;
					p = files[count] + strlen( sourcepath );
					if ( compressed_logs && !strstr( p, ".gz" ) ) 
						sprintf( file, "%s%s.gz", ftppath, p );
					else
						sprintf( file, "%s%s", ftppath, p );

					upstatus = FtpFileUpload( fs, files[count], file, p );
					if ( upstatus == FTPERR_COMPLETE  )
					{
						if( deletelog )
							ret = remove( files[count] );
					}
				}
				else 
				{
					CopyFilenameUsingPath( newfilename, uploadloglocation, source );
				}
				count++;
			}
		}

		if ( doftp )
			FtpClose( fs );
	} else
		return 2;
	return 0;
}
Example #10
0
int PostProc_UploadReport( const char *uploadURL, int deletereport, int zipreport, char *reportLocation )
{
	if ( gFopenHistoryPtr && !IsStopped() )
	{
		char	sourcepath[256];
		char	server[256], ftppath[256], name[64], passwd[32];
		char	*source;
		void	*fs;

		if ( IsURL( uploadURL ) )
		{
			char msg[256];
			ExtractUserFromURL( (char*)uploadURL, server, name, passwd, ftppath );
			DateFixFilename( ftppath, 0 );
			fs = (void*)FtpServerOpen( server, name, passwd );
			if ( fs ){
				sprintf( msg, "FTP %s@%s/%s", name,server,ftppath );
				StatusSet( msg );
			} else 
			{
				FtpServerOpenError( server );
				return 1;
			}
		}

		PathFromFullPath( reportLocation, sourcepath );
		DateFixFilename( sourcepath, 0 );

		// ---------------- UPLOAD ALL INDIVIDUAL FILES
		if ( !zipreport )
		{
			long files;
			files = UploadFiles( fs, (char*)uploadURL, sourcepath, ftppath, deletereport );
			if ( files>0 )
				OutDebugs( "%d files uploaded.", files );
			else
				OutDebugs( "Upload canceled" );

			FtpClose( fs );
			OutDebugs( "Ftp Site Closed" );
		} else
		// ----------------- UPLOAD SINGLE ZIP REPORT
		{
			long	uploadStatus = 0;
			char	srczipname[256];
			char	newfilename[256];

			mystrcpy( srczipname, reportLocation );
			DateFixFilename( srczipname, 0 );
			PathFromFullPath( srczipname, sourcepath );

			if ( !strstr( srczipname, ".zip" ) )
			{
				source = strrchr( srczipname, '.' );
				if ( source )
					mystrcpy( source, ".zip" );
				else
					return 3;
			}
			source = srczipname;

			// Find the FILENAME Component
			if ( strstr( srczipname, sourcepath ) )
			{
				source += strlen( sourcepath );
			}

			// generate remote full path PATH+NAME
			CopyFilenameUsingPath( newfilename, (char*)uploadURL, source );

			// Ok things are ok, lets now upload the zip file
			if ( IsURL( uploadURL ) )
			{
				char fullURLPath[256];
				sprintf( fullURLPath, "%s%s", ftppath, source );

				// upload the zip file
				uploadStatus = FtpFileUpload( fs, srczipname, fullURLPath, source );
				if ( uploadStatus == FTPERR_CANTMAKEDIR )
					ErrorMsg( "Could not make directory %s on ftp server .\nMaybe path does not exist?", ftppath );

				FtpClose( fs );
			}

			if( deletereport && uploadStatus == FTPERR_COMPLETE )
			{
				OutDebugs( "Deleting local zip file %s", srczipname );
				remove( srczipname );
			}
		}
	}
	return 0;
}
Example #11
0
// -2  cant make dir
long FtpFileUpload( void *fs, char *localfilename, char *remotepath, char *file )
{
	long length=0, failedmkdir=FALSE, datadone;

	if ( fs && !IsStopped() )
	{
		void	*hFtpFile;
		FILE	*ff;
		long	dataleft, dataread, perc;
		char	*buffer=NULL;
		char	msg[500];

		if ( !(ff = fopen( localfilename, "rb" )) )
		{
			StatusSetID( IDS_ERR_FILEFAILED, localfilename );
			return FTPERR_NOFILE;
		}

		if ( fs && ff )
		{
			char dir[256], *p;
			static char lastdir[256];
			int tries = 0;

			// Convert all Windows slashes to Unix ones.
			p = remotepath;
			while( *p )
			{
				if ( *p == '\\' ) *p = '/';
				p++;
			}

			// Try to create the remote directories first.
			if ( p )
			{
				// Try to open remote file, if we cant make the remote dir.
				while( (hFtpFile = (void*)FtpOpen( fs, remotepath, 'W' )) == NULL && tries<5 )
				{
					PathFromFullPath( remotepath, dir );
					if ( strcmp( dir, lastdir ) ){
						//long l=mystrcpy( lastdir, dir );
						//if ( dir[l-1] == '/' ) dir[l-1]=0;
						sprintf( msg, "Making dir %s...", dir );
						StatusSet( msg );

						if ( !FtpMakeDir( fs, dir ) )
						{
							failedmkdir = TRUE;
							OutDebugs( "Cannot create remote ftp directory %s", dir );
						} else {
							failedmkdir = FALSE;
						}
					}
					tries++;
					OutDebug( "Trying again to write to server..." );
				}
			}


			// If remote file is opened.
			if ( hFtpFile ) 
			{
				StatusSetID( IDS_UPLOADINGTO, remotepath );
				const long read_size = (4*1024);

				datadone = 0;
				length = dataleft = (long)GetFileLength( localfilename );
				if ( length )
					buffer = (char*)malloc( read_size );

				if ( buffer )
				{
					while( dataleft>0 && buffer && !IsStopped() )
					{
						dataread = fread( buffer, 1, read_size, ff );
						if ( dataread )
							NetWrite( hFtpFile, buffer, dataread );

						dataleft -= dataread;
						datadone += dataread;

						// ------------------------------------------------------
						perc = (long)(100*((length-dataleft)/(float)length));
						sprintf( msg, "Uploading %s  (%d bytes %d%%)", remotepath, datadone, perc );
						StatusSet( msg );
						// ------------------------------------------------------
					}
					if ( datadone == length )
						OutDebug( "Uploaded complete." );

					free( buffer );
				}
				FtpClose( hFtpFile );
				OutDebug( "Ftp File Closed" );
			}
		}
		if ( ff )
			fclose( ff );
	}

	if ( failedmkdir )
		return FTPERR_CANTMAKEDIR;

	if ( IsStopped() )
		return FTPERR_STOPPED;

	if ( datadone == length )
		return FTPERR_COMPLETE;

	return FTPERR_COMPLETEFAIL;
}
void process_file(char *fnm) {
	int sts = 0;
	int fsz;
	struct REMFILE *filelist = NULL;
	struct REMFILE rem;

	ftp_connect();
	FtpOptions(FTPLIB_CALLBACK, (long) NULL, conn);
	if ((action == FTP_SEND) || (action == FTP_GET)) {
		if (action == FTP_SEND) {
			struct stat info;
			if (stat(fnm, &info) == -1) {
				perror(fnm);
				return;
			}
			if (S_ISDIR(info.st_mode)) {
				if (!ftpMkdir(fnm))
					fprintf(stderr, "mkdir %s failed\n%s", fnm,
							FtpLastResponse(conn));
				else if (ftplib_debug)
					fprintf(stderr, "Directory %s created\n", fnm);
				return;
			}
			fsz = info.st_size;
		} else {
			if (!wildcard) {
				struct REMFILE *f;
				f = (struct REMFILE *) malloc(sizeof(struct REMFILE));
				memset(f, 0, sizeof(struct REMFILE));
				f->next = filelist;
				filelist = f;
				f->fnm = strdup(fnm);
			} else {
				netbuf * dir;
				char *buf;
				if (!FtpAccess(fnm, FTPLIB_DIR, FTPLIB_ASCII, conn, &dir)) {
					fprintf(stderr, "error requesting directory of %s\n%s\n",
							fnm, FtpLastResponse(conn));
					return;
				}
				buf = malloc(DIRBUF_SIZE);
				while (FtpRead(buf, DIRBUF_SIZE, dir) > 0) {
					struct REMFILE *f;
					char *p;
					f = (struct REMFILE *) malloc(sizeof(struct REMFILE));
					memset(f, 0, sizeof(struct REMFILE));
					f->next = filelist;
					p = strchr(buf, '\n');
					if (p)
						*p = '\0';
					f->fnm = strdup(buf);
					filelist = f;
				}
				free(buf);
				FtpClose(dir);
			}
		}
	}
	switch (action) {
	case FTP_DIR:
		sts = FtpDir(NULL, fnm, conn);
		break;
	case FTP_LIST:
		sts = FtpNlst(NULL, fnm, conn);
		break;
	case FTP_SEND:
		rem.next = NULL;
		rem.fnm = fnm;
		rem.fsz = fsz;
		fsz /= 10;
		if (fsz > 100000)
			fsz = 100000;
		if (ftplib_debug && fsz) {
			FtpOptions(FTPLIB_CALLBACK, (long) log_progress, conn);
			FtpOptions(FTPLIB_IDLETIME, (long) 1000, conn);
			FtpOptions(FTPLIB_CALLBACKARG, (long) &rem, conn);
			FtpOptions(FTPLIB_CALLBACKBYTES, (long) fsz, conn);
		}
		sts = FtpPut(fnm, fnm, mode, conn);
		if (ftplib_debug && sts)
			printf("%s sent\n", fnm);
		break;
	case FTP_GET:
		while (filelist) {
			struct REMFILE *f = filelist;
			filelist = f->next;
			if (!FtpSize(f->fnm, &fsz, mode, conn))
				fsz = 0;
			f->fsz = fsz;
			fsz /= 10;
			if (fsz > 100000)
				fsz = 100000;
			if (ftplib_debug && fsz) {
				FtpOptions(FTPLIB_CALLBACK, (long) log_progress, conn);
				FtpOptions(FTPLIB_IDLETIME, (long) 1000, conn);
				FtpOptions(FTPLIB_CALLBACKARG, (long) f, conn);
				FtpOptions(FTPLIB_CALLBACKBYTES, (long) fsz, conn);
			}
			sts = FtpGet(f->fnm, f->fnm, mode, conn);
			if (ftplib_debug && sts)
				printf("%s retrieved\n", f->fnm);
			free(f->fnm);
			free(f);
		}
		break;
	case FTP_RM:
		while (filelist) {
			struct REMFILE *f = filelist;
			filelist = f->next;
			sts = FtpDelete(f->fnm, conn);
			if (ftplib_debug && sts)
				printf("%s deleted\n", f->fnm);
			free(f->fnm);
			free(f);
		}
		break;
	}
	if (!sts)
		printf("ftp error\n%s\n", FtpLastResponse(conn));
	return;
}