/* apccomm_am_tr.c
   Part of "APCComm" 
   Copyright (C) 2000,2001 Ralf Hoffmann
   Contact: ralf.hoffmann@epost.de

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  
*/
/* $Id: apccomm_am_tr.c,v 1.14 2002/06/12 20:16:37 ralf Exp $ */

#include "apccomm_am_tr.h"
#include "apccomm_am.h"
#include "apccomm_am_main.h"

#ifdef GUI
#include "apccomm_gui.h"
#endif

#define DDRA 0xbfd200
#define DDRB 0xbfe301
#define PRA 0xbfd000
#define PRB 0xbfe101
#define ICR 0xbfed01

unsigned char *icr=(unsigned char*)ICR;
unsigned char *prb=(unsigned char*)PRB;
unsigned char *pra=(unsigned char*)PRA;
unsigned char *ddrb=(unsigned char*)DDRB;
unsigned char *ddra=(unsigned char*)DDRA;

int lastvalue;

int getack( void )
{
  unsigned char v;
  v=*pra;
  lastvalue=v&3;
  return ((v&4)==0)?0:1;
}

int getvalue( void )
{
  getack();
  return lastvalue;
}

void setack(int value)
{
  unsigned char v;
  v=*prb;
  if(value==0) v&=0xf;
  else v|=0x10;
  *prb=v;
}

void putnibble(int value)
{
  unsigned char v,nv,ack;
  v=*prb;
  ack=v&0x10;
  nv=value&0xf;
  nv|=ack;
  *prb=nv;
}

void putnibbleack(int value,int ack)
{
  unsigned char v;
  v=value&0xf;
  v|=(ack&0x1)<<4;
  *prb=v;
}

void synchro( void )
{
  int count, pc = 0;
#ifdef GUI
  char buf[11];
  struct Gadget *text;
  
  text = ConnectWindowGadgets[ GD_ct ];
  buf[0] = '\0';
#endif

  setack(1);
  putnibble(0);
  for(count=0;getack()!=0;count++) {
    Delay(1);
#ifdef GUI
    HandleConnectWindowIDCMP();
#endif
    if(count%25==0) {
      pc = ( pc + 1 ) % 10;
#ifdef GUI
      memset( buf, '.', pc );
      buf[pc] = '\0';
      GT_SetGadgetAttrs( text, ConnectWindowWnd, NULL, GTTX_Text, buf, TAG_END );
#else
      if ( ! BE_QUIET ) printf(".");
      fflush(stdout);
#endif
    }
#ifdef GUI
    if ( connect_cancel == 1 ) return;
#endif
  }
  putnibble(1);
  for(count=0;getvalue()!=1;count++) {
    Delay(1);
#ifdef GUI
    HandleConnectWindowIDCMP();
#endif
    if(count%25==0) {
      pc = ( pc + 1 ) % 10;
#ifdef GUI
      memset( buf, '.', pc );
      buf[pc] = '\0';
      GT_SetGadgetAttrs( text, ConnectWindowWnd, NULL, GTTX_Text, buf, TAG_END );
#else
      if ( ! BE_QUIET ) printf(".");
      fflush(stdout);
#endif
    }
#ifdef GUI
    if ( connect_cancel == 1 ) return;
#endif
  }
  putnibble(2);
  for(count=0;getvalue()!=2;count++) {
    Delay(1);
#ifdef GUI
    HandleConnectWindowIDCMP();
#endif
    if(count%25==0) {
      pc = ( pc + 1 ) % 10;
#ifdef GUI
      memset( buf, '.', pc );
      buf[pc] = '\0';
      GT_SetGadgetAttrs( text, ConnectWindowWnd, NULL, GTTX_Text, buf, TAG_END );
#else
      if ( ! BE_QUIET ) printf(".");
      fflush(stdout);
#endif
    }
#ifdef GUI
    if ( connect_cancel == 1 ) return;
#endif
  }
  setack(1);
}

int sendfile(const char *name, int mode)
{
  int sendfile;
  int bytecyc;
  int outchecksum,inchecksum,checksum,wrong,tc;
  int sendbytes,ts;
  double d1;
  ULONG secss,secso, tsecs;
  long secs;
  ULONG usecss,usecso, tusecs;
  long usecs;
  int count;
  char outbuf[128],sendbuf[128];
  char *outbasename;
  apc_command_t com;
  int ret=0;
#ifdef GUI
  char guibuf[128];
#endif

  if(init_outgoing_file(name)!=0) {
#ifdef GUI
    rtEZRequest( "Can't open file %s!", "Okay", NULL, (struct TagItem *)rttags, name );
#else
    printf("can't open file %s!\n",name);
#endif
    return 1;
  }

  outbasename=(char*)FilePart((char*)name);
  sendfile=1;
#ifdef GUI
  GT_SetGadgetAttrs( Send_filesGadgets[ GD_sft ], Send_filesWnd, NULL, GTTX_Text, outbasename, TAG_END );
#else
  if ( ! BE_QUIET ) printf("sending file \"%s\", size %d\n",name,outfile.size);
#endif
  checksum=0;
  bytecyc=0;
  putint(outblock,APC_COMMAND_FILETRANSFER);

  putint(outblock+4,outfile.size);

  putint(outblock+8,min(strlen(outbasename),TRANSFERBLOCKSIZE-16));
  strncpy(outblock+12,outbasename,TRANSFERBLOCKSIZE-16);
  putint(outblock+TRANSFERBLOCKSIZE-4,permAmiga2PC(mode));

  /* sending the command to the other side
   * it get received via recvcommand
   */
  transferblock();

  com = (apc_command_t) getint( inblock );
  if ( com != APC_COMMAND_ABORT ) {

    /* preparing progress display */
    sprintf(outbuf,"%d",outfile.size);
#ifdef GUI
#define SEND_PRE ""
#else
#define SEND_PRE "SEND: "
#endif
    sprintf(sendbuf,SEND_PRE"%%%dd/%%%dd (%%3d%%%%)",(int)strlen(outbuf),(int)strlen(outbuf));
#undef SEND_PRE
    
    inchecksum=outchecksum=0;
    sendbytes=0;
    wrong=0;
    
    /* now synchronize with other side and check state */
    if(recvcommand(&com,NULL,NULL)==0) {
      if(com==APC_COMMAND_NOP) {
	CurrentTime(&secss,&usecss);
        tsecs = secss;
        tusecs = usecss;
	for(count=0;sendfile==1;count++) {
	  ts=readtobuffer(outblock,TRANSFERBLOCKSIZE-4,&outchecksum);
	  sendbytes+=ts;
	  if ( ts < 1 ) sendfile=2;
	  if ( ts < 0 ) wrong = 3;

          if ( send_cancel == 1 ) putint( outblock + TRANSFERBLOCKSIZE - 4, 0xffffffee );
	  else if(wrong==0) putint(outblock+TRANSFERBLOCKSIZE-4,outchecksum);
	  else putint(outblock+TRANSFERBLOCKSIZE-4,0xffffffff);

	  if ( ( sendfile == 1 ) || ( wrong != 0 ) ) {
	    transferblock();
	    tc=getint(inblock+TRANSFERBLOCKSIZE/2-4);
	    if(tc==0xffffffff) wrong=2;
            else if ( tc == 0xffffffee ) wrong = 4;  /* abort */
	  }
          if ( send_cancel == 1 ) wrong = 4;
	  if(wrong!=0) break;
	  
	  if ( ( count == 19 ) || ( sendfile != 1 ) ) {
	    count=0;
	    if ( outfile.size )
	      sprintf(outbuf,sendbuf,sendbytes,outfile.size,(sendbytes*100)/outfile.size);
	    else
	      sprintf(outbuf,sendbuf,0,0,100);	      
#ifdef GUI
            GT_SetGadgetAttrs( Send_filesGadgets[ GD_sbt ], Send_filesWnd, NULL, GTTX_Text, outbuf, TAG_END );
            HandleSend_filesIDCMP();
#else
	    if ( ! BE_QUIET ) printf("\r%s",outbuf);
	    fflush(stdout);
#endif

#ifdef GUI
            CurrentTime(&secso,&usecso);

            secs=secso-tsecs;
            usecs=usecso-tusecs;
            if(usecs<0) {
              secs--;
              usecs+=1000000;
	    }
	  
	    if ( ( secs == 0 ) && ( usecs == 0 ) ) d1 = 0.0;
	    else {
	      d1 = 20 * ( TRANSFERBLOCKSIZE - 4 ); /* 20 blocks with each TRANSFERBS - 4 */
	      d1*=1000000;
	      d1/=(secs*1000000.0+usecs);
	      d1/=1024;
	    }
            sprintf( guibuf, "%ld", (long)d1 );
            GT_SetGadgetAttrs( Send_filesGadgets[ GD_srt ], Send_filesWnd, NULL, GTTX_Text, guibuf, TAG_END );
            tsecs = secso;
            tusecs = usecso;
#endif
	  }
	}
	CurrentTime(&secso,&usecso);
#ifndef GUI
	if ( BE_VERBOSE ) printf("\nTransfer finished");
	else if ( ! BE_QUIET ) printf("\n");
#endif
	if(wrong==1) {
#ifdef GUI
          rtEZRequest( "Error while transfer\nI have received wrong datas!\n"
                       "Please repeat transmission!\n"
                       "Wrong file was %s", "Okay", NULL, (struct TagItem *)rttags, name );
#else
	  if ( BE_VERBOSE ) printf("\n");
	  printf("Error while transfer\nI have received wrong datas!\n");
	  printf("Please repeat transmission!\n");
	  printf( "Wrong file was %s\n", name );
#endif
	} else if(wrong==2) {
#ifdef GUI
          rtEZRequest( "Error while transfer\nThe PC reports data loss!\n"
                       "Please repeat transmission!\n"
                       "Wrong file was %s", "Okay", NULL, (struct TagItem *)rttags, name );
#else
	  if ( BE_VERBOSE ) printf("\n");
	  printf("Error while transfer\nThe PC reports data loss!\n");
	  printf("Please repeat transmission!\n");
	  printf( "Wrong file was %s\n", name );
#endif
	} else if(wrong==3) {
#ifdef GUI
          rtEZRequest( "Error while reading file\n"
                       "Wrong file was %s", "Okay", NULL, (struct TagItem *)rttags, name );
#else
	  if ( BE_VERBOSE ) printf("\n");
	  printf("Error while reading file\n");
	  printf( "Wrong file was %s\n", name );
#endif
	} else if ( wrong == 4) {
          /* no requester!, this is done by calling functions */
          ret = -1;
	} else {
	  secs=secso-secss;
	  usecs=usecso-usecss;
	  if(usecs<0) {
	    secs--;
	    usecs+=1000000;
	  }
	  
	  if ( ( secs == 0 ) && ( usecs == 0 ) ) d1 = 0.0;
	  else {
	    d1=outfile.size;
	    d1*=1000000;
	    d1/=(secs*1000000.0+usecs);
	    d1/=1024;
	  }
#ifdef GUI
          sprintf( guibuf, "%ld", (long)d1 );
          GT_SetGadgetAttrs( Send_filesGadgets[ GD_srt ], Send_filesWnd, NULL, GTTX_Text, guibuf, TAG_END );
#else
	  if ( BE_VERBOSE )
            printf(", file sended with %d KBytes/s\n", (int)d1 );
#endif

	  tfl.files++;
	  tfl.bytes += outfile.size;
	  tfl.secs += secs;
	  tfl.usecs += usecs;
	  if ( tfl.usecs >= 1000000 ) {
	    tfl.secs++;
	    tfl.usecs -= 1000000;
	  }
	}
      } else {
	if(com==APC_COMMAND_SKIPFILE) {
#ifndef GUI
	  if ( ! BE_QUIET ) printf("Skipping file!\n");
#endif
	} else if(com==APC_COMMAND_ABORT) {
	  ret=-1;
	} else {
#ifdef GUI
          rtEZRequest( "Wrong command %ld", "Okay", NULL, (struct TagItem *)rttags, com );
#else
	  printf("Wrong command %d\n",com);
#endif
	  ret=1;
	}
      }
    } else {
#ifdef GUI
      rtEZRequest( "Error while receiving command!", "Okay", NULL, (struct TagItem *)rttags );
#else
      printf("Error while receiving command!\n");
#endif
      ret=1;
    }
  } else {
    ret = -1;
  }
  close_outgoing_file();
  free(outfile.name);
  return ret;
}

int sendcommand(apc_command_t com,const char *arg, int mode)
{
  if(com==APC_COMMAND_FILETRANSFER) {
    return sendfile(arg, mode);
  } else if(com==APC_COMMAND_ERROR) {
    putint(outblock,com);
    transferblock();
  } else if(com==APC_COMMAND_ENTERDIR) {
    if( (strlen(arg)+1+4) <= (TRANSFERBLOCKSIZE-4) ) {
      putint(outblock,com);
      strncpy(outblock+4,arg,TRANSFERBLOCKSIZE-4-4);
      putint(outblock+TRANSFERBLOCKSIZE-4,permAmiga2PC(mode));
      transferblock();
    } else {
#ifdef GUI
      rtEZRequest( "Too long dirname!", "Okay", NULL, (struct TagItem *)rttags );
#else
      printf("Too long dirname!\n");
#endif
      return 1;
    }
  } else if(com==APC_COMMAND_LEAVEDIR) {
    putint(outblock,com);
    transferblock();
  } else if(com==APC_COMMAND_FINISHED) {
    putint(outblock,com);
    transferblock();
  } else if(com==APC_COMMAND_NOP) {
    putint(outblock,com);
    transferblock();
  } else if(com==APC_COMMAND_ABORT) {
    putint(outblock,com);
    transferblock();
  } else if(com==APC_COMMAND_SKIPFILE) {
    putint(outblock,com);
    transferblock();
  } else {
#ifdef GUI
    rtEZRequest( "Unknown command %ld to send!", "Okay", NULL, (struct TagItem *)rttags, com );
#else
    printf("Unknown command %d to send!\n",com);
#endif
    return 1;
  }
  return 0;
}

int recvcommand(apc_command_t *com,char **arg, int *mode)
{
  apc_command_t tc;
  char *narg;

  transferblock();
  tc=(apc_command_t)getint(inblock);
  switch(tc) {
    case APC_COMMAND_ERROR:
      *com=tc;
      if(arg!=NULL) *arg=NULL;
      if(mode!=NULL) *mode=0;
      break;
    case APC_COMMAND_ENTERDIR:
      if(arg!=NULL) {
	narg=(char*)malloc(TRANSFERBLOCKSIZE/2-4+1);
	if(narg!=NULL) {
	  *com=tc;
	  strncpy(narg,inblock+4,TRANSFERBLOCKSIZE/2-4-4);
	  narg[TRANSFERBLOCKSIZE/2-4-4]='\0';
	  *arg=narg;
	  *mode=permPC2Amiga(getint(inblock+TRANSFERBLOCKSIZE/2-4));
	} else return 1;
      } else return 1;
      break;
    case APC_COMMAND_LEAVEDIR:
      *com=tc;
      if(arg!=NULL) *arg=NULL;
      if(mode!=NULL) *mode=0;
      break;
    case APC_COMMAND_FILETRANSFER:
      *com=tc;
      if(arg!=NULL) *arg=NULL;
      if(mode!=NULL) *mode=0;
      return recvfile();
      break;
    case APC_COMMAND_FINISHED:
      *com=tc;
      if(arg!=NULL) *arg=NULL;
      if(mode!=NULL) *mode=0;
      break;
    case APC_COMMAND_NOP:
      *com=tc;
      if(arg!=NULL) *arg=NULL;
      if(mode!=NULL) *mode=0;
      break;
    case APC_COMMAND_ABORT:
      *com=tc;
      if(arg!=NULL) *arg=NULL;
      if(mode!=NULL) *mode=0;
      break;
    case APC_COMMAND_SKIPFILE:
      *com=tc;
      if(arg!=NULL) *arg=NULL;
      if(mode!=NULL) *mode=0;
      break;
    default:
#ifdef GUI
      rtEZRequest( "Unknown command %ld received!", "Okay", NULL, (struct TagItem *)rttags, tc );
#else
      printf("Unknown command %d received!\n",tc);
#endif
      return 1;
      break;
  }
  return 0;
}

int recvfile( void )
{
  char *inarg=NULL;
  int s1;
  int getfile;
  int bytecyc;
  int outchecksum,inchecksum,checksum,wrong,tc;
  int size,recbytes;
  double d1;
  ULONG secss,secsi;
#ifdef GUI
  ULONG tsecs, tusecs;
#endif
  long secs;
  ULONG usecss,usecsi;
  long usecs;
  int count;
  char outbuf[128],recvbuf[128],*cwd,*tstr=NULL;
  int cwdsize;
  int l;
  int ret;
  int mode;
#ifdef GUI
  char guibuf[128];
#endif

  size=getint(inblock+4);
  l=getint(inblock+8);

  inarg=(char*)malloc(l+1);
  if(inarg==NULL) return 1;
  strncpy(inarg,inblock+12,l);
  inarg[l]='\0';

  mode=permPC2Amiga(getint(inblock+TRANSFERBLOCKSIZE/2-4));
  
#ifdef GUI
  GT_SetGadgetAttrs( Receive_filesGadgets[ GD_rft ], Receive_filesWnd, NULL, GTTX_Text, inarg, TAG_END );
#else
  if ( ! BE_QUIET ) printf("receiving file \"%s\", size %d\n",inarg,size);
#endif
  ret=init_incoming_file(inarg);
  getfile=1;

  checksum=0;
  bytecyc=0;

  /* preparing progress display */
  sprintf(outbuf,"%d",size);
#ifdef GUI
#define RECV_PRE ""
#else
#define RECV_PRE "RECV: "
#endif
  sprintf(recvbuf,RECV_PRE"%%%dd/%%%dd (%%3d%%%%)",(int)strlen(outbuf),(int)strlen(outbuf));
#undef RECV_PRE

#ifndef GUI
  if ( BE_VERBOSE ) printf("Starting transfer\n");
#endif
  inchecksum=outchecksum=0;
  recbytes=0;
  wrong=0;
  tc = 0;

  if((ret>0)||(ret==-2)) {
#ifdef GUI
    rtEZRequest( "Can't create %s in %s, aborting", "Okay", NULL, (struct TagItem *)rttags, inarg, basedir );
#else
    printf( "Can't create %s in %s, aborting\n", inarg, basedir );
#endif
    sendcommand(APC_COMMAND_ABORT,NULL,0);
  } else if(ret==-1) {
    sendcommand(APC_COMMAND_SKIPFILE,NULL,0);
  } else if(ret==0) {
    sendcommand(APC_COMMAND_NOP,NULL,0);

    CurrentTime(&secss,&usecss);
    for(count=0;getfile==1;count++) {
      if(recbytes<size) {
        if ( receive_cancel == 1 ) putint( outblock + TRANSFERBLOCKSIZE - 4, 0xffffffee );
        else if(wrong==0) putint(outblock+TRANSFERBLOCKSIZE-4,0);
	else putint(outblock+TRANSFERBLOCKSIZE-4,0xffffffff);

	if(getfile==1) {
	  transferblock();
	  tc=getint(inblock+TRANSFERBLOCKSIZE/2-4);
	  if(tc==0xffffffff) wrong=2;
          else if ( tc == 0xffffffee ) wrong = 4;
	}
        if ( receive_cancel == 1) wrong = 4;
	if(wrong!=0) break;
	
	s1=size-recbytes;
	if(s1>TRANSFERBLOCKSIZE/2-4) s1=TRANSFERBLOCKSIZE/2-4;
	else getfile=2;
	
	writefrombuffer(inblock,s1,&inchecksum);
	recbytes+=s1;
	checksum=inchecksum-tc;
	if(checksum!=0) wrong=1;
      } else getfile = 2;
      
      if ( ( count == 19 ) || ( getfile != 1 ) ) {
	count=0;
	if ( size )
	  sprintf(outbuf,recvbuf,recbytes,size,(recbytes*100)/size);
	else
	  sprintf(outbuf,recvbuf,0,0,100);	  
#ifdef GUI
        GT_SetGadgetAttrs( Receive_filesGadgets[ GD_rbt ], Receive_filesWnd, NULL, GTTX_Text, outbuf, TAG_END );
        HandleReceive_filesIDCMP();
#else
	if ( ! BE_QUIET ) printf("\r%s",outbuf);
	fflush(stdout);
#endif

#ifdef GUI
        CurrentTime(&secsi,&usecsi);

        secs=secsi-tsecs;
        usecs=usecsi-tusecs;
        if(usecs<0) {
          secs--;
          usecs+=1000000;
	}
	  
	if ( ( secs == 0 ) && ( usecs == 0 ) ) d1 = 0.0;
	else {
	  d1 = 20 * ( TRANSFERBLOCKSIZE/2 - 4 ); /* 20 blocks with each TRANSFERBS/2 - 4 */
	  d1*=1000000;
	  d1/=(secs*1000000.0+usecs);
	  d1/=1024;
	}
        sprintf( guibuf, "%ld", (long)d1 );
        GT_SetGadgetAttrs( Receive_filesGadgets[ GD_rrt ], Receive_filesWnd, NULL, GTTX_Text, guibuf, TAG_END );
        tsecs = secsi;
        tusecs = usecsi;
#endif

      }
    }
    CurrentTime(&secsi,&usecsi);
#ifndef GUI
    if ( BE_VERBOSE ) printf("\nTransfer finished");
    else if ( ! BE_QUIET ) printf("\n");
#endif
    if(wrong==1) {
#ifdef GUI
      rtEZRequest( "Error while transfer\nI have received wrong datas!\n"
                   "Please repeat transmission!", "Okay", NULL, (struct TagItem *)rttags );
#else
      if ( BE_VERBOSE ) printf("\n");
      printf("Error while transfer\nI have received wrong datas!\n");
      printf("Please repeat transmission!\n");
#endif
    } else if(wrong==2) {
#ifdef GUI
      rtEZRequest( "Error while transfer\nThe PC reports data loss!\n"
                   "Please repeat transmission!", "Okay", NULL, (struct TagItem *)rttags );
#else
      if ( BE_VERBOSE ) printf("\n");
      printf("Error while transfer\nThe PC reports data loss!\n");
      printf("Please repeat transmission!\n");
#endif
    } else if ( wrong == 4 ) {
      ret = -1;
    } else {
      secs=secsi-secss;
      usecs=usecsi-usecss;
      if(usecs<0) {
	secs--;
	usecs+=1000000;
      }
      
      if ( ( secs == 0 ) && ( usecs == 0 ) ) d1 = 0.0;
      else {
	d1=size;
	d1*=1000000;
	d1/=(secs*1000000.0+usecs);
	d1/=1024;
      }
#ifdef GUI
      sprintf( guibuf, "%ld", (long)d1 );
      GT_SetGadgetAttrs( Receive_filesGadgets[ GD_rrt ], Receive_filesWnd, NULL, GTTX_Text, guibuf, TAG_END );
#else
      if ( BE_VERBOSE )
        printf(", file received with %d KBytes/s\n", (int)d1 );
#endif

      tfl.files++;
      tfl.bytes += size;
      tfl.secs += secs;
      tfl.usecs += usecs;
      if ( tfl.usecs >= 1000000 ) {
	tfl.secs++;
	tfl.usecs -= 1000000;
      }
    }
    close_incoming_file();
    
    /* File is stored in the current dir when basedir is NULL
     * File is stored relative to current dir in basedir when basedir contains NOT a ":"
     * File is stored in basedir when basedir contains a ":"
     */

    /* First get the cwd */
    cwdsize = 1024;
    cwd = (char*) malloc( cwdsize );
    if(cwd!=NULL) {
      while(getcwd(cwd,cwdsize)==NULL) {
	if(errno==ERANGE) {
	  free(cwd);
	  cwdsize*=2;
	  cwd=(char*)malloc(cwdsize);
	  if(cwd==NULL) break;
	} else {
	  free(cwd);
	  cwd=NULL;
	}
      }
    }

    /* now check all 3 cases */

    if ( basedir == NULL ) {

      /* just in the cwd */

      if(cwd!=NULL) {
	if(cwd[strlen(cwd)-1]==':') {
	  tstr=(char*)malloc(strlen(cwd)+strlen(infile.name)+1);
	  if(tstr!=NULL) sprintf(tstr,"%s%s",cwd,infile.name);
	} else {
	  tstr=(char*)malloc(strlen(cwd)+1+strlen(infile.name)+1);
	  if(tstr!=NULL) sprintf(tstr,"%s/%s",cwd,infile.name);
	}
      }
    } else {

      /* at least relative to basedir */

      if ( strrchr( basedir, ':' ) == NULL ) {

	/* basedir is relative */

	if ( cwd[strlen( cwd ) - 1] == ':' ) {
	  tstr = (char*) malloc( strlen( cwd ) + strlen( basedir ) + strlen( infile.name ) + 1 );
	  if ( tstr != NULL ) sprintf( tstr, "%s%s%s", cwd, basedir, infile.name );
	} else {
	  tstr = (char*) malloc( strlen( cwd ) + 1 + strlen( basedir ) + strlen( infile.name ) + 1 );
	  if(tstr!=NULL) sprintf( tstr, "%s/%s%s", cwd, basedir, infile.name );
	}
      } else {
	tstr = (char*) malloc( strlen( basedir ) + strlen( infile.name ) + 1 );
	if ( tstr != NULL ) sprintf( tstr, "%s%s", basedir, infile.name );
      }
    }

    if ( tstr != NULL ) {
#ifndef GUI
      if ( ( BE_VERBOSE ) || ( wrong ) ) printf( "Incoming file is stored at: %s\n", tstr );
#endif

      if ( ! ignore_prot )
	if ( SetProtection( tstr, mode ) == 0 )
#ifdef GUI
          rtEZRequest( "Can't restore file protection to %s", "Okay", NULL, (struct TagItem *)rttags, tstr );
#else
	  printf( "Can't restore file protection to %s\n", tstr );
#endif

      free( tstr );
    }
    if ( cwd != NULL) free(cwd);
    free( infile.name );
  }
  free(inarg);
  return ret;
}
