Newer
Older
,guts_lputs, guts_zmodem_progress
,guts_send_byte,guts_recv_byte,guts_is_connected
,NULL /* is_cancelled */
zm.log_level=&log_level;
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
zm.current_file_num = zm.total_files = 1; /* ToDo: support multi-file/batch uploads */
fsize=filelength(fileno(fp));
if(zmodem_send_file(&zm, gi.files[0], fp
,/* ZRQINIT? */TRUE, /* start_time */NULL, /* sent_bytes */ NULL))
zmodem_get_zfin(&zm);
fclose(fp);
oob_close(&gi);
}
void guts_transfer(struct bbslist *bbs)
{
struct GUTS_info gi;
if(safe_mode)
return;
setup_defaults(&gi);
gi.socket=conn_socket;
gi.telnet=bbs->conn_type==CONN_TYPE_TELNET;
gi.server=FALSE;
gi.use_daemon=FALSE;
gi.orig=FALSE;
if(negotiation(&gi)) {
oob_close(&gi);
return;
}
/* Authentication Phase */
if(!gi.inband) {
if(authenticate(&gi)) {
oob_close(&gi);
return;
}
}
if(gi.inband) {
if(gi.direction==UPLOAD)
begin_upload(bbs, TRUE);
zmodem_download(bbs);
oob_close(&gi);
}
else {
if(gi.direction==UPLOAD) {
int result;
struct file_pick fpick;
init_uifc(FALSE, FALSE);
result=filepick(&uifc, "Upload", &fpick, bbs->uldir, NULL, UIFC_FP_ALLOWENTRY);
if(result==-1 || fpick.files<1) {
check_exit(FALSE);
filepick_free(&fpick);
uifcbail();
return;
}
strListPush(&gi.files, fpick.selected[0]);
filepick_free(&fpick);
uifcbail();
_beginthread(guts_background_upload, 0, &gi);
}
else {
strListPush(&gi.files, bbs->dldir);
_beginthread(guts_background_download, 0, &gi);
}
}
return;
}
#endif
void raw_upload(FILE *fp)
{
char buf[1024];
int r;
int inch;
char ch[2];
ch[1]=0;
for(;;) {
r=fread(buf, 1, sizeof(buf), fp);
if(r)
conn_send(buf, r,0);
/* Note, during RAW uploads, do NOT send ANSI responses and don't
* allow speed changes. */
while((inch=recv_byte(NULL, 0))>=0) {
ch[0]=inch;
cterm_write(cterm, ch, 1, NULL, 0, NULL);
}
if(r==0)
break;
}
fclose(fp);
}
{
char linebuf[1024+2]; /* One extra for terminator, one extra for added CR */
char *p;
char ch[2];
int inch;
ch[1]=0;
while(!feof(fp)) {
if(fgets(linebuf, 1025, fp)!=NULL) {
if((p=strrchr(linebuf,'\n'))!=NULL) {
if((p==linebuf && !lastwascr) || (p>linebuf && *(p-1)!='\n')) {
*p='\r';
p++;
*p='\n';
p++;
*p=0;
}
}
if(p!=NULL && p>linebuf) {
if(*(p-1)=='\r')
lastwascr=TRUE;
}
conn_send(linebuf,strlen(linebuf),0);
}
/* Note, during ASCII uploads, do NOT send ANSI responses and don't
* allow speed changes. */
while((inch=recv_byte(NULL, 0))>=0) {
ch[0]=inch;
cterm_write(cterm, ch, 1, NULL, 0, NULL);
}
}
fclose(fp);
}
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
static void transfer_complete(BOOL success)
{
int timeout = success ? settings.xfer_success_keypress_timeout : settings.xfer_failure_keypress_timeout;
conn_binary_mode_off();
if(log_fp!=NULL)
fflush(log_fp);
/* TODO: Make this pretty (countdown timer) and don't delay a second between keyboard polls */
lprintf(LOG_NOTICE,"Hit any key or wait %u seconds to continue...", timeout);
while(timeout > 0) {
if (kbhit()) {
if(getch()==0 && getch()<<8 == CIO_KEY_QUIT)
check_exit(FALSE);
break;
}
timeout--;
SLEEP(1000);
}
erase_transfer_window();
}
void zmodem_upload(struct bbslist *bbs, FILE *fp, char *path)
BOOL success;
zmodem_t zm;
struct zmodem_cbdata cbdata;
draw_transfer_window("ZMODEM Upload");
zmodem_mode=ZMODEM_MODE_SEND;
cbdata.zm=&zm;
cbdata.bbs=bbs;
conn_binary_mode_on();
,/* cbdata */&cbdata
,send_byte,recv_byte
,is_connected
,zmodem_check_abort
zm.log_level=&log_level;
zm.current_file_num = zm.total_files = 1; /* ToDo: support multi-file/batch uploads */
fsize=filelength(fileno(fp));
lprintf(LOG_INFO,"Sending %s (%"PRId64" KB) via ZMODEM"
if((success=zmodem_send_file(&zm, path, fp
,/* ZRQINIT? */TRUE, /* start_time */NULL, /* sent_bytes */ NULL)) == TRUE)
zmodem_get_zfin(&zm);
fclose(fp);
transfer_complete(success);
BOOL zmodem_duplicate_callback(void *cbdata, void *zm_void)
{
struct text_info txtinfo;
BOOL ret=FALSE;
int i;
char *opts[4]={
"Overwrite"
,"Choose New Name"
,"Cancel Download"
,NULL
};
struct zmodem_cbdata *cb=(struct zmodem_cbdata *)cbdata;
zmodem_t *zm=(zmodem_t *)zm_void;
char fpath[MAX_PATH+1];
int old_hold=hold_update;
gettextinfo(&txtinfo);
window(1, 1, txtinfo.screenwidth, txtinfo.screenheight);
init_uifc(FALSE, FALSE);
while(loop) {
loop=FALSE;
i=0;
uifc.helpbuf="Duplicate file... choose action\n";
switch(uifc.list(WIN_MID|WIN_SAV,0,0,0,&i,NULL,"Duplicate File Name",opts)) {
case -1:
if (check_exit(FALSE)) {
ret=FALSE;
break;
}
loop=TRUE;
break;
case 0: /* Overwrite */
sprintf(fpath,"%s/%s",cb->bbs->dldir,zm->current_file_name);
unlink(fpath);
ret=TRUE;
break;
case 1: /* Choose new name */
uifc.changes=0;
uifc.helpbuf="Duplicate Filename... enter new name";
if(uifc.input(WIN_MID|WIN_SAV,0,0,"New Filename: ",zm->current_file_name,sizeof(zm->current_file_name)-1,K_EDIT)==-1) {
loop=TRUE;
}
else {
if(uifc.changes)
ret=TRUE;
else
loop=TRUE;
}
break;
}
}
uifcbail();
restorescreen(savscrn);
freescreen(savscrn);
gotoxy(txtinfo.curx, txtinfo.cury);
hold_update=old_hold;
return(ret);
}
void zmodem_download(struct bbslist *bbs)
int files_received;
struct zmodem_cbdata cbdata;
draw_transfer_window("ZMODEM Download");
zmodem_mode=ZMODEM_MODE_RECV;
conn_binary_mode_on();
cbdata.zm=&zm;
cbdata.bbs=bbs;
zmodem_init(&zm
,/* cbdata */&cbdata
,lputs, zmodem_progress
,send_byte,recv_byte
,is_connected
,zmodem_check_abort
zm.log_level=&log_level;
zm.duplicate_filename=zmodem_duplicate_callback;
files_received=zmodem_recv_files(&zm,bbs->dldir,&bytes_received);
if(files_received>1)
lprintf(LOG_INFO,"Received %u files (%"PRId64" bytes) successfully", files_received, bytes_received);
transfer_complete(files_received);
/* X/Y-MODEM stuff */
uchar block[1024]; /* Block buffer */
ulong block_num; /* Block number */
static BOOL xmodem_check_abort(void* vp)
{
xmodem_t* xm = (xmodem_t*)vp;
static time_t last_check=0;
time_t now=time(NULL);
int key;
if (xm == NULL)
return FALSE;
if (quitting) {
xm->cancelled=TRUE;
return TRUE;
}
if(last_check != now) {
last_check=now;
while(kbhit()) {
switch((key=getch())) {
case ESC:
case CTRL_C:
case CTRL_X:
xm->cancelled=TRUE;
break;
case 0:
case 0xe0:
key |= (getch() << 8);
if(key==CIO_KEY_MOUSE)
getmouse(NULL);
if (key==CIO_KEY_QUIT) {
if (check_exit(FALSE))
xm->cancelled=TRUE;
}
}
}
return(xm->cancelled);
}
/****************************************************************************/
/* Returns the number of blocks required to send len bytes */
/****************************************************************************/
uint64_t num_blocks(unsigned curr_block, uint64_t offset, uint64_t len, unsigned block_size)
blocks=len/block_size;
if(len%block_size)
blocks++;
#if defined(__BORLANDC__)
#pragma argsused
#endif
void xmodem_progress(void* cbdata, unsigned block_num, int64_t offset, int64_t fsize, time_t start)
unsigned cps;
time_t l;
time_t t;
time_t now;
static time_t last_progress;
int old_hold=hold_update;
xmodem_t* xm=(xmodem_t*)cbdata;
now=time(NULL);
if(now-last_progress>0 || offset >= fsize) {
xmodem_check_abort(cbdata);
hold_update = TRUE;
window(((trans_ti.screenwidth-TRANSFER_WIN_WIDTH)/2)+2
, ((trans_ti.screenheight-TRANSFER_WIN_HEIGHT)/2)+1
, ((trans_ti.screenwidth-TRANSFER_WIN_WIDTH)/2) + TRANSFER_WIN_WIDTH - 2
, ((trans_ti.screenheight-TRANSFER_WIN_HEIGHT)/2)+5);
gotoxy(1,1);
textattr(LIGHTCYAN | (BLUE<<4));
t=now-start;
if(t<=0)
t=1;
l=(time_t)(fsize/cps); /* total transfer est time */
l-=t; /* now, it's est time left */
if(l<0) l=0;
if((*(xm->mode))&SEND) {
total_blocks=num_blocks(block_num,offset,fsize,xm->block_size);
,xm->block_size%1024L ? xm->block_size: xm->block_size/1024L
,xm->block_size%1024L ? "" : "K"
,block_num
,total_blocks
,offset);
clreol();
cputs("\r\n");
cprintf("Time: %lu:%02lu/%lu:%02lu %u cps"
,t/60L
,t%60L
,l/60L
,l%60L
,cps
,fsize?(long)(((float)offset/(float)fsize)*100.0):100
);
clreol();
cputs("\r\n");
cprintf("%*s%3d%%\r\n", TRANSFER_WIN_WIDTH/2-5, ""
,fsize?(long)(((float)offset/(float)fsize)*100.0):100);
l = fsize?(long)(((float)offset/(float)fsize)*60.0):60;
cprintf("[%*.*s%*s]", l, l,
"\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1"
"\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1"
"\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1"
"\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1"
"\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1"
"\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1"
, 60-l, "");
} else if((*(xm->mode))&YMODEM) {
cprintf("Block (%lu%s): %lu Byte: %"PRId64
,xm->block_size%1024L ? xm->block_size: xm->block_size/1024L
,xm->block_size%1024L ? "" : "K"
,block_num
,offset);
clreol();
cputs("\r\n");
cprintf("Time: %lu:%02lu/%lu:%02lu %u cps"
,t/60L
,t%60L
,l/60L
,l%60L
,cps);
clreol();
cputs("\r\n");
cprintf("%*s%3d%%\r\n", TRANSFER_WIN_WIDTH/2-5, ""
,fsize?(long)(((float)offset/(float)fsize)*100.0):100);
l = fsize?(long)(((float)offset/(float)fsize)*60.0):60;
cprintf("[%*.*s%*s]", l, l,
"\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1"
"\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1"
"\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1"
"\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1"
"\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1"
"\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1"
, 60-l, "");
} else { /* XModem receive */
cprintf("Block (%lu%s): %lu Byte: %"PRId64
,xm->block_size%1024L ? xm->block_size: xm->block_size/1024L
,xm->block_size%1024L ? "" : "K"
,block_num
,offset);
clreol();
cputs("\r\n");
cprintf("Time: %lu:%02lu %u cps"
,t/60L
,t%60L
,cps);
clreol();
}
last_progress=now;
hold_update = FALSE;
gotoxy(wherex(), wherey());
hold_update = old_hold;
}
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
static int recv_g(void *cbdata, unsigned timeout)
{
xmodem_t *xm=(xmodem_t *)cbdata;
xm->recv_byte=recv_byte;
return('G');
}
static int recv_c(void *cbdata, unsigned timeout)
{
xmodem_t *xm=(xmodem_t *)cbdata;
xm->recv_byte=recv_byte;
return('C');
}
static int recv_nak(void *cbdata, unsigned timeout)
{
xmodem_t *xm=(xmodem_t *)cbdata;
xm->recv_byte=recv_byte;
}
void xmodem_upload(struct bbslist *bbs, FILE *fp, char *path, long mode, int lastch)
BOOL success;
xmodem_t xm;
ulong fsize;
conn_binary_mode_on();
xmodem_init(&xm
,/* cbdata */&xm
,&mode
,lputs
,xmodem_progress
,send_byte
,recv_byte
,is_connected
,xmodem_check_abort
xm.log_level=&log_level;
if(!data_waiting(&xm, 0)) {
switch(lastch) {
case 'G':
xm.recv_byte=recv_g;
break;
case 'C':
xm.recv_byte=recv_c;
break;
case NAK:
xm.recv_byte=recv_nak;
break;
}
}
xm.total_files = 1; /* ToDo: support multi-file/batch uploads */
fsize=filelength(fileno(fp));
if(mode&XMODEM) {
if(mode&GMODE)
draw_transfer_window("XMODEM-g Upload");
else
draw_transfer_window("XMODEM Upload");
lprintf(LOG_INFO,"Sending %s (%"PRId64" KB) via XMODEM%s"
draw_transfer_window("YMODEM-g Upload");
draw_transfer_window("YMODEM Upload");
lprintf(LOG_INFO,"Sending %s (%"PRId64" KB) via YMODEM%s"
fclose(fp);
conn_binary_mode_off();
if((success=xmodem_send_file(&xm, path, fp
,/* start_time */NULL, /* sent_bytes */ NULL)) == TRUE) {
if(mode&YMODEM) {
if(xmodem_get_mode(&xm)) {
lprintf(LOG_INFO,"Sending YMODEM termination block");
memset(block,0,128); /* send short block for terminator */
xmodem_put_block(&xm, block, 128 /* block_size */, 0 /* block_num */);
if(xmodem_get_ack(&xm,/* tries: */6, /* block_num: */0) != ACK) {
lprintf(LOG_WARNING,"Failed to receive ACK after terminating block");
}
}
}
}
fclose(fp);
transfer_complete(success);
BOOL xmodem_duplicate(xmodem_t *xm, struct bbslist *bbs, char *path, size_t pathsize, char *fname)
{
struct text_info txtinfo;
BOOL ret=FALSE;
int i;
char *opts[4]={
"Overwrite"
,"Choose New Name"
,"Cancel Download"
,NULL
};
char newfname[MAX_PATH+1];
BOOL loop=TRUE;
int old_hold=hold_update;
window(1, 1, txtinfo.screenwidth, txtinfo.screenheight);
while(loop) {
loop=FALSE;
i=0;
uifc.helpbuf="Duplicate file... choose action\n";
switch(uifc.list(WIN_MID|WIN_SAV,0,0,0,&i,NULL,"Duplicate File Name",opts)) {
case -1:
if (check_exit(FALSE)) {
ret=FALSE;
break;
}
loop=TRUE;
break;
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
case 0: /* Overwrite */
unlink(path);
ret=TRUE;
break;
case 1: /* Choose new name */
uifc.changes=0;
uifc.helpbuf="Duplicate Filename... enter new name";
SAFECOPY(newfname, getfname(fname));
if(uifc.input(WIN_MID|WIN_SAV,0,0,"New Filename: ",newfname,sizeof(newfname)-1,K_EDIT)==-1) {
loop=TRUE;
}
else {
if(uifc.changes) {
sprintf(path,"%s/%s",bbs->dldir,newfname);
ret=TRUE;
}
else
loop=TRUE;
}
break;
}
}
uifcbail();
restorescreen(savscrn);
freescreen(savscrn);
void xmodem_download(struct bbslist *bbs, long mode, char *path)
{
xmodem_t xm;
/* The better to -Wunused you with my dear! */
int64_t file_bytes=0,file_bytes_left=0;
int64_t total_bytes=0;
time_t t,startfile,ftime=0;
int old_hold=hold_update;
if(safe_mode)
return;
if(mode&XMODEM)
if(mode&GMODE)
draw_transfer_window("XMODEM-g Download");
else
draw_transfer_window("XMODEM Download");
draw_transfer_window("YMODEM-g Download");
draw_transfer_window("YMODEM Download");
return;
conn_binary_mode_on();
xmodem_init(&xm
,/* cbdata */&xm
,&mode
,lputs
,xmodem_progress
,send_byte
,recv_byte
,is_connected
,xmodem_check_abort
xm.log_level=&log_level;
if(isfullpath(path))
SAFECOPY(str,path);
else
sprintf(str,"%s/%s",bbs->dldir,path);
lprintf(LOG_INFO,"Fetching YMODEM header block");
for(errors=0;errors<=xm.max_errors && !xm.cancelled;errors++) {
xmodem_put_nak(&xm, /* expected_block: */ 0);
i=xmodem_get_block(&xm, block, /* expected_block: */ 0);
if(i==NOINP && (mode&GMODE)) { /* Timeout */
mode &= ~GMODE;
lprintf(LOG_WARNING,"Falling back to %s",
(mode&CRC)?"CRC-16":"Checksum");
}
lprintf(LOG_WARNING,"Falling back to XMODEM%s",(mode&GMODE)?"-g":"");
mode |= XMODEM|CRC;
erase_transfer_window();
if(uifc.input(WIN_MID|WIN_SAV,0,0,"XMODEM Filename",fname,sizeof(fname),0)==-1) {
xmodem_cancel(&xm);
goto end;
}
hold_update=old_hold;
if(mode&GMODE)
draw_transfer_window("XMODEM Download");
else
draw_transfer_window("XMODEM-g Download");
lprintf(LOG_WARNING,"Falling back to XMODEM%s",(mode&GMODE)?"-g":"");
if(isfullpath(fname))
SAFECOPY(str,fname);
else
sprintf(str,"%s/%s",bbs->dldir,fname);
file_bytes=file_bytes_left=0x7fffffff;
break;
if(errors+1>xm.max_errors/3 && mode&CRC && !(mode&GMODE)) {
lprintf(LOG_NOTICE,"Falling back to 8-bit Checksum mode");
mode&=~CRC;
}
if(errors>xm.max_errors || xm.cancelled) {
if(i!=NOT_YMODEM) {
if(!block[0]) {
lprintf(LOG_INFO,"Received YMODEM termination block");
goto end;
}
file_bytes=total_bytes=0;
ftime=total_files=0;
i=sscanf(((char *)block)+strlen((char *)block)+1,"%"PRId64" %lo %lo %lo %d %"PRId64
,&file_bytes /* file size (decimal) */
,&tmpftime /* file time (octal unix format) */
,&fmode /* file mode (not used) */
,&serial_num /* program serial number */
,&total_files /* remaining files to be sent */
,&total_bytes /* remaining bytes to be sent */
);
ftime=tmpftime;
lprintf(LOG_DEBUG,"YMODEM header (%u fields): %s", i, block+strlen((char *)block)+1);
SAFECOPY(fname,((char *)block));
if(!file_bytes)
file_bytes=0x7fffffff;
file_bytes_left=file_bytes;
if(!total_files)
total_files=1;
if(total_bytes<file_bytes)
total_bytes=file_bytes;
lprintf(LOG_DEBUG,"Incoming filename: %.64s ",getfname(fname));
sprintf(str,"%s/%s",bbs->dldir,getfname(fname));
lprintf(LOG_INFO,"File size: %"PRId64" bytes", file_bytes);
lprintf(LOG_INFO,"Remaining: %"PRId64" bytes in %u files", total_bytes, total_files);
lprintf(LOG_DEBUG,"Receiving: %.64s ",str);
fnum++;
while(fexistcase(str) && !(mode&OVERWRITE)) {
xmodem_duplicate(&xm, bbs, str, sizeof(str), getfname(fname));
if((fp=fopen(str,"wb"))==NULL) {
lprintf(LOG_ERR,"Error %d creating %s",errno,str);
lprintf(LOG_INFO,"Receiving %s via %s %s"
,mode&GMODE ? "XMODEM-g" : "XMODEM"
,mode&CRC ? "CRC-16" : "Checksum");
lprintf(LOG_INFO,"Receiving %s (%"PRId64" KB) via %s %s"
,mode&GMODE ? "YMODEM-g" : "YMODEM"
,mode&CRC ? "CRC-16" : "Checksum");
startfile=time(NULL);
success=FALSE;
errors=0;
block_num=1;
if(i!=NOT_YMODEM)
xmodem_put_nak(&xm, block_num);
xmodem_progress(&xm,block_num,ftello(fp),file_bytes,startfile);
if(xm.is_cancelled(&xm)) {
lprintf(LOG_WARNING,"Cancelled locally");
xmodem_cancel(&xm);
goto end;
}
else
i=xmodem_get_block(&xm, block, block_num);
if(i==EOT) { /* end of transfer */
success=TRUE;
xmodem_put_ack(&xm);
break;
}
if(i==CAN) { /* Cancel */
xm.cancelled=TRUE;
break;
}
if(mode&GMODE) {
lprintf(LOG_ERR,"Too many errors (%u)",++errors);
goto end;
}
if(++errors>xm.max_errors) {
lprintf(LOG_ERR,"Too many errors (%u)",errors);
xmodem_cancel(&xm);
break;
}
if(i!=NOT_XMODEM
&& block_num==1 && errors>(xm.max_errors/3) && mode&CRC && !(mode&GMODE)) {
lprintf(LOG_NOTICE,"Falling back to 8-bit Checksum mode (error=%d)", i);
if(!(mode&GMODE)) {
send_byte(&xm,ACK,10);
flush_send(&xm);
}
if(file_bytes_left<=0L) { /* No more bytes to receive */
lprintf(LOG_WARNING,"Sender attempted to send more bytes than were specified in header");
if(wr>(uint)file_bytes_left)
wr=(uint)file_bytes_left;
lprintf(LOG_ERR,"Error writing %u bytes to file at offset %"PRId64
,wr,(int64_t)ftello(fp));
xmodem_cancel(&xm);
goto end;
}
file_bytes_left-=wr;
block_num++;
}
lprintf(LOG_DEBUG,"file_bytes=%u", file_bytes);
lprintf(LOG_DEBUG,"file_bytes_left=%u", file_bytes_left);
lprintf(LOG_DEBUG,"filelength=%u", filelength(fileno(fp)));
lprintf(LOG_INFO,"Truncating file to %lu bytes", (ulong)file_bytes);
chsize(fileno(fp),(ulong)file_bytes); /* 4GB limit! */
} else
file_bytes = filelength(fileno(fp));
fclose(fp);
t=time(NULL)-startfile;
if(!t) t=1;
if(success)
lprintf(LOG_INFO,"Successful - Time: %lu:%02lu CPS: %lu"
,t/60,t%60,file_bytes/t);
else
lprintf(LOG_ERR,"File Transfer %s", xm.cancelled ? "Cancelled":"Failure");
if(!(mode&XMODEM) && ftime)
setfdate(str,ftime);
if(!success && file_bytes==0) /* remove 0-byte files */
remove(str);
cps=1;
total_files--;
total_bytes-=file_bytes;
if(total_files>1 && total_bytes)
lprintf(LOG_INFO,"Remaining - Time: %lu:%02lu Files: %u KBytes: %"PRId64
,(total_bytes/cps)/60
,(total_bytes/cps)%60
,total_files
,total_bytes/1024
);
}
end:
transfer_complete(success);
}
/* End of X/Y-MODEM stuff */
void music_control(struct bbslist *bbs)
{
struct text_info txtinfo;
int i;
char *opts[4]={
"ESC[| ANSI Music only"
,"ESC[N (BANSI-Style) and ESC[| ANSI Music"
,"ANSI Music Enabled"
};
gettextinfo(&txtinfo);
i=cterm->music_enable;
uifc.helpbuf="`ANSI Music Setup`\n\n"
"~ ANSI Music Disabled ~ Completely disables ANSI music\n"
" Enables Delete Line\n"
"~ ESC[N ~ Enables BANSI-Style ANSI music\n"
" Enables Delete Line\n"
"~ ANSI Music Enabled ~ Enables both ESC[M and ESC[N ANSI music.\n"
" Delete Line is disabled.\n"
"\n"
"So-Called ANSI Music has a long and troubled history. Although the\n"
"original ANSI standard has well defined ways to provide private\n"
"extensions to the spec, none of these methods were used. Instead,\n"
"so-called ANSI music replaced the Delete Line ANSI sequence. Many\n"
"full-screen editors use DL, and to this day, some programs (Such as\n"
"BitchX) require it to run.\n\n"
"To deal with this, BananaCom decided to use what *they* thought was an\n"
"unspecified escape code, ESC[N, for ANSI music. Unfortunately, this is\n"
"broken also. Although rarely implemented in BBS clients, ESC[N is\n"
"the erase field sequence.\n\n"
"SyncTERM has now defined a third ANSI music sequence which *IS* legal\n"
"according to the ANSI spec. Specifically ESC[|.";
if(uifc.list(WIN_MID|WIN_SAV,0,0,0,&i,NULL,"ANSI Music Setup",opts)!=-1)
cterm->music_enable=i;
else
check_exit(FALSE);
restorescreen(savscrn);
freescreen(savscrn);
void font_control(struct bbslist *bbs)
{
struct text_info txtinfo;
int i,j,k;