Article 2724 of comp.sources.unix:
Path: nntpd.lkg.dec.com!crl.dec.com!crl.dec.com!caen!spool.mu.edu!sol.ctr.columbia.edu!news.uoregon.edu!inquo!vyzynz!news1.cris.com!newshost.comco.com!news.texas.net!news.kei.com!newsfeed.internetmci.com!in1.uu.net!vixie!vixie!not-for-mail
From: orel@dxunk1.cern.ch (Oleg Orel)
Newsgroups: comp.sources.unix
Subject: v29i068: libftp - C library for FTP client access, V5.0, Part07/08
Date: 12 Dec 1995 00:36:00 -0800
Organization: Vixie Enterprises
Lines: 2052
Sender: vixie@vix.com
Approved: vixie@gw.home.vix.com
Message-ID: <4ajetg$amp@gw.home.vix.com>
References: <1.818757291.10931@gw.home.vix.com>
NNTP-Posting-Host: gw.home.vix.com

Submitted-By: orel@dxunk1.cern.ch (Oleg Orel)
Posting-Number: Volume 29, Issue 68
Archive-Name: libftp-5.0/part07

#!/bin/sh
# to extract, remove the header and type "sh filename"
if `test ! -s ./FtpIO.c`
then
echo "writing ./FtpIO.c"
cat > ./FtpIO.c << '\End\Of\Shar\'
static char rcsid[] = "$Id: FtpIO.c,v 5.0 1995/12/10 10:28:38 orel Exp $";

/*
	$Log: FtpIO.c,v $
 * Revision 5.0  1995/12/10  10:28:38  orel
 * LIBFTP Version 5.0 (Distributed revision)
 *
 * Revision 4.1  1995/12/02  11:23:07  orel
 * *** empty log message ***
 *
 * Revision 4.0  1995/07/11  07:00:26  orel
 * Libftp Version 4.0
 *
 * Revision 4.0  1995/07/11  07:00:26  orel
 * Libftp Version 4.0
 *
 * Revision 3.0  1995/03/20  05:26:07  orel
 * *** empty log message ***
 *
 * Revision 3.0  1995/03/20  05:26:07  orel
 * *** empty log message ***
 *
 * Revision 2.6  1995/03/20  05:18:13  orel
 * *** empty log message ***
 *
 * Revision 2.5  1995/02/26  16:46:50  orel
 * *** empty log message ***
 *
 * Revision 2.5  1995/02/26  16:46:50  orel
 * *** empty log message ***
 *
 * Revision 2.4  1995/02/18  15:42:53  orel
 * modify for recurive mget
 *
 * Revision 2.4  1995/02/18  15:42:53  orel
 * modify for recurive mget
 *
 * Revision 2.3  1995/02/04  09:02:53  orel
 * add rcsid
 *
 * Revision 2.3  1995/02/04  09:02:53  orel
 * add rcsid
 *

*/
/*		      Library for ftpd clients.(libftp)
			Copyright by Oleg Orel
			 All rights reserved.
			
This  library is desined  for  free,  non-commercial  software  creation. 
It is changeable and can be improved. The author would greatly appreciate 
any  advises, new  components  and  patches  of  the  exist
ing  programs.
Commercial  usage is  also  possible  with  participation of it's author.



*/

#include "FtpLibrary.h"

int FtpRead(FTP *con)
{
  int c;
  
  if ( con -> mode == 'I' )
    return FtpGetc(con,FTPDATA(con));
  
  if ( con->ch != EOF )
    {
      c=con->ch;
      con->ch=EOF;
      return c;
    }
  
  c=FtpGetc(con,FTPDATA(con));
  
  if ( c == Ctrl('M') )
    {
      c = FtpGetc(con,FTPDATA(con));
      
      if ( c == Ctrl('J') )
	return '\n';
      con->ch = c;
      return Ctrl('M');
    }
  return c;
}

int FtpWrite(FTP *ftp,char c)
{
  
  if ( ftp -> mode == 'I' || c != '\n' )
    return FtpPutc(ftp,FTPDATA(ftp),c);
  
  FtpPutc(ftp,FTPDATA(ftp),Ctrl('M'));
  return FtpPutc(ftp,FTPDATA(ftp),Ctrl('J'));
}

	  
int FtpGetc(FTP *ftp,FILE *fp)
{
  fd_set fds;
  char c;
  
  FD_ZERO(&fds);
  FD_SET(fileno(fp),&fds);

  if (select(getdtablesize(), &fds, 0, 0, &(ftp->timeout))<1)
    return EXIT(ftp,QUIT);

  if (read(fileno(fp),&c,1)<1)
    return EOF;
  
  if (ftp->hash!=NULL) (*ftp->hash)(ftp,1);
  
  return (int)c;
}


STATUS FtpPutc(FTP *ftp,FILE *fp,char c)
{
  fd_set fds;
  
  FD_ZERO(&fds);
  FD_SET(fileno(fp),&fds);
  
  if (select(getdtablesize(), 0, &fds, 0, &(ftp->timeout))<1)
    return EXIT(ftp,QUIT);
  
  if (write(fileno(fp),&c,1)!=1)
    return EXIT(ftp,QUIT);

  if (ftp->hash!=NULL) (*ftp->hash)(ftp,1);
}


STATUS FtpReadBlock(FTP *ftp, char *buffer, int size)
{
  fd_set fds;
  register int rsize,status;
  
  FD_ZERO(&fds);
  FD_SET(fileno(FTPDATA(ftp)),&fds);
  
  if (select(getdtablesize(), &fds,0, 0, &(ftp->timeout))<1)
    return EXIT(ftp,QUIT);
  
  
  if ((rsize=read(fileno(FTPDATA(ftp)),buffer,size))<0)
    return EXIT(ftp,QUIT);
  
  if (ftp->hash!=NULL && rsize!=0) (*ftp->hash)(ftp,rsize);
  
  if (ftp->mode == 'A')
    {
      char buffer2[size];
      register int i,ii;

      for (i=0,ii=0;i<rsize;i++,ii++)
	if (buffer[i]==Ctrl('M')&&buffer[i+1]==Ctrl('J'))
	  buffer2[ii]='\n',i++;
	else
	  buffer2[ii]=buffer[i];
      
      rsize=ii;
      bcopy(buffer2,buffer,rsize);
    }
  return rsize;
}


STATUS FtpWriteBlock(FTP *ftp, char *buffer, int size)
{
  fd_set fds;
  register int wsize;
  char buffer2[size*2];
  
  FD_ZERO(&fds);
  FD_SET(fileno(FTPDATA(ftp)),&fds);
  
  if (select(getdtablesize(), 0, &fds, 0, &(ftp->timeout))<1)
    return EXIT(ftp,QUIT);
  
  
  if (ftp->mode=='A')
    {
      register int i,ii;

      for(i=0,ii=0;i<size;i++,ii++)
	if (buffer[i]=='\n')
	  buffer2[ii++]=Ctrl('M'),buffer2[ii]=Ctrl('J');
	else
	  buffer2[ii]=buffer[i];
      buffer=buffer2;
      size=ii;
    }
  
  if ((wsize=write(fileno(FTPDATA(ftp)),buffer,size))!=size) 
    return EXIT(ftp,QUIT);
  
  if ( ftp->hash!=NULL && wsize!=0 ) (*ftp->hash)(ftp,wsize);
  
  return wsize;
}


    









\End\Of\Shar\
else
  echo "will not over write ./FtpIO.c"
fi
if `test ! -s ./FtpInit.c`
then
echo "writing ./FtpInit.c"
cat > ./FtpInit.c << '\End\Of\Shar\'
static char rcsid[] = "$Id: FtpInit.c,v 5.0 1995/12/10 10:28:38 orel Exp $";

/*
	$Log: FtpInit.c,v $
 * Revision 5.0  1995/12/10  10:28:38  orel
 * LIBFTP Version 5.0 (Distributed revision)
 *
 * Revision 4.1  1995/12/02  11:23:07  orel
 * *** empty log message ***
 *
 * Revision 4.0  1995/07/11  07:00:26  orel
 * Libftp Version 4.0
 *
 * Revision 4.0  1995/07/11  07:00:26  orel
 * Libftp Version 4.0
 *
 * Revision 3.0  1995/03/20  05:26:07  orel
 * *** empty log message ***
 *
 * Revision 3.0  1995/03/20  05:26:07  orel
 * *** empty log message ***
 *
 * Revision 2.4  1995/03/20  05:18:13  orel
 * *** empty log message ***
 *
 * Revision 2.3  1995/02/26  16:46:50  orel
 * *** empty log message ***
 *
 * Revision 2.3  1995/02/26  16:46:50  orel
 * *** empty log message ***
 *
 * Revision 2.2  1995/02/18  15:42:53  orel
 * modify for recurive mget
 *
 * Revision 2.2  1995/02/18  15:42:53  orel
 * modify for recurive mget
 *
 * Revision 2.1  1995/02/04  09:02:53  orel
 * add rcsid
 *
 * Revision 2.1  1995/02/04  09:02:53  orel
 * add rcsid
 *

*/
/*
		      Library for ftpd clients.(libftp)
			Copyright by Oleg Orel
			 All rights reserved.
			
This  library is desined  for  free,  non-commercial  software  creation. 
It is changeable and can be improved. The author would greatly appreciate 
any  advises, new  components  and  patches  of  the  existing  programs.
Commercial  usage is  also  possible  with  participation of it's author.



*/

#include "FtpLibrary.h"

FTP FtpInit = {
  NULL,     /*sock*/
  NULL,  /*data*/
  'A',   /*mode*/
  0,     /*errno*/
  0,     /*ch*/
  NULL,NULL,NULL, NULL, /*funcs*/
  0, /*seek*/
  FTP_HANDLERS, /*flags*/
  {120,0}, /*timeout 2 min*/
  21, /*Port*/
  0, /*Counter*/
};



FTP *FtpCreateObject()
{
  FTP *new = (FTP *) malloc (sizeof(FTP));

  bcopy(&FtpInit,new,sizeof(FTP));

  return new;
}


\End\Of\Shar\
else
  echo "will not over write ./FtpInit.c"
fi
if `test ! -s ./FtpLibrary.h`
then
echo "writing ./FtpLibrary.h"
cat > ./FtpLibrary.h << '\End\Of\Shar\'
/*
		      Library for ftpd clients.(libftp)
			Copyright by Oleg Orel
			 All rights reserved.
			
This  library is desined  for  free,  non-commercial  software  creation. 
It is changeable and can be improved. The author would greatly appreciate 
any  advises, new  components  and  patches  of  the  existing  programs.
Commercial  usage is  also  possible  with  participation of it's author.


*/

  
#ifndef __FTPLIBRARY_H
#define __FTPLIBRARY_H


#ifdef __cplusplus
    extern "C" {
#endif
#include <stdio.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/timeb.h>
#include <sys/socket.h>
#include <errno.h>

#ifdef _AIX
#include <sys/select.h>
#endif
      
#include <arpa/ftp.h>
#include <netinet/in.h>
#include <netdb.h>
#include <varargs.h>
#include <arpa/telnet.h>
#include <sys/stat.h>
#include <strings.h>
      

extern char *sys_errlist[];
extern int errno;


		/* Standard Macros & Definitions */

enum {FTP_REST=1,FTP_NOEXIT=2,FTP_HANDLERS=4};
		
      
#define EXIT(con,e) \
  ( con -> errno = e,  \
    ((con->flags&FTP_HANDLERS)&&(e==QUIT||e==LQUIT)&&(con->IO != NULL))?\
             (*(con->IO))(con,e,sys_errlist[errno]):0,\
   ((con->flags&FTP_HANDLERS)&&(con->error != NULL) && (e < 0) )? \
             (*(con->error))(con,e,FtpMessage(e)):0,\
   e)
	
   
#define MAX_ANSWERS 10 /* Number of known goodest answers for reqest */
#define FTP_NFDS 64
#define FTPBUFSIZ BUFSIZ
#define LQUIT (-6)
#define QUIT (-5) /* Few time ago QUIT character been 
		     equivalence to zero, changed for clear
		     conflicts with reading functions */
#define OK (0)    /* Synonym for neitral good answer */
#define Ctrl(x) ((x) - '@')
#define FREE(x) memset ( &(x) , '\0' , sizeof (x) )
#define CUT(x) ((x)&0xff)
#define FtpStatus(ftp,what) \
    ( ((ftp)->flags&=~FTP_HANDLERS),(what),((ftp)->flags|=FTP_HANDLERS),\
     ((ftp)->errno) )
#define FtpError(what) ( (what)<0 )
#define FtpAssert(ftp,what) if (FtpError(what)) return EXIT((ftp),(ftp)->errno);

typedef int STATUS;
typedef char FtpString[256];

#ifdef __GNUC__
#define INLINE inline
#else
#define INLINE
#endif



		/* Common Information Structure */

typedef struct/* All structure initialize from edited struct FtpInit */
{
  FILE *sock;       /* Command stream to server */

#define FTPDATA(x) ((x)->data)
#define FTPCMD(x) ((x)->sock)


  FILE *data;       /* Data stream to server */
  char mode;        /* Binary, Ascii, ......... */
  int errno;        /* Last error code */
  int ch;           /* Help character for ascii streams */
  
  STATUS (*error)();
  STATUS (*debug)();
  STATUS (*IO)();
  STATUS (*hash)(); /* Call with reading/writing next "int" characters
			 from stream */  
  int seek;        /*
		     Warning! If server not supported REST-command,
		     then seek variable automaticaly turn to zero
		   */
  int flags;       /* FTP_REST, 
		      FTP_NOEXIT,
		      FTP_HANDLERS */
  struct timeval timeout;
                   /* How long must be waiting next character 
		      from server */
  int port;
  FtpString title;    /* Using for FtpLog, FtpConnect lets hostname */
  unsigned long counter; 
                   /* Using by FtpHash */
} FTP;

typedef struct 
{
  struct tm createtime;
  unsigned long size;
  FtpString host;
  FtpString file;
} ARCHIE;


typedef struct __ftp_stat__
{
  char type;        /* Type of file dir, regular, ..... */
  int  mode;        /* Protections */
  int  inodes;
  FtpString user;
  FtpString group;
  unsigned long size;
  int month;
  int day;
  FtpString time;
  FtpString name;
  FtpString link;
  struct __ftp_stat__ *next;
} FTP_STAT;


enum {no,yes};
enum {off,on};
enum {false,true};

extern FTP FtpInit;

/* Options defines */

#define FtpSetFlag(ftp,flag) ((ftp)->flags|=(flag))
#define FtpClearFlag(ftp,flag) ((ftp)->flags &= (~(flag)) )
#define FtpTestFlag(ftp,flag) ((ftp)->flags&(flag)==flag)
#define FtpSetTimeout(ftp,tim) \
  ((ftp)->timeout.tv_sec=tim,(ftp)->timeout.tv_usec=0)
#define FtpSetPort(ftp,prt) ((ftp)->port=(prt))

/* Connect & disconnect */ 

STATUS  FtpConnect(FTP **con,char *hostname);
#define FtpUser(ftp,user)           FtpCommand(ftp,"USER %s",user,230,331,332,EOF)
#define FtpPassword(ftp,pas)        FtpCommand(ftp,"PASS %s",pas,230,332,EOF)
#define FtpAccount(ftp,acc)         FtpCommand(ftp,"ACCT %s",acc,230,EOF)
STATUS  FtpLogin(FTP **con,char *host ,char *user,char *pass,char *acct);
STATUS  FtpBye (FTP * con);
STATUS  FtpQuickBye (FTP * con);
STATUS  FtpAbort(FTP *ftp);

/* Set type of transfer */

STATUS FtpType(FTP *ftp,char type);
#define FtpAscii(ftp)               FtpType(ftp,'A')
#define FtpBinary(ftp)              FtpType(ftp,'I')


/* Send/Receive and handling Procedure(s) */

STATUS  FtpCopy(FTP *ftp1, FTP *ftp2, char *in, char *out);
STATUS  FtpPassiveTransfer(FTP *ftp1, FTP *ftp2, char *in, char *out);

STATUS  FtpRetr(FTP *con, char *command,char *inp,char *out);
#define FtpGet(ftp,in,out)          FtpRetr(ftp,"RETR %s",in,out)
#define FtpDirectory(ftp,pat,out)   FtpRetr(ftp,"LIST %s",pat,out)
#define FtpDir(ftp,out)             FtpRetr(ftp,"LIST","",out)

STATUS  FtpStor(FTP *con ,char*command ,char *inp,char *out);
#define FtpPut(ftp,in,out)          FtpStor(ftp,"STOR %s",in,out)

STATUS  FtpData( FTP * con , char * command , char * param , char *mode);
STATUS  FtpPort ( FTP *con ,int ,int ,int ,int ,int ,int );
#define FtpOpenRead(ftp,file)       FtpData(ftp,"RETR %s",file,"r")
#define FtpOpenWrite(ftp,file)      FtpData(ftp,"STOR %s",file,"w")
#define FtpOpenAppend(ftp,file)     FtpData(ftp,"APPE %s",file,"r")
STATUS  FtpOpenDir( FTP * con , char * files );
STATUS  FtpClose ( FTP *);

/* Command for hand transfer */

STATUS  FtpRead ( FTP * con);
STATUS  FtpWrite ( FTP * con , char c);
int     FtpGetc ( FTP * ftp, FILE *fp );
STATUS  FtpPutc (FTP *ftp, FILE *fp, char c);

/* Manipulation commands for remote server */

STATUS  FtpCommand ();
#define FtpChdir(ftp,dir)           FtpCommand(ftp,"CWD %s",dir,200,250,EOF)
#define FtpMkdir(ftp,dir)           FtpCommand(ftp,"MKD %s",dir,200,257,EOF)
#define FtpRm(ftp,dir)              FtpCommand(ftp,"DELE %s",dir,200,250,EOF)
STATUS  FtpChmod(FTP *,char*file,int mode);
char   *FtpPwd(FTP *con);
char   *FtpSyst(FTP *con);
int     FtpSize(FTP *con,char *filename);
STATUS  FtpMove ( FTP *con,char * old,char *new);
STATUS  FtpStat( FTP *con, char *pat, FTP_STAT **);
STATUS  FtpStatFree(FTP_STAT *);

/* Procedures for dialog with remote server */

STATUS  FtpInitMessageList();
STATUS  FtpSendMessage( FTP * con , char * Message );
int     FtpGetMessage( FTP * con , char * Message);
char   *FtpMessage(int Number);
int     FtpNumber ( char * Message );


/* Debug */

#define FtpSetErrorHandler(con,f) (con)->error = f
#define FtpSetDebugHandler(con,f) (con)->debug = f 
#define FtpSetIOHandler(con,f) (con)->IO =f
#define FtpSetHashHandler(con,f) (con)->hash =f
#define FtplibDebug(t) FtpDebug(&FtpInit)

STATUS  FtpDebugDebug ( FTP *con, int errno, char * Message);
STATUS  FtpDebugError ( FTP *con, int errno, char * Message);
STATUS  FtpDebugIO    ( FTP *con, int errno, char * Message);
STATUS  FtpLog(char *progtitle, char *msg);
STATUS  FtpHash ( FTP *con, unsigned long number_of_bytes );
void    FtpDebug ( FTP * con );
STATUS  FtpBadReply550 (char *message);


/* Other Procedures */

FTP    *FtpCreateObject();
FILE   *FtpFullOpen(char * file,char * mode );
STATUS  FtpFullSyntax(FtpString,FtpString,FtpString,FtpString,FtpString);
FILE   *Ftpfopen(char *filename,char *mode);
STATUS  Ftpfclose(FILE *);
STATUS  FtpFullClose(FILE *);
STATUS  FtpGood ();
STATUS  FtpGood1 (int, int *);
struct  hostent *FtpGetHost(char *host);
STATUS  FtpFilenameChecher(char *input, char *output);
STATUS  FtpLink(FTP *,FTP *);
int     FtpArchie(char *what, ARCHIE *, int number);
char   *word(char *s,int n);
STATUS  FtpHttpGet(char *server,int port,char *spec, char *newfile);

#ifdef __cplusplus
}
#endif
      

/* Additional definitions */

#ifdef _AIX1
int accept (int, struct sockaddr_in*, int*);
char *bcopy (char*, char*, size_t);
int bind (int, const void*, int);
int connect (int, struct sockaddr_in*, int);
int gethostname (char*, size_t);
int getsockname (int, struct sockaddr_in*, int*);
int getpeername (int, struct sockaddr_in*, int*);
int getsockopt (int, int, int, void*, int*);
int listen(int, int);
int setsockopt (int, int, int, void*, int);
int socket (int, int, int);
void free (void*);
void *malloc (size_t);
#endif




#endif /* __FTPLIBRARYH_ */



\End\Of\Shar\
else
  echo "will not over write ./FtpLibrary.h"
fi
if `test ! -s ./FtpLogin.c`
then
echo "writing ./FtpLogin.c"
cat > ./FtpLogin.c << '\End\Of\Shar\'
static char rcsid[] = "$Id: FtpLogin.c,v 5.0 1995/12/10 10:28:38 orel Exp $";

/*
	$Log: FtpLogin.c,v $
 * Revision 5.0  1995/12/10  10:28:38  orel
 * LIBFTP Version 5.0 (Distributed revision)
 *
 * Revision 4.1  1995/12/02  11:23:07  orel
 * *** empty log message ***
 *
 * Revision 4.0  1995/07/11  07:00:26  orel
 * Libftp Version 4.0
 *
 * Revision 4.0  1995/07/11  07:00:26  orel
 * Libftp Version 4.0
 *
 * Revision 3.0  1995/03/20  05:26:07  orel
 * *** empty log message ***
 *
 * Revision 3.0  1995/03/20  05:26:07  orel
 * *** empty log message ***
 *
 * Revision 2.4  1995/03/20  05:18:13  orel
 * *** empty log message ***
 *
 * Revision 2.3  1995/02/26  16:46:50  orel
 * *** empty log message ***
 *
 * Revision 2.3  1995/02/26  16:46:50  orel
 * *** empty log message ***
 *
 * Revision 2.2  1995/02/18  15:42:53  orel
 * modify for recurive mget
 *
 * Revision 2.2  1995/02/18  15:42:53  orel
 * modify for recurive mget
 *
 * Revision 2.1  1995/02/04  09:02:53  orel
 * add rcsid
 *
 * Revision 2.1  1995/02/04  09:02:53  orel
 * add rcsid
 *

*/
/*
		      Library for ftpd clients.(libftp)
			Copyright by Oleg Orel
			 All rights reserved.
			
This  library is desined  for  free,  non-commercial  software  creation. 
It is changeable and can be improved. The author would greatly appreciate 
any  advises, new  components  and  patches  of  the  existing  programs.
Commercial  usage is  also  possible  with  participation of it's author.



*/

#include "FtpLibrary.h"

STATUS FtpLogin ( FTP ** con, char * host , char * user , 
		  char * password , char * account)
{
  
  FtpAssert((*con),FtpConnect(con,host));
  FtpAssert((*con),FtpUser((*con),user));
  if (((*con)->errno)==230 )
    return ((*con)->errno);
  if (((*con)->errno)==332)
    {
      if ( account == NULL )
	return EXIT(((*con)),(*con)->errno);
      FtpAssert((*con),FtpAccount( (*con) , account ));
      if ( ((*con)->errno)==230 )
	return (*con)->errno;
    }
  return FtpPassword((*con),password);
}
\End\Of\Shar\
else
  echo "will not over write ./FtpLogin.c"
fi
if `test ! -s ./FtpMessage.c`
then
echo "writing ./FtpMessage.c"
cat > ./FtpMessage.c << '\End\Of\Shar\'
static char rcsid[] = "$Id: FtpMessage.c,v 5.0 1995/12/10 10:28:38 orel Exp $";

/*
	$Log: FtpMessage.c,v $
 * Revision 5.0  1995/12/10  10:28:38  orel
 * LIBFTP Version 5.0 (Distributed revision)
 *
 * Revision 4.1  1995/12/02  11:23:07  orel
 * *** empty log message ***
 *
 * Revision 4.0  1995/07/11  07:00:26  orel
 * Libftp Version 4.0
 *
 * Revision 4.0  1995/07/11  07:00:26  orel
 * Libftp Version 4.0
 *
 * Revision 3.0  1995/03/20  05:26:07  orel
 * *** empty log message ***
 *
 * Revision 3.0  1995/03/20  05:26:07  orel
 * *** empty log message ***
 *
 * Revision 2.4  1995/03/20  05:18:13  orel
 * *** empty log message ***
 *
 * Revision 2.3  1995/02/26  16:46:50  orel
 * *** empty log message ***
 *
 * Revision 2.3  1995/02/26  16:46:50  orel
 * *** empty log message ***
 *
 * Revision 2.2  1995/02/18  15:42:53  orel
 * modify for recurive mget
 *
 * Revision 2.2  1995/02/18  15:42:53  orel
 * modify for recurive mget
 *
 * Revision 2.1  1995/02/04  09:02:53  orel
 * add rcsid
 *
 * Revision 2.1  1995/02/04  09:02:53  orel
 * add rcsid
 *

*/
/*
		      Library for ftpd clients.(libftp)
			Copyright by Oleg Orel
			 All rights reserved.
			
This  library is desined  for  free,  non-commercial  software  creation. 
It is changeable and can be improved. The author would greatly appreciate 
any  advises, new  components  and  patches  of  the  existing  programs.
Commercial  usage is  also  possible  with  participation of it's author.



*/

#include "FtpLibrary.h"


static char * FtpMessageList[1000];

INLINE static char *___gets(char *s, int maxchars, FTP *ftp)
{
  char *p=s;
  int c;

  while (1)
    {
      if ((c = FtpGetc(ftp,FTPCMD(ftp))) == EOF)
	return NULL;
      
      if ( c == '\n' && *(p-1) == '\r' )
	{
	  p--;
	  *p='\0';
	  return s;
	}
      
      if ( (p-s) > maxchars ) return NULL;
      
      *p++=(char)c;
    }
}
    


     
int FtpGetMessage(FTP *con , char * Message )
{
  int i=0,n;
  char tmp[1024];
  
  while(1)
    {
      if (___gets(tmp,sizeof tmp,con)==NULL)
	return EXIT(con,QUIT);
      if (isdigit(tmp[0]) &&
	  isdigit(tmp[1]) &&
	  isdigit(tmp[2]) &&
	  tmp[3]!='-') break;
      if ( con -> debug != NULL )
	(*con->debug)(con,0,tmp);
    }

  strcpy(Message,tmp); 
  FtpInitMessageList();
  FtpMessageList[n=FtpNumber(Message)] =
    ( char * ) malloc ( strlen(Message) + 1);
  strcpy(FtpMessageList[n] , Message );
  if ( con -> debug != NULL )
    (*con->debug)(con,n,Message);

  return n;
}

STATUS FtpSendMessage(FTP *ftp,char * Message )
{
  char *msg=Message;
  
  while (*Message) 
    FtpAssert(ftp,FtpPutc(ftp,FTPCMD(ftp),*Message++));
  
  FtpAssert(ftp,FtpPutc(ftp,FTPCMD(ftp),'\015'));
  FtpAssert(ftp,FtpPutc(ftp,FTPCMD(ftp),'\012'));

  if ( ftp -> debug != NULL )
    (*ftp->debug)(ftp,0,msg);
  return 1;
}

char *FtpMessage(int number)
{
  extern int sys_nerr,errno;
  extern char *sys_errlist[]; 
  
  FtpInitMessageList();
  if ( number == 0 )
    return sys_errlist[errno];
  return (FtpMessageList[abs(number)]==NULL)?
    "":FtpMessageList[abs(number)];
}


STATUS FtpInitMessageList()
{
  int i;
  static u = 0;
  
  if ( u )
    return 1;

  u = 1;

  for (i=0;i<1000;i++)
    FtpMessageList[i]=NULL;

  return 1;
}

int FtpNumber(char *Message)
{
  return (Message[0] - '0') * 100 +
         (Message[1] - '0') * 10  +
	 (Message[2] - '0') ;
}





\End\Of\Shar\
else
  echo "will not over write ./FtpMessage.c"
fi
if `test ! -s ./FtpMove.c`
then
echo "writing ./FtpMove.c"
cat > ./FtpMove.c << '\End\Of\Shar\'
static char rcsid[] = "$Id: FtpMove.c,v 5.0 1995/12/10 10:28:38 orel Exp $";

/*
	$Log: FtpMove.c,v $
 * Revision 5.0  1995/12/10  10:28:38  orel
 * LIBFTP Version 5.0 (Distributed revision)
 *
 * Revision 4.1  1995/12/02  11:23:07  orel
 * *** empty log message ***
 *
 * Revision 4.0  1995/07/11  07:00:26  orel
 * Libftp Version 4.0
 *
 * Revision 4.0  1995/07/11  07:00:26  orel
 * Libftp Version 4.0
 *
 * Revision 3.0  1995/03/20  05:26:07  orel
 * *** empty log message ***
 *
 * Revision 3.0  1995/03/20  05:26:07  orel
 * *** empty log message ***
 *
 * Revision 1.5  1995/03/20  05:18:13  orel
 * *** empty log message ***
 *
 * Revision 1.4  1995/02/26  16:46:50  orel
 * *** empty log message ***
 *
 * Revision 1.4  1995/02/26  16:46:50  orel
 * *** empty log message ***
 *
 * Revision 1.3  1995/02/18  15:42:53  orel
 * modify for recurive mget
 *
 * Revision 1.3  1995/02/18  15:42:53  orel
 * modify for recurive mget
 *
 * Revision 1.2  1995/02/04  09:02:53  orel
 * add rcsid
 *
 * Revision 1.2  1995/02/04  09:02:53  orel
 * add rcsid
 *

*/
/*
		      Library for ftpd clients.(libftp)
			Copyright by Oleg Orel
			 All rights reserved.
			
This  library is desined  for  free,  non-commercial  software  creation. 
It is changeable and can be improved. The author would greatly appreciate 
any  advises, new  components  and  patches  of  the  existing  programs.
Commercial  usage is  also  possible  with  participation of it's author.



*/

#include "FtpLibrary.h"

STATUS FtpMove(FTP *con,char * oldname , char * newname )
{
  STATUS i;

  if ((i=FtpCommand(con,"RNFR %s",oldname,200,350,EOF)) > 1 )
    return FtpCommand(con,"RNTO %s",newname,200,250,EOF);
  else
    return i;
}
\End\Of\Shar\
else
  echo "will not over write ./FtpMove.c"
fi
if `test ! -s ./FtpOpenDir.c`
then
echo "writing ./FtpOpenDir.c"
cat > ./FtpOpenDir.c << '\End\Of\Shar\'
static char rcsid[] = "$Id: FtpOpenDir.c,v 5.0 1995/12/10 10:28:38 orel Exp $";

/*
	$Log: FtpOpenDir.c,v $
 * Revision 5.0  1995/12/10  10:28:38  orel
 * LIBFTP Version 5.0 (Distributed revision)
 *
 * Revision 4.1  1995/09/09  09:49:42  orel
 *  Change type String to FtpString for clean conflicting with
 * X11's type string which is pointer to character only.
 * Thanks for MIT for this good name of type.
 *
 * Revision 4.1  1995/09/09  09:49:42  orel
 *  Change type String to FtpString for clean conflicting with
 * X11's type string which is pointer to character only.
 * Thanks for MIT for this good name of type.
 *
 * Revision 4.0  1995/07/11  07:00:26  orel
 * Libftp Version 4.0
 *
 * Revision 3.0  1995/03/20  05:26:07  orel
 * *** empty log message ***
 *
 * Revision 3.0  1995/03/20  05:26:07  orel
 * *** empty log message ***
 *
 * Revision 1.5  1995/03/20  05:18:13  orel
 * *** empty log message ***
 *
 * Revision 1.4  1995/02/26  16:46:50  orel
 * *** empty log message ***
 *
 * Revision 1.4  1995/02/26  16:46:50  orel
 * *** empty log message ***
 *
 * Revision 1.3  1995/02/18  15:42:53  orel
 * modify for recurive mget
 *
 * Revision 1.3  1995/02/18  15:42:53  orel
 * modify for recurive mget
 *
 * Revision 1.2  1995/02/04  09:02:53  orel
 * add rcsid
 *
 * Revision 1.2  1995/02/04  09:02:53  orel
 * add rcsid
 *

*/
/*
		      Library for ftpd clients.(libftp)
			Copyright by Oleg Orel
			 All rights reserved.
			
This  library is desined  for  free,  non-commercial  software  creation. 
It is changeable and can be improved. The author would greatly appreciate 
any  advises, new  components  and  patches  of  the  existing  programs.
Commercial  usage is  also  possible  with  participation of it's author.



*/

#include "FtpLibrary.h"

STATUS FtpOpenDir(FTP * con,char * file)
{
  FtpString command;

  if ( file == NULL || *file == '\0' )
    strcpy(command,"NLST");
  else
    sprintf(command,"NLST %s",file);

  return FtpCommand(con,command,"",120,150,200,EOF);
}
\End\Of\Shar\
else
  echo "will not over write ./FtpOpenDir.c"
fi
if `test ! -s ./FtpPasv.c`
then
echo "writing ./FtpPasv.c"
cat > ./FtpPasv.c << '\End\Of\Shar\'
static char rcsid[] = "$Id: FtpPasv.c,v 5.0 1995/12/10 10:28:38 orel Exp $";

/*
	$Log: FtpPasv.c,v $
 * Revision 5.0  1995/12/10  10:28:38  orel
 * LIBFTP Version 5.0 (Distributed revision)
 *
 * Revision 4.1  1995/09/09  09:49:42  orel
 *  Change type String to FtpString for clean conflicting with
 * X11's type string which is pointer to character only.
 * Thanks for MIT for this good name of type.
 *
 * Revision 4.1  1995/09/09  09:49:42  orel
 *  Change type String to FtpString for clean conflicting with
 * X11's type string which is pointer to character only.
 * Thanks for MIT for this good name of type.
 *
 * Revision 4.0  1995/07/11  07:00:26  orel
 * Libftp Version 4.0
 *
 * Revision 3.1  1995/06/20  15:53:50  orel
 * Porting to AIX
 *
 * Revision 3.0  1995/03/20  05:26:07  orel
 * *** empty log message ***
 *
 * Revision 2.4  1995/03/20  05:18:13  orel
 * *** empty log message ***
 *
 * Revision 2.3  1995/02/26  16:46:50  orel
 * *** empty log message ***
 *
 * Revision 2.3  1995/02/26  16:46:50  orel
 * *** empty log message ***
 *
 * Revision 2.2  1995/02/18  15:42:53  orel
 * modify for recurive mget
 *
 * Revision 2.2  1995/02/18  15:42:53  orel
 * modify for recurive mget
 *
 * Revision 2.1  1995/02/04  09:02:53  orel
 * add rcsid
 *
 * Revision 2.1  1995/02/04  09:02:53  orel
 * add rcsid
 *

*/
/*		      Library for ftpd clients.(libftp)
			Copyright by Oleg Orel
			 All rights reserved.
			
This  library is desined  for  free,  non-commercial  software  creation. 
It is changeable and can be improved. The author would greatly appreciate 
any  advises, new  components  and  patches  of  the  exist
ing  programs.
Commercial  usage is  also  possible  with  participation of it's author.



*/

#include "FtpLibrary.h"


char * FtpPasv (FTP *ftp)
{
  char *msg;
  static FtpString PORT;
  char *p=PORT;
  
  if FtpError(FtpCommand(ftp,"PASV","",227,EOF)) 
    return "";
  
  msg = FtpMessage (227);

  msg+=3;
  
  while (!isdigit(*msg++));  
  msg--;

  while (isdigit(*msg)||*msg==',') *p++=*msg++;
  *p=0;
  
  return PORT;
}


STATUS FtpLink(FTP *ftp1, FTP *ftp2)
{
  
  FtpString PORT;

  strcpy(PORT,FtpPasv(ftp1));

  FtpCommand(ftp2,"PORT %s",PORT,200,EOF);
}

STATUS FtpPassiveTransfer(FTP *ftp1, FTP *ftp2, char *f1, char *f2)
{
  FtpString tmp;
  fd_set fds;

  FtpAssert(ftp1,FtpLink(ftp1,ftp2));


  if (!*f2) f2=f1;

  FtpAssert(ftp2,FtpCommand(ftp2,"STOR %s",f2, 200, 120 , 150 , 125 , 250 , EOF ));
  FtpAssert(ftp1,FtpCommand(ftp1,"RETR %s",f1, 200, 120 , 150 , 125 , 250 , EOF ));
  
  FD_ZERO(&fds);
  
  FD_SET(fileno(FTPCMD(ftp1)),&fds);
  FD_SET(fileno(FTPCMD(ftp2)),&fds);
  
  if (select(getdtablesize(),&fds,0,0,0)<0)
    {
      if (ftp1->error!=NULL)
	return (*(ftp1->error))(ftp1,QUIT,sys_errlist[errno]);
      if (ftp2->error!=NULL)
	return (*(ftp2->error))(ftp1,QUIT,sys_errlist[errno]);
      return QUIT;
    }
  
  if (FD_ISSET(fileno(FTPCMD(ftp1)),&fds))
    {
      FtpGetMessage(ftp1,tmp);
      FtpLog(ftp1->title,tmp);
      FtpGetMessage(ftp2,tmp);
      FtpLog(ftp2->title,tmp);
    }
  else
    {
      FtpGetMessage(ftp2,tmp);
      FtpLog(ftp2->title,tmp);
      FtpGetMessage(ftp1,tmp);
      FtpLog(ftp1->title,tmp);
    }
}





\End\Of\Shar\
else
  echo "will not over write ./FtpPasv.c"
fi
if `test ! -s ./FtpPort.c`
then
echo "writing ./FtpPort.c"
cat > ./FtpPort.c << '\End\Of\Shar\'
static char rcsid[] = "$Id: FtpPort.c,v 5.0 1995/12/10 10:28:38 orel Exp $";

/*
	$Log: FtpPort.c,v $
 * Revision 5.0  1995/12/10  10:28:38  orel
 * LIBFTP Version 5.0 (Distributed revision)
 *
 * Revision 4.1  1995/09/09  09:49:42  orel
 *  Change type String to FtpString for clean conflicting with
 * X11's type string which is pointer to character only.
 * Thanks for MIT for this good name of type.
 *
 * Revision 4.1  1995/09/09  09:49:42  orel
 *  Change type String to FtpString for clean conflicting with
 * X11's type string which is pointer to character only.
 * Thanks for MIT for this good name of type.
 *
 * Revision 4.0  1995/07/11  07:00:26  orel
 * Libftp Version 4.0
 *
 * Revision 3.0  1995/03/20  05:26:07  orel
 * *** empty log message ***
 *
 * Revision 3.0  1995/03/20  05:26:07  orel
 * *** empty log message ***
 *
 * Revision 1.5  1995/03/20  05:18:13  orel
 * *** empty log message ***
 *
 * Revision 1.4  1995/02/26  16:46:50  orel
 * *** empty log message ***
 *
 * Revision 1.4  1995/02/26  16:46:50  orel
 * *** empty log message ***
 *
 * Revision 1.3  1995/02/18  15:42:53  orel
 * modify for recurive mget
 *
 * Revision 1.3  1995/02/18  15:42:53  orel
 * modify for recurive mget
 *
 * Revision 1.2  1995/02/04  09:02:53  orel
 * add rcsid
 *
 * Revision 1.2  1995/02/04  09:02:53  orel
 * add rcsid
 *

*/
/*
		      Library for ftpd clients.(libftp)
			Copyright by Oleg Orel
			 All rights reserved.
			
This  library is desined  for  free,  non-commercial  software  creation. 
It is changeable and can be improved. The author would greatly appreciate 
any  advises, new  components  and  patches  of  the  existing  programs.
Commercial  usage is  also  possible  with  participation of it's author.



*/

#include "FtpLibrary.h"

STATUS FtpPort(FTP *con,int a,int b,int c,int d,int e,int f)
{
  FtpString cmd;
  int i;

  sprintf(cmd,"PORT %d,%d,%d,%d,%d,%d",a,b,c,d,e,f);
  if ( FtpSendMessage(con,cmd) == QUIT)
    return QUIT;
  if ( (i=FtpGetMessage(con,cmd)) == QUIT)
    return QUIT;
  
  if ( ! FtpGood ( i , 200 , EOF ))
    return EXIT(con,-i);

  return EXIT(con,i);
}
\End\Of\Shar\
else
  echo "will not over write ./FtpPort.c"
fi
if `test ! -s ./FtpPwd.c`
then
echo "writing ./FtpPwd.c"
cat > ./FtpPwd.c << '\End\Of\Shar\'
static char rcsid[] = "$Id: FtpPwd.c,v 5.0 1995/12/10 10:28:38 orel Exp $";

/*
	$Log: FtpPwd.c,v $
 * Revision 5.0  1995/12/10  10:28:38  orel
 * LIBFTP Version 5.0 (Distributed revision)
 *
 * Revision 4.1  1995/09/09  09:49:42  orel
 *  Change type String to FtpString for clean conflicting with
 * X11's type string which is pointer to character only.
 * Thanks for MIT for this good name of type.
 *
 * Revision 4.1  1995/09/09  09:49:42  orel
 *  Change type String to FtpString for clean conflicting with
 * X11's type string which is pointer to character only.
 * Thanks for MIT for this good name of type.
 *
 * Revision 4.0  1995/07/11  07:00:26  orel
 * Libftp Version 4.0
 *
 * Revision 3.0  1995/03/20  05:26:07  orel
 * *** empty log message ***
 *
 * Revision 3.0  1995/03/20  05:26:07  orel
 * *** empty log message ***
 *
 * Revision 1.5  1995/03/05  15:02:26  orel
 * /
 *
 * Revision 1.5  1995/03/05  15:02:26  orel
 * /
 *
 * Revision 1.4  1995/02/26  16:46:50  orel
 * *** empty log message ***
 *
 * Revision 1.3  1995/02/18  15:42:53  orel
 * modify for recurive mget
 *
 * Revision 1.3  1995/02/18  15:42:53  orel
 * modify for recurive mget
 *
 * Revision 1.2  1995/02/04  09:02:53  orel
 * add rcsid
 *
 * Revision 1.2  1995/02/04  09:02:53  orel
 * add rcsid
 *

*/
/*
		      Library for ftpd clients.(libftp)
			Copyright by Oleg Orel
			 All rights reserved.
			
This  library is desined  for  free,  non-commercial  software  creation. 
It is changeable and can be improved. The author would greatly appreciate 
any  advises, new  components  and  patches  of  the  existing  programs.
Commercial  usage is  also  possible  with  participation of it's author.



*/

#include "FtpLibrary.h"

char * FtpPwd(FTP * con)
{
  FtpString tmp,tmp1;
  int i;
  
  if ( FtpSendMessage(con,"PWD") == QUIT )
    return (char *) EXIT(con,QUIT);
  if ( (i=FtpGetMessage(con,tmp)) == QUIT )
    return (char *) EXIT(con,QUIT);
  
  if ( i != 257 )
    return (char *) EXIT(con,-i);

  strcpy(tmp1,word(tmp,2));
  if (*tmp1=='"')
    {
      strcpy(tmp,tmp1+1);
      strncpy(tmp1,tmp,strlen(tmp)-1);
    }
  con -> errno = i;
  return tmp1;
}
\End\Of\Shar\
else
  echo "will not over write ./FtpPwd.c"
fi
if `test ! -s ./FtpRetr.c`
then
echo "writing ./FtpRetr.c"
cat > ./FtpRetr.c << '\End\Of\Shar\'
static char rcsid[] = "$Id: FtpRetr.c,v 5.0 1995/12/10 10:28:38 orel Exp $";

/*
	$Log: FtpRetr.c,v $
 * Revision 5.0  1995/12/10  10:28:38  orel
 * LIBFTP Version 5.0 (Distributed revision)
 *
 * Revision 4.1  1995/12/02  11:23:07  orel
 * *** empty log message ***
 *
 * Revision 4.0  1995/07/11  07:00:26  orel
 * Libftp Version 4.0
 *
 * Revision 4.0  1995/07/11  07:00:26  orel
 * Libftp Version 4.0
 *
 * Revision 3.0  1995/03/20  05:26:07  orel
 * *** empty log message ***
 *
 * Revision 3.0  1995/03/20  05:26:07  orel
 * *** empty log message ***
 *
 * Revision 2.4  1995/03/20  05:18:13  orel
 * *** empty log message ***
 *
 * Revision 2.3  1995/02/26  16:46:50  orel
 * *** empty log message ***
 *
 * Revision 2.3  1995/02/26  16:46:50  orel
 * *** empty log message ***
 *
 * Revision 2.2  1995/02/18  15:42:53  orel
 * modify for recurive mget
 *
 * Revision 2.2  1995/02/18  15:42:53  orel
 * modify for recurive mget
 *
 * Revision 2.1  1995/02/04  09:02:53  orel
 * add rcsid
 *
 * Revision 2.1  1995/02/04  09:02:53  orel
 * add rcsid
 *

*/
/*
		      Library for ftpd clients.(libftp)
			Copyright by Oleg Orel
			 All rights reserved.
			
This  library is desined  for  free,  non-commercial  software  creation. 
It is changeable and can be improved. The author would greatly appreciate 
any  advises, new  components  and  patches  of  the  existing  programs.
Commercial  usage is  also  possible  with  participation of it's author.



*/

#include "FtpLibrary.h"

STATUS FtpRetr (FTP * con , char * command ,
		       char *in , char * out)
{
  FILE *o;
  int c;
  struct stat st;
  char buffer[FTPBUFSIZ],buffer2[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->errno);
      
      con -> seek = 0;
      fclose(o);
      
      if ( FtpError(FtpData(con,command,in,"r")) )
	{
	  return EXIT(con,con->errno);
	}
      
      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);
}












\End\Of\Shar\
else
  echo "will not over write ./FtpRetr.c"
fi
if `test ! -s ./FtpSize.c`
then
echo "writing ./FtpSize.c"
cat > ./FtpSize.c << '\End\Of\Shar\'
static char rcsid[] = "$Id: FtpSize.c,v 5.0 1995/12/10 10:28:38 orel Exp $";

/*
	$Log: FtpSize.c,v $
 * Revision 5.0  1995/12/10  10:28:38  orel
 * LIBFTP Version 5.0 (Distributed revision)
 *
 * Revision 4.1  1995/09/09  09:49:42  orel
 *  Change type String to FtpString for clean conflicting with
 * X11's type string which is pointer to character only.
 * Thanks for MIT for this good name of type.
 *
 * Revision 4.1  1995/09/09  09:49:42  orel
 *  Change type String to FtpString for clean conflicting with
 * X11's type string which is pointer to character only.
 * Thanks for MIT for this good name of type.
 *
 * Revision 4.0  1995/07/11  07:00:26  orel
 * Libftp Version 4.0
 *
 * Revision 3.0  1995/03/20  05:26:07  orel
 * *** empty log message ***
 *
 * Revision 3.0  1995/03/20  05:26:07  orel
 * *** empty log message ***
 *
 * Revision 2.4  1995/03/20  05:18:13  orel
 * *** empty log message ***
 *
 * Revision 2.3  1995/02/26  16:46:50  orel
 * *** empty log message ***
 *
 * Revision 2.3  1995/02/26  16:46:50  orel
 * *** empty log message ***
 *
 * Revision 2.2  1995/02/18  15:42:53  orel
 * modify for recurive mget
 *
 * Revision 2.2  1995/02/18  15:42:53  orel
 * modify for recurive mget
 *
 * Revision 2.1  1995/02/04  09:02:53  orel
 * add rcsid
 *
 * Revision 2.1  1995/02/04  09:02:53  orel
 * add rcsid
 *

*/
/*
		      Library for ftpd clients.(libftp)
			Copyright by Oleg Orel
			 All rights reserved.
			
This  library is desined  for  free,  non-commercial  software  creation. 
It is changeable and can be improved. The author would greatly appreciate 
any  advises, new  components  and  patches  of  the  existing  programs.
Commercial  usage is  also  possible  with  participation of it's author.



*/

#include "FtpLibrary.h"

int FtpSize(FTP * con, char *filename)
{
  FtpString tmp;
  int i,size;

  strcpy(tmp,"SIZE ");
  strcat(tmp,filename);
  
  if ( FtpSendMessage(con,tmp) == QUIT )
    return EXIT(con,QUIT);
  if ( (i=FtpGetMessage(con,tmp)) == QUIT )
    return EXIT(con,QUIT);
  
  if ( i != 213 )
    return con -> errno = (-i);

  sscanf(tmp,"%*d %d",&size);
  return size;
}
\End\Of\Shar\
else
  echo "will not over write ./FtpSize.c"
fi
if `test ! -s ./FtpStat.c`
then
echo "writing ./FtpStat.c"
cat > ./FtpStat.c << '\End\Of\Shar\'
static char rcsid[] = "$Id: FtpStat.c,v 5.0 1995/12/10 10:28:38 orel Exp $";

/*
	$Log: FtpStat.c,v $
 * Revision 5.0  1995/12/10  10:28:38  orel
 * LIBFTP Version 5.0 (Distributed revision)
 *
 * Revision 4.1  1995/09/09  09:49:42  orel
 *  Change type String to FtpString for clean conflicting with
 * X11's type string which is pointer to character only.
 * Thanks for MIT for this good name of type.
 *
 * Revision 4.1  1995/09/09  09:49:42  orel
 *  Change type String to FtpString for clean conflicting with
 * X11's type string which is pointer to character only.
 * Thanks for MIT for this good name of type.
 *
 * Revision 4.0  1995/07/11  07:00:26  orel
 * Libftp Version 4.0
 *
 * Revision 3.1  1995/06/20  15:53:50  orel
 * Porting to AIX
 *
 * Revision 3.0  1995/03/20  05:26:07  orel
 * *** empty log message ***
 *
 * Revision 1.5  1995/03/14  10:47:44  orel
 * add UNKNOWN system type
 *
 * Revision 1.5  1995/03/14  10:47:44  orel
 * add UNKNOWN system type
 *
 * Revision 1.4  1995/03/05  15:02:26  orel
 * /
 *
 * Revision 1.3  1995/02/26  16:46:50  orel
 * *** empty log message ***
 *
 * Revision 1.2  1995/02/18  15:45:05  orel
 * *** empty log message ***
 *
 * Revision 1.1  1995/02/18  15:42:53  orel
 * Initial revision

*/
/*
		      Library for ftpd clients.(libftp)
			Copyright by Oleg Orel
			 All rights reserved.
			
This  library is desined  for  free,  non-commercial  software  creation. 
It is changeable and can be improved. The author would greatly appreciate 
any  advises, new  components  and  patches  of  the  existing  programs.
Commercial  usage is  also  possible  with  participation of it's author.



*/

static char * months[] = { "Jan", "Feb" , "Mar", "Apr", "May", "Jun", "Jul",
			     "Aug", "Sep",  "Oct", "Nov", "Dec"};

#include "FtpLibrary.h"
#include <sys/stat.h>
#include <pwd.h>

static unix_parse(char *,FTP_STAT*); 
static vms_parse(char *,FTP_STAT*, FILE*); 
static vms_axp_parse(char *,FTP_STAT*); 
static msdos_parse(char *,FTP_STAT*);

STATUS FtpStat(FTP *ftp, char *patern, FTP_STAT **first)
{
  FtpString tmp,syst;
  register FILE *in;
  register FTP_STAT *stat=NULL, *prev=NULL;
  register int status,sys_unix,sys_vms,sys_msdos;
  
  *first = NULL;
  strcpy(syst,FtpSyst(ftp));

  sys_unix = !strcmp(syst,"UNIX") || !strcmp(syst,"UNKNOWN");
  sys_vms  = !strcmp(syst,"VMS");
  sys_msdos  = !strcmp(syst,"MSDOS");

  sprintf(tmp,"/tmp/%s.XXXXXX",getpwuid(getuid())->pw_name);
  mktemp(tmp);

  if (*patern==0)
    FtpRetr(ftp,"LIST","",tmp);
  else
    FtpRetr(ftp,sys_unix?"LIST -d %s":"LIST %s",patern,tmp);
  
  if ( (in=fopen(tmp,"r")) == NULL)
    return EXIT(ftp,LQUIT);

  
  while(1)
    {

      if (fgets(tmp,sizeof tmp,in)==NULL)
	break;
      
      if ( stat == NULL )
	{
	  *first = stat = (FTP_STAT *) malloc(sizeof(FTP_STAT));
	  bzero(stat,sizeof(FTP_STAT));
	}
      
      if (  ( sys_unix && unix_parse(tmp,stat))
	  ||( sys_vms  && (vms_parse(tmp,stat,in)||vms_axp_parse(tmp,stat)))
	  ||( sys_msdos && msdos_parse(tmp,stat)))
	  {
	  stat -> next = (FTP_STAT *) malloc(sizeof(FTP_STAT));
	  prev = stat;
	  stat = stat -> next;
	}
    }

  if (prev!=NULL)
    free(prev->next),
    prev->next=NULL;
  
  fclose(in);

  return 0;
}

static unix_parse(char *str, FTP_STAT *stat )
{
  FtpString tmp;
  register int column=1;
  register int i;
  
  if (*word(str,8)=='\0') return 0; /* Isn't file description */
  
  strcpy(tmp,word(str,column++));

  if (strlen(tmp)!=10) return 0;

  stat->type = tmp[0];

  stat->mode =
	(( tmp[1] == 'r' ) ? S_IRUSR : 0)  |
	(( tmp[2] == 'w' ) ? S_IWUSR : 0)  |
	(( tmp[3] == 'x' ) ? S_IXUSR : 0)  |
	(( tmp[4] == 'r' ) ? S_IRGRP : 0)  |
	(( tmp[5] == 'w' ) ? S_IWGRP : 0)  |
	(( tmp[6] == 'x' ) ? S_IXGRP : 0)  |
	(( tmp[7] == 'r' ) ? S_IROTH : 0)  |
	(( tmp[8] == 'w' ) ? S_IWOTH : 0)  |
	(( tmp[9] == 'x' ) ? S_IXOTH : 0);

  
  stat -> inodes = atoi ( word(str,column++));
  
  strcpy ( stat -> user , word ( str, column ++ ));
  
  if (*word(str,9)=='\0')
    stat -> group[0] = 0;
  else
    strcpy ( stat -> group , word ( str, column ++ ));
  
  stat -> size = atoi ( word(str,column++));


  strcpy(tmp,word(str,column++));
  
  stat->month = -1;
  for (i=0;i<12;i++)
    if (!strncasecmp(months[i],tmp,3))
      {
	stat->month=i;
	break;
      }

  
  stat -> day = atoi ( word(str,column++));

  strcpy(stat->time,word(str,column++));
      
  strcpy(stat->name,word(str,column++));

  if ( stat->type == 'l' &&  !strcmp(word(str,column++),"->") )
    strcpy(stat->link,word(str,column++));
  
}

static vms_parse(char *str, FTP_STAT *stat, FILE *in)
{
  FtpString tmp;
  register char *p;
  register int i;

  strcpy(tmp,word(str,1));
  
  if (*word(str,2)==0 && ((char*)strchr(tmp,'.')!=NULL && 
     	((char*)strchr(tmp,';'))!=NULL)
      && fgets(tmp,sizeof tmp,in)!=NULL)
    *(char *)strchr(str,10)=0,
    strcat(str,tmp);
  
  
  if (*word(str,5) != '[' && *word(str,6)!='(' ) return 0;

  strcpy(stat -> name , word(str,1));
  stat -> size = atoi(word(str,2));

  strcpy(tmp,word(str,5));


  if (strchr(tmp+1,',')==NULL)
    {
      strcpy(stat->user,tmp+1);
      *(char *)strchr(stat->user,']')='\0';
      stat->group[0]=0;
    }
  else
    {
      strcpy(stat->group,tmp+1);
      *(char *)strchr(stat->group,',')='\0';
      strcpy(stat->user,(char *)strchr(tmp,',')+1);
      *(char *)strchr(stat->user,']')='\0';
    }
  
  for (p=stat->name;*p;p++) *p=tolower(*p);
  
  if ( (char*)strstr(stat->name,".dir;") != NULL)
    {
      *(char *)strchr(stat->name,'.')=0;
      stat->type='d';
    }
  else
    {
      *(char *)strchr(stat->name,';')=0;
      stat->type = '-';
    }

  stat -> day = atoi(word(str,3));

  strcpy(tmp,(char *)strchr(word(str,3),'-')+1);
  tmp[3]=0;

  stat->month = -1;

  for (i=0;i<12;i++)
    if (!strncasecmp(months[i],tmp,3))
      {
	stat->month=i;
	break;
      }

  strcpy(stat->time,word(str,4));

  strcpy(tmp,word(str,6));


  for(p=tmp;*p!=',';p++);
  p++;

  stat->mode=0;
  
  if (*p=='R') { stat -> mode |= S_IRUSR; p++;}
  if (*p=='W') { stat -> mode |= S_IWUSR; p++;}
  if (*p=='E') { stat -> mode |= S_IXUSR; p++;}
  if (*p=='D') { p++;}
  p++;
  
  if (*p=='R') { stat -> mode |= S_IRGRP; p++;}
  if (*p=='W') { stat -> mode |= S_IWGRP; p++;}
  if (*p=='E') { stat -> mode |= S_IXGRP; p++;}
  if (*p=='D') { p++;}
  p++;
  
  if (*p=='R') { stat -> mode |= S_IROTH; p++;}
  if (*p=='W') { stat -> mode |= S_IWOTH; p++;}
  if (*p=='E') { stat -> mode |= S_IXOTH; p++;}
  if (*p=='D') { p++;}

  return 1;
}


static vms_axp_parse(char *str, FTP_STAT *stat)
{
  FtpString tmp;
  register char *p;
  register int i;

  if (*word(str,4) != '[' && *word(str,5)!='(' ) return 0;

  strcpy(stat -> name , word(str,1));
  stat -> size = atoi(word(str,2))*512;

  strcpy(tmp,word(str,4));

  strcpy(stat->group,tmp+1);
  *(char *)strchr(stat->group,',')='\0';
  strcpy(stat->user,(char *)strchr(tmp,',')+1);
  *(char *)strchr(stat->user,']')='\0';
  
  for (p=stat->name;*p;p++) *p=tolower(*p);
  
  if ( (char*)strstr(stat->name,".dir;") != NULL)
    {
      *(char *)strchr(stat->name,'.')=0;
      stat->type='d';
    }
  else
    {
      *(char *)strchr(stat->name,';')='.';
      stat->type = '-';
    }

  stat -> day = atoi(word(str,3));

  strcpy(tmp,(char *)strchr(word(str,3),'-')+1);
  tmp[3]=0;

  stat->month = -1;

  for (i=0;i<12;i++)
    if (!strncasecmp(months[i],tmp,3))
      {
	stat->month=i;
	break;
      }

  strcpy(tmp,word(str,5));
  for(p=tmp;*p!=',';p++);
  p++;

  stat->mode=0;
  
  if (*p=='R') { stat -> mode |= S_IRUSR; p++;}
  if (*p=='W') { stat -> mode |= S_IWUSR; p++;}
  if (*p=='E') { stat -> mode |= S_IXUSR; p++;}
  if (*p=='D') { p++;}
  p++;
  
  if (*p=='R') { stat -> mode |= S_IRGRP; p++;}
  if (*p=='W') { stat -> mode |= S_IWGRP; p++;}
  if (*p=='E') { stat -> mode |= S_IXGRP; p++;}
  if (*p=='D') { p++;}
  p++;
  
  if (*p=='R') { stat -> mode |= S_IROTH; p++;}
  if (*p=='W') { stat -> mode |= S_IWOTH; p++;}
  if (*p=='E') { stat -> mode |= S_IXOTH; p++;}
  if (*p=='D') { p++;}

  return 1;
}

static msdos_parse(char *str, FTP_STAT *stat)
{
  FtpString tmp;
  register char *p;
  
  if (*word(str,5) != 0) return 0;

  strcpy(stat -> name , word(str,1));

  for (p=stat->name;*p;*p++) *p=tolower(*p);

  stat ->mode = 0644;
  
  if (!strcmp(stat->name,".")||!strcmp(stat->name,"..")) return 0;
  
  strcpy(tmp,word(str,2));

  if (!strcasecmp(tmp,"<dir>"))
    {
      stat ->type = 'd';
      stat ->mode |= S_IXUSR;
    }
  else
    {
      stat -> size = atoi(tmp);
      stat -> type = '-';
    }

  strcpy(tmp,word(str,3));
  stat -> month = atoi(tmp);
  stat -> day = atoi((char*)strchr(tmp,'-')+1);

  strcpy(stat->time,word(str,4));
  return 1;
}


      
      
STATUS FtpStatFree(FTP_STAT *stat)
{
  FTP_STAT *next;
  
  while ( stat != NULL )
    {
      next = stat -> next;
      free(stat);
      stat = next;
    }
}

      
      
	
      
  
  
	 
\End\Of\Shar\
else
  echo "will not over write ./FtpStat.c"
fi
echo "Finished archive 7 of 8"
exit



