#include "ufk.h" #include char stopflag; recfile() { if (numprm > 2) prterr(ER_ONENAME); /* Only one name allowed */ else { if (!open_port(TRUE,FALSE)) /* Setup communication port */ prterr(ER_POPNERR); else { if (numprm == 2) strcpy(rec_filnam,params[1]); /* Get filename to use */ else rec_filnam[0] = '\0'; /* Use default name */ if (alloc_pkt(RECEIVE)) /* Allocate receive packet */ { rflg = 1; /* Receive command */ n = 0; /* Init packet number */ set_frame(); purgeline(ttyfd); /* Eat old input */ if (!recsw('R')) /* Receive the file(s) */ disp(0,18,"Receive failed.\n"); beep(); } close_port(rflg,FALSE); } } } getfile() { char status, i; if (numprm <= 1) /* check for parameter */ prterr(ER_FSPCREQ); else { if (!open_port(TRUE,FALSE)) /* Setup communication port */ prterr(ER_POPNERR); else { rec_filnam[0] = '\0'; /* Use default name */ if (alloc_pkt(RECEIVE)) /* Allocate receive packet */ { rflg = 2; /* 'GET' command */ n = 0; /* Init packet number */ set_frame(); i = TRUE; while (get_file_spec(i)) /* Get filespec */ { i = FALSE; if (!(status = get())) /* Get the file */ break; } while (get_file_spec(FALSE)); /* Flush filespec */ if (!status) disp(0,18,"Get failed.\n");/* Report failure */ beep(); } close_port(rflg,FALSE); } } } /* * get file from remote server */ get() { char num; int len; n = 0; numtry = 0; set_default_comm(); /* Set default communication */ aborted = FALSE; while(TRUE) { len = strlen(filnam); strcpy(sndpkt,filnam); /* Setup filename */ if (debug) { prtdbgf("Receive state: "); if (!screen) fputs("Receive state: ",stdout); disp_state(16,13,'R'); } spack('R',n,len,sndpkt,0,1); /* Receiver init */ switch(rpack(&len,&num,recpkt,1)) { case 'S': rpar(recpkt,len); /* Get the other side's init data */ spar(sndpkt,&len); /* Fill up packet with my init info */ spack('Y',n,len,sndpkt,0,1); /* ACK with my parameters */ oldtry = numtry; /* Save old try count */ numtry = 0; /* Start a new counter */ n = (n + 1) % 64; /* Bump packet number, mod 64 */ return(recsw('F')); /* Enter File-Receive state */ case 'E': prerrpkt(recpkt); /* error return */ return(FALSE); case 'T': if (aborted) /* user abort */ return(FALSE); default: if (numtry++ >= maxtry) return (FALSE); /* max try's exceeded */ } } } /* * r e c s w * * This is the state table switcher for receiving files. */ recsw(istate) char istate; { char rinit(), rfile(), rdata(); /* Use these procedures */ init_xfer(); /* reset character counters */ if (istate != 'F') /* if not already done */ set_default_comm(); /* Set default communication */ state = istate; /* set start state 'R' or 'F' */ numtry = 0; /* Say no tries yet */ stopflag = FALSE; /* Not stopped yet */ aborted = FALSE; /* Not aborted yet */ while(TRUE) { if (debug) { prtdbgf("Receive state: "); if (!screen) fputs("Receive state: ",stdout); disp_state(16,13,state); } switch(state) /* Do until done */ { case 'R': /* Receive-Init */ state = rinit(); break; case 'F': /* Receive-File */ state = rfile(); break; case 'D': /* Receive-Data */ state = rdata(); break; case 'C': /* Complete state */ fin_xfer(); return(TRUE); case 'Q': default: /* Unknown or abort */ fin_xfer(); return(FALSE); } } } /* * r i n i t * * Receive Initialization */ char rinit() { char num; /* Packet number */ int len; /* length */ if (numtry++ >= maxtry) /* If too many tries, "abort" */ return('Q'); switch(rpack(&len,&num,recpkt,1)) /* Get a packet */ { case 'S': /* Send-Init */ rpar(recpkt,len); /* Get the other side's init data */ spar(sndpkt,&len); /* Fill packet with my init info */ spack('Y',n,len,sndpkt,0,1); /* ACK with my parameters */ oldtry = numtry; /* Save old try count */ numtry = 0; /* Start a new counter */ n = (n + 1) % 64; /* Bump packet number, mod 64 */ return('F'); /* Enter File-Receive state */ case 'E': /* Error packet received */ prerrpkt(recpkt); /* Print it out and */ return('Q'); /* abort */ case 'T': /* Timeout */ if (aborted) return('Q'); /* aborted by user */ case FALSE: /* Didn't get packet */ spack('N',n,0,0,0,1); /* Return a NAK */ return(state); /* Keep trying */ default: /* Some other packet type, "abort" */ return('Q'); } } /* * r f i l e * * Receive File Header */ char rfile() { char num, *w; /* Packet number */ int len; /* length */ struct stat buf; if (numtry++ >= maxtry) /* "abort" if too many tries */ return('Q'); switch(rpack(&len,&num,recpkt,block_check_type)) /* Get a packet */ { case 'S': /* Send-Init, maybe our ACK lost */ if (oldtry++ >= maxtry) /* If too many tries "abort" */ return('Q'); if (num == ((n == 0) ? 63 : n-1)) /* Previous packet, mod 64? */ { /* Yes, ACK it again with */ spar(sndpkt,&len); /* our Send-Init parameters */ spack('Y',num,len,sndpkt,0,1); numtry = 0; /* Reset try counter */ return(state); /* Stay in this state */ } else /* Not previous packet, "abort" */ return('Q'); case 'Z': /* End-Of-File */ if (oldtry++ >= maxtry) return('Q'); if (num == ((n==0) ? 63 : n-1)) /* Previous packet, mod 64? */ { /* Yes, ACK it again. */ spack('Y',num,0,0,0,block_check_type); numtry = 0; return(state); /* Stay in this state */ } else /* Not previous packet, "abort" */ return('Q'); case 'F': /* File Header (just what we want) */ if (num != n) /* The packet number must be right */ return('Q'); if (!rec_filnam[0]) /* Copy filename if not given */ bufemp(recpkt,len,rec_filnam); map_case(rec_filnam,IN); /* map to correct case */ tabsleft = TABSIZE; /* Restore for real data */ transmit_chr_count = 0; /* Counter for total data size */ w = "w"; /* open text file */ if (warning && !stat(rec_filnam,&buf)) { /* File already there */ if (!remote && !nooutput) { clreol(0,19); printf("Warning: File %s already exists, creating new name", rec_filnam); beep(); if (!screen) fputs("\n\l",stdout); } new_name(rec_filnam); /* Create new filename */ } if ((fp = fopen(rec_filnam,w)) == NULL)/* Try to open new file */ { error(PER_CREATE,"%s",rec_filnam); /* Give up if error */ return('Q'); } else if (!nooutput) /* OK, give message */ { if (screen) { disp(0,2,"Receiving: "); disp(20,2,rec_filnam); clreol(-1,-1); } else printf("\n\lReceiving: %s\n\l",rec_filnam); prtdbgf("New file name: %s\n",rec_filnam); } spack('Y',n,0,0,0,block_check_type); /* Acknowledge file header */ oldtry = numtry; /* Reset try counters */ numtry = 0; /* ... */ stopflag = FALSE; /* In case we're aborted */ aborted = FALSE; init_attributes(); /* Prepare for attribute packets */ n = (n + 1) % 64; /* Bump packet number, mod 64 */ return('D'); /* Switch to Data state */ case 'B': /* Break transmission (EOT) */ if (num != n) /* Need right packet number here */ return ('Q'); spack('Y',n,0,0,0,block_check_type); /* Say OK */ return('C'); /* Go to complete state */ case 'E': /* Error packet received */ prerrpkt(recpkt); /* Print it out and */ return('Q'); /* abort */ case 'T': /* Timeout */ if (aborted) { error(PER_ABORTED); /* send error packet */ return('Q'); /* aborted by user */ } case FALSE: /* Didn't get packet */ spack('N',n,0,0,0,block_check_type); /* Return a NAK */ return(state); /* Keep trying */ default: /* Some other packet, "abort" */ return ('Q'); } } /* * r d a t a * * Receive Data */ char rdata() { char num; /* Packet number */ int tlen; /* length */ if (numtry++ >= maxtry) /* "abort" if too many tries */ return('Q'); switch(rpack(&size,&num,recpkt,block_check_type)) /* Get packet */ { case 'D': /* Got Data packet */ if (num != n) /* Right packet? */ { /* No */ if (oldtry++ >= maxtry) return('Q'); /* If too many tries, abort */ if (num == ((n==0) ? 63 : n-1)) /* Else check packet number */ { /* Previous packet again? */ spack('Y',num,0,0,0,block_check_type); /* Yes, re-ACK it */ numtry = 0; /* Reset try counter */ return(state); /* Don't write out data! */ } else /* sorry, wrong number */ return('Q'); } if (stopflag) /* Other side still sending ? */ { error(PER_ABORTED); /* Transfer aborted */ return('Q'); } /* Got data with right packet number */ if (bufemp(recpkt,size,0) == ERROR)/* Write the data to the file */ { error(PER_WRITE,"%d",errno);/* UniFLEX error */ return('Q'); /* enter abort state */ } tlen = 1; /* Assume aborted */ stopflag = TRUE; if (aborted == ABORTX) /* Abort current file ? */ *sndpkt = 'X'; else if (aborted == ABORTZ) /* Abort whole batch ? */ { *sndpkt = 'Z'; filecount = 0; /* No more files for 'GET' */ } else { tlen = 0; /* Nothing to abort, length = 0 */ stopflag = FALSE; } *(sndpkt+sizeof(char)) = '\0';/* For debug printout */ spack('Y',n,tlen,sndpkt,0,block_check_type);/* Ack packet */ oldtry = numtry; /* Reset the try counters */ numtry = 0; /* ... */ n = (n + 1) % 64; /* Bump packet number, mod 64 */ return('D'); /* Remain in data state */ case 'F': /* Got a File Header */ case 'X': if (oldtry++ >= maxtry) return('Q'); /* If too many tries, "abort" */ if (num == ((n==0) ? 63 : n-1)) /* Else check packet number */ { /* It was the previous one */ spack('Y',num,0,0,0,block_check_type); /* ACK it again */ numtry = 0; /* Reset try counter */ return(state); /* Stay in Data state */ } else /* Not previous packet, "abort" */ return('Q'); case 'A': /* Attribute packet */ if (num != n) /* Must have right packet number */ return('Q'); if (attribute) { if (rcv_attributes() == ERROR) /* Process receive attributes */ { error(PER_DEVFULL); /* Device full */ return('Q'); } } else { error(PER_PACKET); /* Packet error */ return('Q'); } spack('Y',n,0,0,0,block_check_type); /* OK, ACK it. */ n = (n + 1) % 64; /* Bump packet number */ return(state); /* Stay in data state */ case 'Z': /* End-Of-File */ if (num != n) /* Must have right packet number */ return('Q'); spack('Y',n,0,0,0,block_check_type); /* OK, ACK it. */ fclose(fp); /* Close the file */ if (attribute) fset_attributes(); /* set file attributes if enabled */ if (size == 1) /* Interrupt */ { if (!nooutput) { if (screen) { clreol(0,19); disp(0,19,"Transfer aborted."); } else fputs("Transfer aborted.\n\l",stdout); beep(); } if ((*recpkt == 'D') && !save_file) unlink(rec_filnam); /* Discard input file */ } rec_filnam[0] = '\0'; /* Use default for next transfer */ n = (n + 1) % 64; /* Bump packet number */ return('F'); /* Go back to Receive File state */ case 'E': /* Error packet received */ prerrpkt(recpkt); /* Print it out and */ return('Q'); /* abort */ case 'T': /* Timeout */ if (aborted) { error(PER_ABORTED); /* send error packet */ return('Q'); /* aborted by user */ } case FALSE: /* Didn't get packet */ spack('N',n,0,0,0,block_check_type); /* Return a NAK */ return(state); /* Keep trying */ default: /* Some other packet, "abort" */ return('Q'); } }