Article 12652 of alt.sources:
Newsgroups: alt.sources
Path: nntpd.lkg.dec.com!pa.dec.com!news1.digital.com!nntp-hub2.barrnet.net!nntp-sc.barrnet.net!ratatosk.yggdrasil.com!news.duke.edu!news.mathworks.com!tank.news.pipex.net!pipex!oleane!jussieu.fr!univ-lyon1.fr!swidir.switch.ch!CERN.ch!orel
From: orel@lpuds.oea.ihep.su (Oleg Orel)
Subject: libftp & uftp version 4.0 (Part 1)
X-Nntp-Posting-Host: dxunk1.cern.ch
Message-ID: <DBxCFn.241@news.cern.ch>
Sender: news@news.cern.ch (USENET News System)
Organization: CERN European Lab for Particle Physics
X-Newsreader: TIN [version 1.2 PL0]
Date: Tue, 18 Jul 1995 18:23:46 GMT
Lines: 2194

#!/bin/sh
# to extract, remove the header and type "sh filename"
if `test ! -d ./utils`
then
  mkdir ./utils
  echo "mkdir ./utils"
fi
if `test ! -s ./utils/uftp_tab.c`
then
echo "writing ./utils/uftp_tab.c"
cat > ./utils/uftp_tab.c << '\End\Of\Shar\'
#include <uftp.h>

TOKEN *root = NULL;
     

TOKEN *get_pointer(TOKEN*,char*);


TOKEN *new_token()
{
  TOKEN *n=(TOKEN *)malloc(sizeof(TOKEN));

  bzero(n,sizeof(TOKEN));

  return n;
}

	      
	  


load_key(char *s)
{
  TOKEN *cur=root,*prev=NULL;
  char *cw;
  int i;
  
  for (i=1; (*(cw=word(s,i))) != '\0'; i++)
    {
      if (cur==NULL)
	{
	  cur=new_token();

	  if (root==NULL) root=cur;
	  
	  if (prev!=NULL) prev->shift=cur;
	  
	  strcpy(cur->word,cw);
	  prev=cur;
	  cur=cur->shift;
	}
      else
	{
	  while ( strcmp(cur->word,cw) !=0 && cur->next != NULL &&
		  cur->word[0]!=0 )
	    cur=cur->next;

	  if (strcmp(cur->word,cw)==0 || cur->word[0]==0)
	    {
	      strcpy(cur->word,cw);
	      prev=cur;
	      cur=cur->shift;
	      continue; /* Take next word from string */
	    }

	  cur->next=new_token();
	  cur=cur->next;
	  strcpy(cur->word,cw);
	  prev=cur;
	  cur=cur->shift;
	  
	}
    }
}

load_link(char *s1,char *s2)
{
  TOKEN *t1,*t2;

  load_key(s1);
  load_key(s2);
  
  t1=get_pointer(root,s1);
  t2=get_pointer(root,s2);

  if (t1->shift==NULL) t1->shift=new_token();
  if (t2->shift!=NULL) free(t2->shift);
  t2->shift=t1->shift;
}

compctl_hook(char *buf, int plen, int *loc)
{
  TOKEN *cur=root;
  int i,ii,lc;
  TOKEN *nw;
  LIST *list=NULL;
  char *cw,*p;
  
  for (i=1;/**/;i++)
    {
      String r={0};
      
      cw=word(buf,i);
      
      if ((nw=get_pointer(cur,cw))!=NULL &&
	  (*word(buf,i+1)!=0 || buf[strlen(buf)-1]==' '))
	{
	  cur=nw->shift;
	  continue;
	}

      if (*word(buf,i+1)!=0)
	return;
      
      for (;cur!=NULL;cur=cur->next)
	if (strncmp(cur->word,cw,strlen(cw))==0)
	  list_add(&list,cur->word);

      lc = list_count(&list);
      
      if (lc==0)
	return;


      if (lc==1)
	{
	  for (ii=1;ii<i;ii++) strcpy(r,makestr(r,word(buf,ii),NULL));
	  strcpy(r,makestr(r,list->item,NULL));

	  for (ii=i+1;*(p=word(buf,ii))!=0;ii++)
	    strcpy(r,makestr(r,word(buf,ii),NULL));

	  strcpy(buf,r);
	  strcat(buf," ");
	  break;
	}
      
      if (*(char*)word(buf,i+1)!=0)
	{
	  cur=nw->shift;
	  continue;
	}
      

      printlist(&list);

      for (ii=1;ii<i;ii++) strcpy(r,makestr(r,word(buf,ii),NULL));

      strcpy(buf,makestr(r,p=common_space(list,cw),NULL));

      if (*p==0 && *cw==0 ) strcat(buf," ");
  
      break;
    }

  *loc=strlen(buf);
  
  gl_redraw_r();
  return -2;

}

print_ctl(char *msg1, TOKEN *t)
{
  String tmp;

  if (t==NULL) t=root;

  for (;t!=NULL;t=t->next)
    {
      sprintf(tmp,"%s %s",msg1,t->word);
      
      if (t->shift!=0)
	print_ctl(tmp,t->shift);
      else
	puts(tmp);
    }
}



TOKEN *get_pointer(TOKEN *cur,char *cw)
{
  while (cur!=NULL)
    {
      if (strcmp(cur->word,cw)==0) return cur;
      cur=cur->next;
    }
  return NULL;
}

char *common_space(LIST *valid, char *item)
{
  LIST *new=NULL;
  LIST *t;
  int i,item_len=strlen(item);
  static String result;

  result[0]=0;
  
  for (t=valid;t!=NULL;t=t->next)
    if (!strncmp(item,t->item,item_len))
      list_add(&new,t->item);


  if (new!=NULL)
    for (i=0; ;i++) /* Compared space */
      for(t=new;t!=NULL;t=t->next)
	if (new->item[i]!=t->item[i] || t->item[i]==0 )
	  {
	    if (i>0)
	      {
		strcpy(result,new->item);
		result[i]=0;
	      }
	    list_init(&new);
	    return result;
	  }
  return result;
}
	

printlist(LIST **list)
{
  LIST *t;
  int maxlen,n,ncols;
  String format;

  gl_char_cleanup();
  fputc ('\n',stderr);

  list_sort(list);
  
  for(maxlen=0,t=(*list);t!=NULL;t=t->next)
    if ((n=strlen(t->item))>maxlen) maxlen=n;

  maxlen++;
  
  ncols=winsize/maxlen;

  if (ncols==0) ncols=1;

  sprintf(format,"%%-%ds",maxlen);
  
  for (n=0,t=(*list);t!=NULL;t=t->next,n++,n%=ncols)
    {
      fprintf(stderr,format,t->item);
      if (n+1==ncols) fputc('\n',stderr);
    }

  if (n!=0) fputc('\n',stderr);
  
  gl_char_init();
  gl_redraw_r();
}





\End\Of\Shar\
else
  echo "will not over write ./utils/uftp_tab.c"
fi
if `test ! -s ./utils/uftpcmd.c`
then
echo "writing ./utils/uftpcmd.c"
cat > ./utils/uftpcmd.c << '\End\Of\Shar\'
static char rcsid[] = "$Id: uftpcmd.c,v 4.1 1995/07/17 15:27:59 orel Exp orel $";

/*
	$Log: uftpcmd.c,v $
 * Revision 4.1  1995/07/17  15:27:59  orel
 * Correct bug in help command
 *
 * Revision 4.0  1995/07/11  14:51:08  orel
 * Libftp version 4.0
 *
 * Revision 3.4  1995/07/04  13:37:12  orel
 * chenge compctl function
 *
 * Revision 3.3  1995/07/02  08:39:06  orel
 * remove alias for "user" as "login"
 *
 * Revision 3.2  1995/06/21  09:28:34  orel
 * Porting to AIX and some modification..........
 *
 * Revision 3.1  1995/06/20  15:54:28  orel
 * Porting to AIX
 *
 * Revision 3.0  1995/03/20  05:26:29  orel
 * *** empty log message ***
 *
 * Revision 2.17  1995/03/20  05:17:54  orel
 * *** empty log message ***
 *
 * Revision 2.16  1995/03/20  05:17:31  orel
 * *** empty log message ***
 *
 * Revision 2.16  1995/03/20  05:17:31  orel
 * *** empty log message ***
 *
 * Revision 2.15  1995/03/16  09:38:04  orel
 * modify help
 * add save(s) funcs
 * replace readline to getline
 * etc...
 *
 * Revision 2.14  1995/03/07  16:01:40  orel
 * *** empty log message ***
 *
 * Revision 2.13  1995/03/05  15:02:08  orel
 * *** empty log message ***
 *
 * Revision 2.12  1995/02/26  16:41:21  orel
 * add recursive rm and recursive put
 *
 * Revision 2.11  1995/02/26  12:44:02  orel
 * *** empty log message ***
 *
 * Revision 2.10  1995/02/18  15:42:27  orel
 * add recursive mget
 *
 * Revision 2.9  1995/02/17  12:53:18  orel
 * add parallel put
 *
 * Revision 2.8  1995/02/17  12:47:14  orel
 * add parallel mget
 *
 * Revision 2.7  1995/02/13  16:05:10  orel
 * add setargs call
 *
 * Revision 2.7  1995/02/13  16:05:10  orel
 * add setargs call
 *
 * Revision 2.6  1995/02/13  12:08:16  orel
 * Add save sets
 *
 * Revision 2.5  1995/02/08  17:31:53  orel
 * *** empty log message ***
 *
 * Revision 2.4  1995/02/04  09:12:51  orel
 * rcs id
 *
 * Revision 2.4  1995/02/04  09:12:51  orel
 * rcs id
 *

*/
#include "uftp.h"

jmp_buf connectstack;



Ftp_connect_hook(FTP *ftp,int code, char *msg)
{
  FtpLog(ftp->title,msg);
  longjmp(connectstack,1);
  
}
  

Ftp_connect(ARGS) 
{
  STATUS (*func1)(),(*func2)();

  if (*w2==0)
    {
      w2=getline("Host:");
      *(char *)strchr(w2,'\n')=0;
    }
  
  if (FtpGetHost(w2)==NULL && FtpInit.IO != NULL) 
    {
      char *msg;
      extern int h_errno;
      
      switch(h_errno)
	{
	case HOST_NOT_FOUND:	  msg = "Host unknown";	  break;
	case TRY_AGAIN:	          msg = "Hostname lookup failure";break;
	default:	          msg = "gethostbyname failure";	  
	}
      return (*FtpInit.IO)(LINK,QUIT,msg);
    }
  
  newframe(0);
  
  func1 = FtpInit.error;
  func2 = FtpInit.IO;
  
  if (trymode) 
    {
      FtpSetErrorHandler(&FtpInit,Ftp_connect_hook);
      FtpSetIOHandler(&FtpInit,Ftp_connect_hook);
      setjmp(connectstack);
    }

  list_add(&hosts,w2);
  
  FtpConnect(&LINK,w2);
  strcpy(iftp[frame].host,FtpGetHost(w2)->h_name);
  
  FtpSetErrorHandler(LINK,func1);
  FtpSetErrorHandler(&FtpInit,func1);
  FtpSetIOHandler(LINK,func2);
  FtpSetIOHandler(&FtpInit,func2);
  
  return;
}

Ftp_user(ARGS)
{
  String tmp;
  
  if (*w2==0)
    {
      sprintf(tmp,"login (default %s):",defaultuser);
      w2=getline(tmp);
      *(char *)strchr(w2,'\n')=0;
      if (*w2==0) 
	w2=defaultuser;
    }
  strcpy(iftp[frame].user,w2);
  strcpy(iftp[frame].pass,w3);
  if (FtpUser(LINK,w2)==331) Ftp_pass("",w3,"","","","");
}

Ftp_pass(ARGS)
{
  String tmp;

  if (*w2==0) 
    {
      String pass;
      String host;
  
      gethostname(host, sizeof host);
      strcpy(host,FtpGetHost(host)->h_name);
      sprintf(pass,"%s@%s",getpwuid(getuid())->pw_name,host);
      sprintf(tmp,"Password (default %s):",pass);
      w2=(char*)getpass(tmp);
      if (*w2==0) w2=pass;
    }
  
  strcpy(iftp[frame].pass,w2);
  FtpPassword(LINK,w2);
  strcpy(iftp[frame].pwd,FtpPwd(LINK));
}

Ftp_open(ARGS)
{

  STATUS (*err)();
  
  Ftp_connect("",w2,"","","","");
  Ftp_user("",w3,w4,"","","" );
  if (ifalias("autologin")) execute("autologin");
  if (*w5) 
    Ftp_cd("cd",w5,"","","","");
}

Ftp_reopen(ARGS)
{
  String host,user,pass,pwd;

  strcpy(host,iftp[frame].host);
  strcpy(user,iftp[frame].user);
  strcpy(pass,iftp[frame].pass);
  strcpy(pwd,iftp[frame].pwd);

  Ftp_close(NULLARGS);
  Ftp_open("",host,user,pass,pwd,"");
}

Ftp_ftp(ARGS)
{
  String pass;
  String host;
  
  gethostname(host, sizeof host);
  strcpy(host,FtpGetHost(host)->h_name);
  sprintf(pass,"%s@%s",getpwuid(getuid())->pw_name,host);
  
  Ftp_open("",w2,"anonymous",pass,w3,"");
  return;
}

Ftp_quit(ARGS)
{
  quit(0);
}

Ftp_mput_handler()
{
  log("File(s) or directory not found");
  longjmp(start,1);
}


Ftp_lcd(ARGS)
{
  glob_t gl;
  String tmp;
  
  bzero(&gl,sizeof gl);
 
  glob(w2,GLOB_BRACE|GLOB_TILDE|GLOB_QUOTE,
       Ftp_mput_handler, &gl);
  
  
  if (gl.gl_matchc<1 || chdir(*gl.gl_pathv))
    perror(w2);
  
  fprintf(stderr,"Local directory is \"%s\"\n",getwd(tmp));
}

Ftp_close(ARGS)
{
  register int i;
  
  if (isdigit(*w2)) 
    {
      i=atoi(w2);
    }
  else 
    {
      i=frame;
    }
  
  FtpQuickBye(ftp[i]);
  
  iftp[i].host[0]=0;
  iftp[i].pwd[0]=0;
  ftp[i]=NULL;
  newframe(1);
}


INLINE SetLogicalVar(char arg, int * var, char *msg)
{
  switch(arg)
    {
      
    case 'y':
      
      *var=1;
      break;
      
    case 'n':
      
      *var=0;
      break;
      
    default:
      
      (*var)?(*var=0):(*var=1);
      break;
    }
}

Ftp_set(ARGS)
{
  if (!strcmp("frame",w2))
    return atoi(w3)<NFRAMES?frame=atoi(w3):0;
  
  if (!strcmp("timeout",w2))
    {
      FtpSetTimeout(&FtpInit,atoi(w3));
      if (LINK!=0)
	FtpSetTimeout(LINK,atoi(w3));
      return;
    }
  
  if (!strcmp("sleep",w2))
    {
      sleeptime=atoi(w3);
      return;
    }
  
  if (!strcmp("debug",w2))
    {
      if ( *w3=='y' || *w3==0) 
	{ 
	  if (LINK!=NULL) FtpSetDebugHandler(LINK,FtpDebugDebug);
	  FtpSetDebugHandler(&FtpInit,FtpDebugDebug);
	  return;
	}
      if ( *w3 == 'n')
	{
	  if (LINK!=NULL) FtpSetDebugHandler(LINK,NULL);
	  FtpSetDebugHandler(&FtpInit,NULL);
	  return;
	}
    }
  
  if (!strcmp("bin",w2))
    {
      if ( *w3=='y' || *w3==0) 
	{ 
	  FtpInit.mode='I';
	  return;
	}
      if ( *w3 == 'n')
	{
	  FtpInit.mode='A';
	  return;
	}
    }
  
  if (!strcmp("try",w2))
    return SetLogicalVar(*w3,&trymode,"Try mode");
  if (!strcmp("hash",w2))
    return SetLogicalVar(*w3,&hashmode,"Hash mode");
  if (!strcmp("rest",w2)||!strcmp(w2,"restore"))
    return SetLogicalVar(*w3,&restmode,"Restore mode");
  
  if (!strcmp("prompt",w2))
    {
      strcpy(prompt,w3);
      return;
    }
  
  if (!strcmp("port",w2))
    {
      if ( isdigit(*w3)) 
	return FtpSetPort(&FtpInit,atoi(w3));
      return;
    }

  if (!strcmp("noopinterval",w2)||!strcmp("noop",w2))
    {
      if ( isdigit(*w3)) 
	return noopinterval=(time_t)atoi(w3);
      fputs("Time must be number\n",stderr);
      return;
    }

  if (!strcmp("nooptimeout",w2))
    {
      if ( isdigit(*w3)) 
	return nooptimeout=(time_t)atoi(w3);
      fputs("Time must be number\n",stderr);
      return;
    }

      

  if (!strcmp("user",w2))
    {
      strcpy(defaultuser,w3);
      return;
    }
  
  if (!strcmp("",w2))
    {

      fprintf(stderr,"frime %d\n",frame);
      fprintf(stderr,"timeout %d secs\n",FtpInit.timeout.tv_sec);
      fprintf(stderr,"sleep time %d secs\n",sleeptime);
      fprintf(stderr,"debug %s\n",(FtpInit.debug!=NULL)?"enable":"disable");
      fprintf(stderr,"try mode %s\n",trymode?"enable":"disable");
      fprintf(stderr,"hash mode %s\n",hashmode?"enable":"disable");
      fprintf(stderr,"restore mode %s\n",restmode?"enable":"disable");
      fprintf(stderr,"automatic binary mode %s\n",(FtpInit.mode=='I')?"enable":"disable");
      fprintf(stderr,"prompt  \"%s\"\n",prompt);
      fprintf(stderr,"port %d\n",FtpInit.port);
      fprintf(stderr,"noop interval %d\n",noopinterval);
      fprintf(stderr,"noop timeout %d\n",nooptimeout);
      fprintf(stderr,"Default login name \"%s\"\n",defaultuser);
      fflush(stderr);
      return;
    }
  return puts("arg 2 unknown"); 
  
}

jmp_buf getstack;

Ftp_get_hook(FTP *con,int code, char *msg)
{

  if ( abs(code)==553 || (abs(code)==550 && FtpBadReply550(msg)) ) 
    {
      FtpLog(con->title,msg);
      log("Transfer cancel");
      longjmp(getstack,2);
    }
  
  if ( code == LQUIT )
    {
      log(msg);
      log("Transfer leave after I/O error with local file");
      longjmp(getstack,2);
    }


  
  FtpLog(con->title,msg);
  FtpQuickBye(LINK);
  LINK=NULL;

  log("sleeping......");
  sleep(sleeptime);
  log("try again...");
  
  longjmp(getstack,1);
  
}
  
void Ftp_get_intr(int sig)
{
  signal(SIGINT,intr);
  log("Transfer interupt");
  Ftp_abort();
  longjmp(start,3);
}

Ftp_get(ARGS)
{
  FTP OldInit;
  register int status=0;

  
  OldInit=FtpInit;
  
  if (restmode)
    FtpSetFlag(LINK,FTP_REST);
  else
    FtpClearFlag(LINK,FTP_REST);    
  
  if (trymode)
    {
      FtpSetErrorHandler(LINK,Ftp_get_hook);
      FtpSetIOHandler(LINK,Ftp_get_hook);
      FtpInit= (*LINK);
      FTPCMD(&FtpInit)=FTPCMD(&OldInit);
      FTPDATA(&FtpInit)=FTPDATA(&OldInit);
    }
  
  signal(SIGINT,Ftp_get_intr);
  FtpSetHashHandler(LINK,NULL);
  
  
  if ((status=setjmp(getstack))==2||status==3) 
    goto done;
  
  if ((LINK==NULL)||(LINK->sock==FtpInit.sock))
    {
      FtpLogin(&LINK,iftp[frame].host,iftp[frame].user,
	       iftp[frame].pass,NULL);	  
      FtpChdir(LINK,iftp[frame].pwd);
    }
  
  if ((hashmode && isatty(fileno(stderr)) &&
       strstr(w1,"dir")==NULL && strstr(w1,"ls")==NULL))
    FtpSetHashHandler(LINK,myhash);
  else
    FtpSetHashHandler(LINK,NULL);
    
  myhash(LINK,0);
  
  if (strstr(w1,"get")!=NULL)
    FtpGet(LINK,w2,makefilename(w2,w3));
  if (strstr(w1,"put")!=NULL)
    FtpPut(LINK,w2,makefilename(w2,w3));

  if (strstr(w1,"dir")!=NULL)
    FtpRetr(LINK,(*w2==0)?"LIST":"LIST %s",makestr(w2,w3,w4,w5,w6,NULL),"-");

  if (strstr(w1,"ls")!=NULL)
    FtpRetr(LINK,(*w2==0)?"NLST":"NLST %s",makestr(w2,w3,w4,w5,w6,NULL),"-");
  
  if (LINK->debug!=NULL) log("Transfer complete");
  
  
done:

  if (LINK!=NULL)
    {
      FtpSetHashHandler(LINK,NULL);
      FtpSetErrorHandler(LINK,my_error);
      FtpSetIOHandler(LINK,my_error);
      FtpClearFlag(LINK,FTP_REST);    
    }
  FtpInit=OldInit;
}


Ftp_mget(ARGS)
{
  FTP_STAT *ftpstat, *first;
  String local;
  String pwd;
  
  while (FtpError(FtpStatus(LINK,FtpStat(LINK,w2,&ftpstat))))
    {
      FtpStatFree(ftpstat);
      Ftp_reopen(NULLARGS);
    }
  
  first = ftpstat;

  strcpy(pwd,FtpPwd(LINK));
  strcpy(iftp[frame].pwd,pwd);
  getcwd(local,sizeof local);
  
  while (ftpstat!=NULL)
    {

      if (ftpstat->type=='-')
	{
	  String tmp;
	  struct stat st;

	  if (stat(ftpstat->name,&st)==-1 || st.st_size < ftpstat->size)
	    {
	      
	      sprintf(tmp,"get %s/%s",pwd,ftpstat->name);
	      log(tmp);
	      Ftp_get("get",ftpstat->name,"","","","");
	      chmod(ftpstat->name,ftpstat->mode);
	    }
	}
      
      if (ftpstat->type=='l')
	symlink(ftpstat->link,ftpstat->name);
      
      ftpstat=ftpstat->next;
    }

  ftpstat=first;
  
  while(ftpstat!=NULL)
    {
      if ( ftpstat -> type == 'd' &&
	  ((mkdir(ftpstat->name,ftpstat->mode),chdir(ftpstat->name))!=-1) && 
	  !FtpError(FtpStatus(LINK,FtpChdir(LINK,ftpstat->name))))
	{
	  Ftp_mget(NULLARGS);
	  chdir(local);
	  FtpChdir(LINK,pwd);
	}
      ftpstat=ftpstat->next;
      
    }


  strcpy(iftp[frame].pwd,pwd);

  FtpStatFree(first);
  
}

Ftp_rm(ARGS)
{
  FTP_STAT *ftpstat, *first;
  String local;
  String pwd,tmp;
  
  while (FtpError(FtpStatus(LINK,FtpStat(LINK,w2,&ftpstat))))
    {
      FtpStatFree(ftpstat);
      Ftp_reopen(NULLARGS);
    }
  
  first = ftpstat;

  strcpy(pwd,FtpPwd(LINK));
  strcpy(iftp[frame].pwd,pwd);
  getcwd(local,sizeof local);
  
  for (;ftpstat!=NULL;ftpstat=ftpstat->next)
    if (ftpstat->type!='d')
      FtpStatus(LINK,FtpRm(LINK,ftpstat->name)),
      sprintf(tmp,"rm %s/%s",pwd,ftpstat->name),
      log(tmp);

  for (ftpstat=first;ftpstat!=NULL;ftpstat=ftpstat->next)
    if ( ftpstat -> type == 'd' &&
	!FtpError(FtpStatus(LINK,FtpChdir(LINK,ftpstat->name))))
      {
	Ftp_rm(NULLARGS);
	chdir(local);
	FtpChdir(LINK,pwd);
	FtpStatus(LINK,FtpCommand(LINK,"XRMD %s",ftpstat->name,0,EOF));
      }

  strcpy(iftp[frame].pwd,pwd);
  FtpStatFree(first);
  
}

Ftp_copy(ARGS)
{
  char *p;
  int in,out;
  
  if ( !*w2 || !*w3 ) return puts("Must pass two args");
  
  if ((p=strchr(w2,'!'))!=NULL) 
    {
      *p=0;
      in=atoi(w2);
      w2=p+1;
    }
  else
    in=frame;

  if ((p=strchr(w3,'!'))!=NULL) 
    {
      *p=0;
      out=atoi(w3);
      w3=p+1;
    }
  else
    in=frame;
  
  if (in==out) return puts("Files must been from different frames");
  
  FtpCopy(ftp[in],ftp[out],w2,w3);
}

Ftp_ccopy(ARGS)
{
  char *p;
  int in,out;
  
  if ( !*w2 || !*w3 ) return puts("Must pass two args");
  
  if ((p=strchr(w2,'!'))!=NULL) 
    {
      *p=0;
      in=atoi(w2);
      w2=p+1;
    }
  else
    in=frame;

  if ((p=strchr(w3,'!'))!=NULL) 
    {
      *p=0;
      out=atoi(w3);
      w3=p+1;
    }
  else
    in=frame;
  
  if (in==out) return puts("Files must been from different frames");
  
  FtpPassiveTransfer(ftp[in],ftp[out],w2,w3);
}

Ftp_bin(ARGS)
{
  FtpBinary(LINK);
}

Ftp_ascii(ARGS)
{
  FtpAscii(LINK);
}

Ftp_cd(ARGS)
{
  FtpChdir(LINK,w2);
  strcpy(iftp[frame].pwd,FtpPwd(LINK));
  if (ifalias("autocd")) execute("autocd");
}


Ftp_dup(ARGS)
{ 
  LINKINFO oldinfo;
  FTP oldftp;
  
  oldinfo=iftp[frame];
  oldftp=(*LINK);
  
  newframe(0);
  puts("Make alternative connection...");
  Ftp_open("",oldinfo.host,oldinfo.user,oldinfo.pass,"","");
  if (strcmp(oldinfo.pwd,iftp[frame].pwd)) 
    Ftp_cd("",oldinfo.pwd,"","","","");
  if (LINK->mode!=oldftp.mode)
    FtpType(LINK,oldftp.mode);
  LINK -> timeout = oldftp.timeout;
  LINK -> flags = oldftp.flags;
  FtpSetDebugHandler(LINK,oldftp.debug);
  FtpSetErrorHandler(LINK,oldftp.error);
  FtpSetIOHandler(LINK,oldftp.IO);
  FtpSetHashHandler(LINK,oldftp.hash);
}
  

  
Ftp_bg(ARGS)
{
  String tmp;

  if (fork())
    {
      log(makestr("Backgrounding \"",w2,w3,w4,w5,w6,"\"",NULL));
      return;
    }
  else
    {
      int i=frame;
  
      lastcmd=1;
     
      /* Ignoring keypad */

      alarm (0);
      signal(SIGALRM,SIG_IGN);
      signal(SIGURG,SIG_IGN);
      signal(SIGPIPE,SIG_IGN);
      signal(SIGTSTP,SIG_IGN);
      signal(SIGINT,SIG_IGN);
      signal(SIGQUIT,SIG_IGN);
      signal(SIGCHLD,SIG_IGN);
      signal(SIGIO,SIG_IGN);

      /* Droping output*/

      sprintf(tmp,"/tmp/uftp-%s",getpwuid(getuid())->pw_name);
      mkdir(tmp,0700);
      sprintf(tmp,"/tmp/uftp-%s/logfile.XXXXXX",getpwuid(getuid())->pw_name);
      mktemp(tmp);
      close(0);close(1);close(2);
      open(tmp,O_RDWR|O_TRUNC|O_CREAT,0600);
      dup(0);dup(0);

      if (LINK!=NULL)
	{
	  Ftp_dup(NULLARGS);
	  free(ftp[i]);
	  ftp[i]=NULL;
	}
      
      executev(w2,w3,w4,w5,w6,"");
      exit(0);
    }
}
  

Ftp_list()
{
  register int i;
      
#define _FMT "%-5s %-15s %-10s %-25s %-7s %-4s\n" 
#define  FMT "%-5d %-15s %-10s %-25s %-7d %-4d\n" 
      
  fprintf(stderr,_FMT,"Frame","Host name","User's name","Working directory","Timeout","Port");
  
  for ( i = 0 ; i < NFRAMES ; i++ )
    if (ftp[i]!=NULL)
      fprintf(stderr,FMT,i,iftp[i].host,iftp[i].user,iftp[i].pwd,
	     ftp[i]->timeout.tv_sec,ftp[i]->port);
  fflush(stderr);
  return;
}

Ftp_abort(ARGS)
{
  time_t save;

  if (LINK!=NULL)
    {
      save = LINK ->timeout.tv_sec;
      LINK->timeout.tv_sec = nooptimeout;
      FtpAbort(LINK);
      LINK->timeout.tv_sec = save;
    }
}

Ftp_type(ARGS)
{
  FtpGet(LINK,w2,"*STDOUT*");
}


Ftp_page(ARGS)
{
  register char *pager;
  String out={'|',0};
  
  if ((pager=(char *)getenv("PAGER"))==NULL) 
    pager="more";
 
  strcat(out,pager);
  FtpGet(LINK,w2,out);
}


Ftp_mkdir(ARGS)
{
  FtpMkdir(LINK,w2);
}

Ftp_move(ARGS)
{
  FtpMove(LINK,w2,w3);
}

Ftp_help(ARGS)
{
  LIST *list=NULL;
  register int i,ii,w2_len=strlen(w2);
  
  if ( !*w2 )
    {
      for ( i = 0 ; cmds[i].cmd!=NULL ; i++)
	list_add(&list,cmds[i].cmd);
    }
  
  else

    for ( i = 0 ; cmds[i].cmd!=NULL; i++)
      {
	int len=strlen(cmds[i].cmd);
	if (!strncmp(cmds[i].cmd,w2,MIN(len,w2_len)))
	  list_add(&list,cmds[i].help);
      }
  
  list_sort(&list);
  printlist(&list);
  list_init(&list);
}

Ftp_quote(ARGS)
{
  String new;
  
  new[0]=0;

  strcpy(new,makestr(w2,w3,w4,w5,w6,NULL));
  FtpCommand(LINK,new,"",0,EOF);
}

Ftp_alias(ARGS)
{
  ALIAS *a=firstalias;
  
  if ( *w2==0 )
    {
      while (a!=NULL)
	{
	  fprintf(stderr,"%s=%s\n",a->name,a->str);
	  a=a->next;
	}
      return;
    }


  while (1) 
    {

      if ( a == NULL )
	{ 
	  firstalias = a = (ALIAS *) malloc(sizeof(ALIAS));
	  memset(a,0,sizeof(ALIAS));
	  a -> next = NULL;
	  break;
	}
      
      if (!strcmp(a->name,w2))
	break;
      
      if ( a->next == NULL)
	{
	  a -> next = (ALIAS *) malloc(sizeof(ALIAS));
	  a = a->next;
	  memset(a,0,sizeof(ALIAS));
	  a -> next = NULL;
	  break;
	}
      a=a->next;
    }

  strcpy(a -> name,w2);
  strcpy(a -> str,makestr(w3,w4,w5,w6,NULL));
}

Ftp_mkalias(ARGS)
{
  String new;

  if (!*w2) return puts("Arg must present\n");

  sprintf(new,"open \"%s\" \"%s\" \"%s\" \"%s\"",
	  iftp[frame].host,iftp[frame].user,
	  iftp[frame].pass,iftp[frame].pwd);
  
  Ftp_alias("alias",w2,new,"","","");
}

Ftp_unalias(ARGS)
{
  ALIAS *cur,*prev;

  cur=prev=firstalias;

  while ( cur != NULL )
    {
      if (!strcmp(cur->name,w2))
	{
	  if ( cur == firstalias )
	    {
	      firstalias = cur->next;
	      free(cur);
	      return;
	    }
	  prev -> next = cur -> next;
	  free(cur);
	}
      prev=cur;
      cur=cur->next;
    }
}


Ftp_save_aliases(ARGS)
{
  ALIAS *a=firstalias;
  FILE *out;
  
  if ((out=fopen (getaliasrcname(),"w"))==NULL)
    {
      perror(getaliasrcname());
      return;
    }

  while (a!=NULL)
    {
      fprintf(out,"alias %s '%s'\n",a->name,a->str);
      a=a->next;
    }

  fclose(out);
  
  chmod ( getaliasrcname(), 0600);
}

Ftp_save_sets(ARGS)
{
  FILE *out;
  String newprompt;
  char *p1=prompt, *p2=newprompt;
  
  if ((out=fopen (getsetsrcname(),"w"))==NULL)
    {
      perror(getaliasrcname());
      return;
    }

  fprintf(out,"set timeout %d\n",FtpInit.timeout.tv_sec);
  fprintf(out,"set sleep %d\n",sleeptime);
  fprintf(out,"set debug %c\n",(FtpInit.debug!=NULL)?'y':'n');
  fprintf(out,"set try %c\n",trymode?'y':'n');
  fprintf(out,"set hash %c\n",hashmode?'y':'n');
  fprintf(out,"set rest %c\n",restmode?'y':'n');
  fprintf(out,"set bin %c\n", (FtpInit.mode=='I')?'y':'n');

  while (*p1)
    {
      if (*p1=='>'||*p1=='<') *p2++='\\';
      *p2++ = *p1++;
    }

  *p2=0;
  
  fprintf(out,"set prompt '%s'\n",newprompt);
  
  fprintf(out,"set port %d\n",FtpInit.port);
  fprintf(out,"set noopinterval %d\n",noopinterval);
  fprintf(out,"set nooptimeout %d\n",nooptimeout);
  fprintf(out,"set user '%s'\n",defaultuser);
  
  fclose(out);
  
  chmod ( getsetsrcname(), 0600);
  
}


#define ARCHIE_MAX_TARGETS 20

Ftp_acd(ARGS)
{
  static int targets=0;
  static String what={0};
  static ARCHIE result[ARCHIE_MAX_TARGETS];
  String tmp;
  
  int i, selected_target;

  char *p;

  
  if ( (what[0] == 0 || strcmp(w2,what) != 0) && *w2!=0 )
    {
      if ((targets=FtpArchie(w2,result,ARCHIE_MAX_TARGETS))<1) 
	return puts("Archie failure or target not found");
      strcpy(what,w2);
    }
  
  for (i=0;i<targets;i++)
    fprintf(stderr,"%2d %s:%s\n",i,result[i].host,result[i].file);
  
  if (strcmp(w1,"archie")==0)
    return;
  
  
  p = getline("Your selection? ");
  *(char *)strchr(p,'\n')=0;
  if (*word(p,1)==0) return;
  
  selected_target = atoi(p);


  if (strcmp(w1,"acd")==0 || *(strrchr(result[selected_target].file,'/')+1)=='\0' )
    {
      strcpy(tmp,result[selected_target].file);
      *(char*)strrchr(tmp,'/')=0;
      
      Ftp_ftp("ftp",result[selected_target].host,tmp,"","","");
    }
  else
    {
      Ftp_ftp("ftp",result[selected_target].host,"","","","");
      Ftp_get("get",result[selected_target].file,"","","","");
    }
  
}

Ftp_aaget(ARGS)
{
  ARCHIE result[ARCHIE_MAX_TARGETS];
  int targets;
  int maxsize;
  register int i;
  String pass,host,tmp;
  FTP save;
  
  if (*w2==0)
    {
      printf("%s <filename>\n",w1);
      return;
    }
  
  if ((targets=FtpArchie(w2,result,ARCHIE_MAX_TARGETS))<1) 
    {
      printf("Specified file not found by archie\n");
      return;
    }

  gethostname(host, sizeof host);
  sprintf(pass,"%s@%s",getpwuid(getuid())->pw_name,FtpGetHost(host)->h_name);
  
  for (i=0,maxsize=0;i<targets;i++)
    if (result[i].size>maxsize) maxsize=result[i].size;
  
  for (i=0; ; i++,(i==targets)?i=0:i)
    {
      FTP *ftp;
      
      if (result[i].size<maxsize) continue;

      save=FtpInit;

      FtpSetIOHandler(&FtpInit,NULL);
      FtpSetErrorHandler(&FtpInit,NULL);
      
      sprintf(tmp,"Retrive file %s from %s.....",result[i].file,result[i].host);
      FtpLog("aaget",tmp);

      
      if (FtpError(FtpLogin(&ftp,result[i].host,"anonymous",pass,NULL)) ||
	  FtpError(FtpGet(ftp,result[i].file,strrchr(result[i].file,'/')+1)))
	{
	  FtpQuickBye(ftp);
	  continue;
	}
      FtpQuickBye(ftp);
      break;
    }

  FtpInit=save;
  
}


INLINE char filetype(char *name)
{
  struct stat st;

  if (stat(name,&st)==-1) return '0';
  
  if ( S_IFREG == (st.st_mode & S_IFMT)) return '-';
  if ( S_IFDIR == (st.st_mode & S_IFMT)) return 'd';
  
  return '?';
}

Ftp_mput(ARGS)
{
  glob_t gl;
  char **args;
  int nargs;
  int chmod_status=0;
  String local,pwd;
  String tmp;
  
  glob((*w2==0)?"*":w2,GLOB_BRACE|GLOB_TILDE|GLOB_QUOTE,
       Ftp_mput_handler, &gl);

  nargs=gl.gl_matchc;
  args=gl.gl_pathv;
  
  while(nargs--)
    {
      if (filetype(*args)=='-')
	{
	  struct stat st;

	  getcwd(local,sizeof local);
	  
	  sprintf(tmp,"put %s/%s",local,*args);
	  log(tmp);
	  
	  Ftp_get("put",*args,"","","","");
	  stat(*args,&st);
	  if (chmod_status>=0)
	    chmod_status=FtpStatus(LINK,FtpChmod(LINK,*args,st.st_mode&0777));
	}
      args++;
    }

  nargs=gl.gl_matchc;
  args=gl.gl_pathv;
  
  while(nargs--)
    {
      if (filetype(*args)=='d')
	{
	  getcwd(local,sizeof local);

	  if (chdir(*args)==-1) continue;

	  strcpy(pwd,iftp[frame].pwd);

	  FtpStatus(LINK,FtpMkdir(LINK,*args));
	  
	  if (!FtpError(FtpStatus(LINK,FtpChdir(LINK,*args))))
	    {
	      Ftp_mput(NULLARGS);
	      FtpChdir(LINK,pwd);
	    }

	  chdir(local);
	}
      args++;
    }
}


Ftp_env(ARGS)
{

  if (!strcmp(w1,"setenv")) return setenv(w2,w3);
  if (!strcmp(w1,"unsetenv")) return unsetenv(w2);
  if (!strcmp(w1,"env")) return printenv();
}

Ftp_compctl(ARGS)
{
  if (*w2==0) return print_ctl("compctl",NULL);
  load_key(makestr(w2,w3,w4,w5,w6,NULL));
}


CMDS cmds[]={
  
  "compctl",		Ftp_compctl,      0,
  "compctl command arg1 arg2... - load complition map",

  "connect",		Ftp_connect,      0,
  "connect <hostname> - make new ftp connection",

  "open",		Ftp_open,         0,
  "open <hostname> <user> <pass> <directory> - login to server",
  
  "reopen",		Ftp_reopen,       1,
  "reopen - Open again connection with existing frame information",
  
  "ftp",		Ftp_ftp,          0,
  "ftp <hostname> - anonymously login to server",
  
  "close",		Ftp_close,        1,
  "close - Close connection",
  
  "quit",		Ftp_quit,         0,
  "quit - Exit from uftp",

  
  "exit",		Ftp_quit,         0,
  "exit - Exit from uftp",

  
  "set",		Ftp_set,          0,
"set - Set variables: (Without args print current settings)\n\
       frame <number>    - select another session(frame)\n\
       timeout <secs>    - Set network timeout\n\
       nooptimeout <secs>- Set network timeout with clearing timeout\n\
       noop <secs>       - Set time interval for sending NOOP operator\n\
                           to server for erased delay\n\
       sleep <secs>      - Set pause beetween transfer attempt\n\
       debug <y|n>       - Set debuging ftp's protocol (Default no)\n\
       try <y|n>         - Set retransfer mode with broken network (Default yes)\n\
       hash <y|n>        - Set hashing transfer (Default no)\n\
       restore <y|n>     - Set retransfer mode (reget/reput) (Default yes!!!!)\n\
       bin <y|n>         - Set automatic turn on binary mode (Default no) \n\
       prompt <string>   - Set prompt (See help prompt)\n\
       port <number>     - Set ftpd's port for next sessions\n\
       user <name>       - Set default user name (default you name)",

  "setenv",            Ftp_env,           0,
  "setenv - Set enviroment variable",
	 
  "unsetenv",          Ftp_env,           0,
  "unsetenv - Unset enviroment variable",
	 
  "env",               Ftp_env,           0,
  "env - Print enviroment variables",
	 
	 
  "prompt",               NULL,         0,
  "\
prompt is a string, which may be contains %<char> 
or ^<char> combitanion, which have next interprets:

%H, %h - full and short remote host names
%M, %m - full and short local host names
%u     - remote user's name
%d     - remote current directory
%D     - local current directory
%f     - number of current frame
%p     - the ftp's port number
%t     - timeout 
%T     - current time 
%P     - uftp process id
%%     - character %
^<char>- control character
%^     - character ^
",

  "list",		Ftp_list,         0,
"list - List session's information",

  "user",		Ftp_user,         1,
"user <user> - send user's name",

  "pass",		Ftp_pass,         1,
"pass <pass> - send user's password",

  "bin",		Ftp_bin,          1,
"bin - Set binary mode for current frame",

  "ascii",		Ftp_ascii,        1,
"ascii - Set ASCII mode for current frame",

  "cd",			Ftp_cd,           1,
"cd <directory> - change current remote directory ",

  "acd",		Ftp_acd,          0,
"acd <file_or_directory> - search pointed directory using archie, and setup connection to it",

  "lcd",		Ftp_lcd,          0,
"lcd <directory> - Change local directory",

  "abort",		Ftp_abort,        1,
"abort - abort last operation",

  "mkdir",		Ftp_mkdir,        1,
"mkdir <dirname> - create new directory",

  "rm",		        Ftp_rm,           1,
"rm <filename_spec> - remove file(s)",

  "mv",		        Ftp_move,         1,
"mv <old> <new> - rename file",

  "dir",		Ftp_get,          1,
"dir <argslist> ... - print list of files",

  "ls",		        Ftp_get,          1,
"ls <arglist> ... - print short list of files",

  "get",		Ftp_get,          1,
"get <remote_file> [<local_file>] - receive file from server",

  "mget",		Ftp_mget,         1,
"mget <remote_file(s)> - recursive receive file(s) from server",

  "aget",		Ftp_acd,          0,
"aget <file> - search pointed file using archie, and retrive it",

  "aaget",		Ftp_aaget,        0,
"aaget <file> - search pointed file using archie, and retrive it from anywhere",

  "put",		Ftp_get,          1,
"put <local_file> [<remote_file>] - send server to file",

  "mput",		Ftp_mput,         1,
"mput <local_file(s)>  - recursive send file(s) to server",

  "copy",               Ftp_copy,         1,
"copy [<frame>!]file [<frame>!]file - copy file via client cache",

  "ccopy",               Ftp_ccopy,       1,
"ccopy [<frame>!]file [<frame>!]file - copy file directly beetween servers",

  "cat",		Ftp_type,         1,
"cat <file> - print body of remote file to screen",
  
  "page",		Ftp_page,         1,
"page <file> - print body of remote file to screen via pager",

  "bg",			Ftp_bg,           0,
"bg <any_command> - run command(s) backgroundly (output redirect to file),\n\
You can also add &-char to back of line without \"bg\"",

  "archie",             Ftp_acd,       0,
"archie - Find file using archie service and display to screen",

  "dup",		Ftp_dup,          1,
"dup - Make new analogous frame",

  "quote",              Ftp_quote,        1,
"quote <some_string> - send command directly to server",

  "help",		Ftp_help,         0,
"help <command> - print list of commands or command description",

  "alias",              Ftp_alias,        0,
"\
alias aliasname <list> .... - make new alias, use $X for taking \n\
                  X's argument from command string, and $* for taking\n\
                  all arguments. If $<anything> on alias not present,\n\
                  the arguments appending to end of command string",

  "unalias",            Ftp_unalias,      0,
"unalias <aliasname> - remove alias",

  "mkalias",            Ftp_mkalias,      0,
"mkalias <Alias_name> - make alias for create this frame, use save for saving it to file",

  "savealiases",              Ftp_save_aliases,     0,
  "savealiases - Save aliases to file",

  "savesets",                 Ftp_save_sets,     0,
  "savesets - Save sets to file",

  "etc",               NULL,         0,
  "\
1. In any command you may use constructions <file and >file for\n\
   redirect input output.\n\
\n\
2. All local files files interprets as libftp file(s), \n\
   this support next specification:\n\
\n\
   |string - interprets string as shell command, which must be\n\
   execute and input or output take from/to it.\n\
   \n\
\n\
   *STDIN*, *STDOUT*, *STDERR* - opened streams.\n\
\n\
   anything - local file name.\n\
\n\
3. Command started with '!' passed to shell.\n
\n\
4. If string beetween two \" or \', its interprets as one word.\n\
\n\
5. Any string may be devide to few commands using ';'.",



  NULL

  };







\End\Of\Shar\
else
  echo "will not over write ./utils/uftpcmd.c"
fi
if `test ! -s ./utils/cdefs.h`
then
echo "writing ./utils/cdefs.h"
cat > ./utils/cdefs.h << '\End\Of\Shar\'
/*
 * Copyright (c) 1991, 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * This code is derived from software contributed to Berkeley by
 * Berkeley Software Design, Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by the University of
 *	California, Berkeley and its contributors.
 * 4. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *	@(#)cdefs.h	8.7 (Berkeley) 1/21/94
 */

#ifndef	_CDEFS_H_
#define	_CDEFS_H_

#if defined(__cplusplus)
#define	__BEGIN_DECLS	extern "C" {
#define	__END_DECLS	};
#else
#define	__BEGIN_DECLS
#define	__END_DECLS
#endif

/*
 * The __CONCAT macro is used to concatenate parts of symbol names, e.g.
 * with "#define OLD(foo) __CONCAT(old,foo)", OLD(foo) produces oldfoo.
 * The __CONCAT macro is a bit tricky -- make sure you don't put spaces
 * in between its arguments.  __CONCAT can also concatenate double-quoted
 * strings produced by the __STRING macro, but this only works with ANSI C.
 */
#if defined(__STDC__) || defined(__cplusplus)
#define	__P(protos)	protos		/* full-blown ANSI C */
#define	__CONCAT(x,y)	x ## y
#define	__STRING(x)	#x

#define	__const		const		/* define reserved names to standard */
#define	__signed	signed
#define	__volatile	volatile
#if defined(__cplusplus)
#define	__inline	inline		/* convert to C++ keyword */
#else
#ifndef __GNUC__
#define	__inline			/* delete GCC keyword */
#endif /* !__GNUC__ */
#endif /* !__cplusplus */

#else	/* !(__STDC__ || __cplusplus) */
#define	__P(protos)	()		/* traditional C preprocessor */
#define	__CONCAT(x,y)	x/**/y
#define	__STRING(x)	"x"

#ifndef __GNUC__
#define	__const				/* delete pseudo-ANSI C keywords */
#define	__inline
#define	__signed
#define	__volatile
/*
 * In non-ANSI C environments, new programs will want ANSI-only C keywords
 * deleted from the program and old programs will want them left alone.
 * When using a compiler other than gcc, programs using the ANSI C keywords
 * const, inline etc. as normal identifiers should define -DNO_ANSI_KEYWORDS.
 * When using "gcc -traditional", we assume that this is the intent; if
 * __GNUC__ is defined but __STDC__ is not, we leave the new keywords alone.
 */
#ifndef	NO_ANSI_KEYWORDS
#define	const				/* delete ANSI C keywords */
#define	inline
#define	signed
#define	volatile
#endif
#endif	/* !__GNUC__ */
#endif	/* !(__STDC__ || __cplusplus) */

/*
 * GCC1 and some versions of GCC2 declare dead (non-returning) and
 * pure (no side effects) functions using "volatile" and "const";
 * unfortunately, these then cause warnings under "-ansi -pedantic".
 * GCC2 uses a new, peculiar __attribute__((attrs)) style.  All of
 * these work for GNU C++ (modulo a slight glitch in the C++ grammar
 * in the distribution version of 2.5.5).
 */
#if !defined(__GNUC__) || __GNUC__ < 2 || __GNUC_MINOR__ < 5
#define	__attribute__(x)	/* delete __attribute__ if non-gcc or gcc1 */
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
#define	__dead		__volatile
#define	__pure		__const
#endif
#endif

/* Delete pseudo-keywords wherever they are not available or needed. */
#ifndef __dead
#define	__dead
#define	__pure
#endif

#endif /* !_CDEFS_H_ */
\End\Of\Shar\
else
  echo "will not over write ./utils/cdefs.h"
fi
if `test ! -s ./utils/getline.h`
then
echo "writing ./utils/getline.h"
cat > ./utils/getline.h << '\End\Of\Shar\'
#ifndef GETLINE_H
#define GETLINE_H

/* unix systems can #define POSIX to use termios, otherwise 
 * the bsd or sysv interface will be used 
 */

char           *getline();		/* read a line of input */
void            gl_setwidth();		/* specify width of screen */
void            gl_histadd();		/* adds entries to hist */
void		gl_strwidth();		/* to bind gl_strlen */

extern int 	(*gl_in_hook)();
extern int 	(*gl_out_hook)();
extern int	(*gl_tab_hook)();

#endif /* GETLINE_H */
\End\Of\Shar\
else
  echo "will not over write ./utils/getline.h"
fi
if `test ! -s ./utils/glob.h`
then
echo "writing ./utils/glob.h"
cat > ./utils/glob.h << '\End\Of\Shar\'
/*
 * Copyright (c) 1989, 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * This code is derived from software contributed to Berkeley by
 * Guido van Rossum.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by the University of
 *	California, Berkeley and its contributors.
 * 4. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *	@(#)glob.h	8.1 (Berkeley) 6/2/93
 */

#ifndef _GLOB_H_
#define	_GLOB_H_


#include <cdefs.h>

struct stat;
typedef struct {
	int gl_pathc;		/* Count of total paths so far. */
	int gl_matchc;		/* Count of paths matching pattern. */
	int gl_offs;		/* Reserved at beginning of gl_pathv. */
	int gl_flags;		/* Copy of flags parameter to glob. */
	char **gl_pathv;	/* List of paths matching pattern. */
				/* Copy of errfunc parameter to glob. */
	int (*gl_errfunc) __P((const char *, int));

	/*
	 * Alternate filesystem access methods for glob; replacement
	 * versions of closedir(3), readdir(3), opendir(3), stat(2)
	 * and lstat(2).
	 */
	void (*gl_closedir) __P((void *));
	struct dirent *(*gl_readdir) __P((void *));	
	void *(*gl_opendir) __P((const char *));
	int (*gl_lstat) __P((const char *, struct stat *));
	int (*gl_stat) __P((const char *, struct stat *));
} glob_t;

#define	GLOB_APPEND	0x0001	/* Append to output from previous call. */
#define	GLOB_DOOFFS	0x0002	/* Use gl_offs. */
#define	GLOB_ERR	0x0004	/* Return on error. */
#define	GLOB_MARK	0x0008	/* Append / to matching directories. */
#define	GLOB_NOCHECK	0x0010	/* Return pattern itself if nothing matches. */
#define	GLOB_NOSORT	0x0020	/* Don't sort. */

#define	GLOB_ALTDIRFUNC	0x0040	/* Use alternately specified directory funcs. */
#define	GLOB_BRACE	0x0080	/* Expand braces ala csh. */
#define	GLOB_MAGCHAR	0x0100	/* Pattern had globbing characters. */
#define	GLOB_NOMAGIC	0x0200	/* GLOB_NOCHECK without magic chars (csh). */
#define	GLOB_QUOTE	0x0400	/* Quote special chars with \. */
#define	GLOB_TILDE	0x0800	/* Expand tilde names from the passwd file. */

#define	GLOB_NOSPACE	(-1)	/* Malloc call failed. */
#define	GLOB_ABEND	(-2)	/* Unignored error. */

__BEGIN_DECLS
int	glob __P((const char *, int, int (*)(const char *, int), glob_t *));
void	globfree __P((glob_t *));
__END_DECLS

#endif /* !_GLOB_H_ */
\End\Of\Shar\
else
  echo "will not over write ./utils/glob.h"
fi
if `test ! -s ./utils/list.h`
then
echo "writing ./utils/list.h"
cat > ./utils/list.h << '\End\Of\Shar\'
#ifndef __LIST_H__
#define __LIST_H__
typedef struct _list
{
  char item[1024];
  struct _list *next;
} LIST;


int list_init(LIST**);
int list_add(LIST**,char*);
int list_remove(LIST**,char*);
int list_count(LIST**);
#endif


\End\Of\Shar\
else
  echo "will not over write ./utils/list.h"
fi
if `test ! -s ./utils/uftp.h`
then
echo "writing ./utils/uftp.h"
cat > ./utils/uftp.h << '\End\Of\Shar\'
#include <sys/types.h>
#include <FtpLibrary.h>
#include <strings.h>
#include <setjmp.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/file.h>
#include <arpa/telnet.h>
#include <sys/ioctl.h>
#include <pwd.h>
#include <errno.h>
#include <glob.h>
#include "getline.h"
#include "list.h"

#define SYSTEMRC "/usr/share/etc/uftprc"
#define LINK ftp[frame]
#define NFRAMES 10
#define TIME(proc) settimer(), status = proc , showtimer(), status
#define ARGS char *w1,char *w2,char *w3,char *w4,char *w5,char *w6
#define NULLARGS "","","","","",""
#define log(x) FtpLog("uftp",x)

#ifdef MIN
#undef MIN
#endif

#define MIN(x,y) ((x)<(y)?(x):(y))
typedef struct
{
  String host;
  String user;
  String pass;
  String pwd;
  int lock;
} LINKINFO;

typedef struct
{
  char *cmd;
  int (*func)();
  int need;
  char *help;
} CMDS;

typedef struct _alias
{
  String name,str;
  struct _alias *next;
} ALIAS;

typedef struct _token
{
  String word;
  struct _token *next;
  struct _token *shift;
} TOKEN;



extern ALIAS *firstalias;
extern FTP *ftp[NFRAMES];
extern LINKINFO iftp[NFRAMES];
extern LIST *hosts;
extern int frame;
extern int lastcmd;
extern int trymode;
extern int hashmode;
extern int restmode;
extern int sleeptime;
extern int winsize;
extern time_t noopinterval,nooptimeout;
extern CMDS cmds[];
extern int status;
extern String prompt;
extern String defaultuser;
extern jmp_buf start;

char *word(char *,int);
char *readline(char *);

#ifndef _AIX
char *getpass(char *);
#endif

char *getrcname();
char *getaliasrcname();
char *getsetsrcname();
char *gethostsname();
char *makestr();
char *expandalias(char *str);
char *getprompt();
char *makefilename(char *,char *);
char *getalias(char *);

int tab_hook(char *,int,int*);
int compctl_hook(char *,int,int*);

int setenv(char *, char*);
int unsetenv(char *);
int printenv();
void getwinsz();

void intr(int);
void noop();
int  setargs(char *);

int myhash(FTP *,unsigned int);
STATUS my_error(FTP *, int, char *);









\End\Of\Shar\
else
  echo "will not over write ./utils/uftp.h"
fi
if `test ! -s ./utils/Makefile`
then
echo "writing ./utils/Makefile"
cat > ./utils/Makefile << '\End\Of\Shar\'
# Generated automatically from Makefile.in by configure.

CC=gcc -O0
CO=co

CFLAGS = -g -I. -I.. -L. -L..

ALL=uftp

OBJS=uftp.o uftpcmd.o uftp_tab.o

SRCS=uftp.c uftpcmd.c uftp_tab.c uftp.h list.h list.c env.c getline.c getline.h glob.h cdefs.h glob.c

LIBS=../libftp.a libetc.a

###############################################################################
#
# Basic Rules
#
###############################################################################


all: $(ALL)

uftp:	$(OBJS) ../libftp.a libetc.a
	$(CC) $(CFLAGS) -o uftp $(OBJS) -lftp -letc 

clean: 
	rm -f $(ALL) $(OBJS) libetc.a $(LIBOBJS) *~ core
	
###############################################################################
#
# Depending from main library (libftp)
#
###############################################################################



./libftp.a: $(shell echo ../*.[ch])
	@cd ..;$(MAKE) CFLAGS="$(CFLAGS)" CC="$(CC)" 

###############################################################################
#
# Library with help functions
#
###############################################################################



LIBOBJS= getline.o glob.o env.o list.o

libetc.a: $(LIBOBJS)	
	ar cruv libetc.a  $(LIBOBJS)
	ranlib libetc.a


	

uftp.o: ../libftp.a


$(SRCS):
	$(CO) $@

# DO NOT DELETE THIS LINE -- make depend depends on it.

getline.o: getline.h
glob.o: glob.h cdefs.h
glob.o: cdefs.h
list.o: list.h uftp.h glob.h cdefs.h getline.h
uftp.o: uftp.h glob.h cdefs.h getline.h list.h
uftp.o: glob.h cdefs.h getline.h list.h
uftp_tab.o: uftp.h glob.h cdefs.h getline.h list.h
uftpcmd.o: uftp.h glob.h cdefs.h getline.h list.h
\End\Of\Shar\
else
  echo "will not over write ./utils/Makefile"
fi
echo "Finished archive 1 of 6"
exit


--
``


