Annotation of sbbs/src/sbbs3/sexyz.c, revision 1.1.1.1

1.1       root        1: /* sexyz.c */
                      2: 
                      3: /* Synchronet External X/Y/ZMODEM Transfer Protocols */
                      4: 
                      5: /* $Id: sexyz.c,v 1.77 2006/12/28 22:25:36 rswindell Exp $ */
                      6: 
                      7: /****************************************************************************
                      8:  * @format.tab-size 4          (Plain Text/Source Code File Header)                    *
                      9:  * @format.use-tabs true       (see http://www.synchro.net/ptsc_hdr.html)              *
                     10:  *                                                                                                                                                     *
                     11:  * Copyright 2006 Rob Swindell - http://www.synchro.net/copyright.html         *
                     12:  *                                                                                                                                                     *
                     13:  * This program is free software; you can redistribute it and/or                       *
                     14:  * modify it under the terms of the GNU General Public License                         *
                     15:  * as published by the Free Software Foundation; either version 2                      *
                     16:  * of the License, or (at your option) any later version.                                      *
                     17:  * See the GNU General Public License for more details: gpl.txt or                     *
                     18:  * http://www.fsf.org/copyleft/gpl.html                                                                                *
                     19:  *                                                                                                                                                     *
                     20:  * Anonymous FTP access to the most recent released source is available at     *
                     21:  * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net     *
                     22:  *                                                                                                                                                     *
                     23:  * Anonymous CVS access to the development source and modification history     *
                     24:  * is available at cvs.synchro.net:/cvsroot/sbbs, example:                                     *
                     25:  * cvs -d :pserver:[email protected]:/cvsroot/sbbs login                       *
                     26:  *     (just hit return, no password is necessary)                                                     *
                     27:  * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src                *
                     28:  *                                                                                                                                                     *
                     29:  * For Synchronet coding style and modification guidelines, see                                *
                     30:  * http://www.synchro.net/source.html                                                                          *
                     31:  *                                                                                                                                                     *
                     32:  * You are encouraged to submit any modifications (preferably in Unix diff     *
                     33:  * format) via e-mail to [email protected]                                                                      *
                     34:  *                                                                                                                                                     *
                     35:  * Note: If this box doesn't appear square, then you need to fix your tabs.    *
                     36:  ****************************************************************************/
                     37: 
                     38: /* 
                     39:  * ZMODEM code based on zmtx/zmrx v1.02 (C) Mattheij Computer Service 1994
                     40:  * by Jacques Mattheij <[email protected]> 
                     41:  */
                     42: 
                     43: #include <time.h>
                     44: #include <stdio.h>
                     45: #include <errno.h>
                     46: #include <string.h>
                     47: #include <stdlib.h>
                     48: #include <stdarg.h>
                     49: #include <ctype.h>             /* isdigit */
                     50: #include <sys/stat.h>
                     51: 
                     52: #ifdef __unix__
                     53:        #include <termios.h>
                     54:        #include <signal.h>
                     55: #endif
                     56: 
                     57: /* xpdev */
                     58: #include "conwrap.h"
                     59: #include "genwrap.h"
                     60: #include "semwrap.h"
                     61: #include "dirwrap.h"
                     62: #include "filewrap.h"
                     63: #include "sockwrap.h"
                     64: #include "str_list.h"
                     65: #include "ini_file.h"
                     66: #include "eventwrap.h"
                     67: #include "threadwrap.h"
                     68: 
                     69: /* sbbs */
                     70: #include "ringbuf.h"
                     71: #include "telnet.h"
                     72: #include "nopen.h"
                     73: 
                     74: /* sexyz */
                     75: #include "sexyz.h"
                     76: 
                     77: #define SINGLE_THREADED                FALSE
                     78: #define MIN_OUTBUF_SIZE                1024
                     79: #define MAX_OUTBUF_SIZE                (64*1024)
                     80: 
                     81: /***************/
                     82: /* Global Vars */
                     83: /***************/
                     84: long   mode=0;                                                 /* Program mode                                         */
                     85: long   zmode=0L;                                               /* Zmodem mode                                          */
                     86: uchar  block[1024];                                    /* Block buffer                                         */
                     87: ulong  block_num;                                              /* Block number                                         */
                     88: char*  dszlog;
                     89: BOOL   dszlog_path=TRUE;                               /* Log complete path to filename        */
                     90: BOOL   dszlog_short=FALSE;                             /* Log Micros~1 short filename          */
                     91: BOOL   dszlog_quotes=FALSE;                    /* Quote filenames in DSZLOG            */
                     92: int            log_level=LOG_INFO;
                     93: 
                     94: xmodem_t xm;
                     95: zmodem_t zm;
                     96: 
                     97: FILE*  errfp;
                     98: FILE*  statfp;
                     99: FILE*  logfp=NULL;
                    100: 
                    101: char   revision[16];
                    102: 
                    103: SOCKET sock=INVALID_SOCKET;
                    104: 
                    105: BOOL   telnet=TRUE;
                    106: #ifdef __unix__
                    107: BOOL   stdio=FALSE;
                    108: struct termios origterm;
                    109: #endif
                    110: BOOL   aborted=FALSE;
                    111: BOOL   terminate=FALSE;
                    112: BOOL   debug_tx=FALSE;
                    113: BOOL   debug_rx=FALSE;
                    114: BOOL   debug_telnet=FALSE;
                    115: BOOL   pause_on_exit=FALSE;
                    116: BOOL   pause_on_abend=FALSE;
                    117: BOOL   newline=TRUE;
                    118: 
                    119: time_t         progress_interval;
                    120: 
                    121: RingBuf                outbuf;
                    122: #if defined(RINGBUF_EVENT)
                    123:        #define         outbuf_empty outbuf.empty_event
                    124: #else
                    125:        xpevent_t       outbuf_empty;
                    126: #endif
                    127: unsigned       outbuf_drain_timeout;
                    128: long           outbuf_size;
                    129: 
                    130: unsigned       flows=0;
                    131: unsigned       select_errors=0;
                    132: 
                    133: #ifdef __unix__
                    134: void resetterm(void)
                    135: {
                    136:        tcsetattr(STDOUT_FILENO, TCSADRAIN, &origterm);
                    137: }
                    138: #endif
                    139: 
                    140: #ifdef _WINSOCKAPI_
                    141: 
                    142: /* Note: Don't call WSACleanup() or TCP session will close! */
                    143: WSADATA WSAData;       
                    144: 
                    145: static BOOL winsock_startup(void)
                    146: {
                    147:        int             status;             /* Status Code */
                    148: 
                    149:     if((status = WSAStartup(MAKEWORD(1,1), &WSAData))==0) {
                    150:                fprintf(statfp,"%s %s\n",WSAData.szDescription, WSAData.szSystemStatus);
                    151:                return(TRUE);
                    152:        }
                    153: 
                    154:     fprintf(errfp,"!WinSock startup ERROR %d\n", status);
                    155:        return(FALSE);
                    156: }
                    157: 
                    158: #else /* No WINSOCK */
                    159: 
                    160: #define winsock_startup()      (TRUE)  
                    161: 
                    162: #endif
                    163: 
                    164: static int lputs(void* unused, int level, const char* str)
                    165: {
                    166:        FILE*   fp=statfp;
                    167: 
                    168: #if defined(_WIN32) && defined(_DEBUG)
                    169:        if(log_level==LOG_DEBUG)
                    170:                OutputDebugString(str);
                    171: #endif
                    172: 
                    173:        if(level>log_level)
                    174:                return 0;
                    175: 
                    176:     if(level<LOG_NOTICE)
                    177:                fp=errfp;
                    178: 
                    179:        if(!newline) {
                    180:                fprintf(fp,"\n");
                    181:                newline=TRUE;
                    182:        }
                    183:        if(level<LOG_NOTICE)
                    184:                return fprintf(fp,"!%s\n",str);
                    185:        else
                    186:                return fprintf(fp,"%s\n",str);
                    187: }
                    188: 
                    189: static int lprintf(int level, const char *fmt, ...)
                    190: {
                    191:        char sbuf[1024];
                    192:        va_list argptr;
                    193: 
                    194:     va_start(argptr,fmt);
                    195:     vsnprintf(sbuf,sizeof(sbuf),fmt,argptr);
                    196:        sbuf[sizeof(sbuf)-1]=0;
                    197:     va_end(argptr);
                    198:     return(lputs(NULL,level,sbuf));
                    199: }
                    200: 
                    201: void break_handler(int type)
                    202: {
                    203:        lprintf(LOG_NOTICE,"-> Aborted Locally (signal: %d)",type);
                    204: 
                    205:        /* Flag to indicate local (as opposed to remote) abort */
                    206:        aborted=TRUE;
                    207: 
                    208:        /* Stop any transfers in progress immediately */
                    209:        xm.cancelled=TRUE;      
                    210:        zm.cancelled=TRUE;
                    211: }
                    212: 
                    213: #if defined(_WIN32)
                    214: BOOL WINAPI ControlHandler(DWORD CtrlType)
                    215: {
                    216:        break_handler((int)CtrlType);
                    217:        return TRUE;
                    218: }
                    219: #endif
                    220: 
                    221: char* dszlog_filename(char* str)
                    222: {
                    223:        char*           p=str;
                    224:        static char     path[MAX_PATH+1];
                    225: 
                    226: #ifdef _WIN32
                    227:        char sfpath[MAX_PATH+1];
                    228:        if(dszlog_short) {
                    229:                SAFECOPY(sfpath,str);
                    230:                GetShortPathName(str,sfpath,sizeof(sfpath));
                    231:                p=sfpath;
                    232:        }
                    233: #endif
                    234: 
                    235:        if(!dszlog_path)
                    236:                p=getfname(p);
                    237: 
                    238:        if(!dszlog_quotes)
                    239:                return(p);
                    240: 
                    241:        SAFEPRINTF(path,"\"%s\"",p);
                    242:        return(path);
                    243: }
                    244: 
                    245: static char *chr(uchar ch)
                    246: {
                    247:        static char str[25];
                    248: 
                    249:        if(mode&ZMODEM) {
                    250:                switch(ch) {
                    251:                        case ZRQINIT:   return("ZRQINIT");
                    252:                        case ZRINIT:    return("ZRINIT");
                    253:                        case ZSINIT:    return("ZSINIT");
                    254:                        case ZACK:              return("ZACK");
                    255:                        case ZFILE:             return("ZFILE");
                    256:                        case ZSKIP:             return("ZSKIP");
                    257:                        case ZNAK:              return("ZNAK");
                    258:                        case ZABORT:    return("ZABORT");
                    259:                        case ZFIN:              return("ZFIN");
                    260:                        case ZRPOS:             return("ZRPOS");
                    261:                        case ZDATA:             return("ZDATA");
                    262:                        case ZEOF:              return("ZEOF");
                    263:                        case ZPAD:              return("ZPAD");
                    264:                        case ZDLE:              return("ZDLE");
                    265:                        case ZDLEE:             return("ZDLEE");
                    266:                        case ZBIN:              return("ZBIN");
                    267:                        case ZHEX:              return("ZHEX");
                    268:                        case ZBIN32:    return("ZBIN32");
                    269:                        case ZRESC:             return("ZRESC");
                    270:                        case ZCRCE:             return("ZCRCE");
                    271:                        case ZCRCG:             return("ZCRCG");
                    272:                        case ZCRCQ:             return("ZCRCQ");
                    273:                        case ZCRCW:             return("ZCRCW");
                    274:                }
                    275:        } else {
                    276:                switch(ch) {
                    277:                        case SOH:       return("SOH");
                    278:                        case STX:       return("STX");
                    279:                        case ETX:       return("ETX");
                    280:                        case EOT:       return("EOT");
                    281:                        case ACK:       return("ACK");
                    282:                        case NAK:       return("NAK");
                    283:                        case CAN:       return("CAN");
                    284:                }
                    285:        }
                    286:        if(ch>=' ' && ch<='~')
                    287:                sprintf(str,"'%c' (%02Xh)",ch,ch);
                    288:        else
                    289:                sprintf(str,"%u (%02Xh)",ch,ch);
                    290:        return(str); 
                    291: }
                    292: 
                    293: void dump(BYTE* buf, int len)
                    294: {
                    295:        char str[128];
                    296:        int i,j;
                    297:        size_t slen=0;
                    298: 
                    299:        slen=sprintf(str,"TX: ");
                    300:        for(i=0;i<len;i+=j) {
                    301:                for(j=0;i+j<len && j<32;j++)
                    302:                        slen+=sprintf(str+slen,"%02X ",buf[i+j]);
                    303:                lprintf(LOG_DEBUG,"%s",str);
                    304:                slen=sprintf(str,"TX: ");
                    305:        }
                    306: }
                    307: 
                    308: void send_telnet_cmd(SOCKET sock, uchar cmd, uchar opt)
                    309: {
                    310:        uchar   buf[3];
                    311:        
                    312:        buf[0]=TELNET_IAC;
                    313:        buf[1]=cmd;
                    314:        buf[2]=opt;
                    315: 
                    316:        if(debug_telnet)
                    317:                lprintf(LOG_DEBUG,"Sending telnet command: %s %s"
                    318:                        ,telnet_cmd_desc(buf[1]),telnet_opt_desc(buf[2]));
                    319: 
                    320:        if(sendsocket(sock,buf,sizeof(buf))!=sizeof(buf) && debug_telnet)
                    321:                lprintf(LOG_ERR,"FAILED");
                    322: }
                    323: 
                    324: #define DEBUG_TELNET FALSE
                    325: 
                    326: /****************************************************************************/
                    327: /* Receive a byte from remote (single-threaded version)                                                */
                    328: /****************************************************************************/
                    329: int recv_byte(void* unused, unsigned timeout)
                    330: {
                    331:        int                     i;
                    332:        long            t;
                    333:        uchar           ch;
                    334:        fd_set          socket_set;
                    335:        time_t          end;
                    336:        struct timeval  tv;
                    337:        static uchar    telnet_cmd;
                    338:        static int              telnet_cmdlen;
                    339: 
                    340:        end=msclock()+(timeout*MSCLOCKS_PER_SEC);
                    341:        while(!terminate) {
                    342: 
                    343:                FD_ZERO(&socket_set);
                    344: #ifdef __unix__
                    345:                if(stdio)
                    346:                        FD_SET(STDIN_FILENO,&socket_set);
                    347:                else
                    348: #endif
                    349:                        FD_SET(sock,&socket_set);
                    350:                if((t=end-msclock())<0) t=0;
                    351:                tv.tv_sec=t/MSCLOCKS_PER_SEC;
                    352:                tv.tv_usec=0;
                    353: 
                    354:                if((i=select(sock+1,&socket_set,NULL,NULL,&tv))<1) {
                    355:                        if(i==SOCKET_ERROR) {
                    356:                                lprintf(LOG_ERR,"ERROR %d selecting socket", ERROR_VALUE);
                    357:                        }
                    358:                        if(timeout)
                    359:                                lprintf(LOG_WARNING,"Receive timeout (%u seconds)", timeout);
                    360:                        return(NOINP);
                    361:                }
                    362:                
                    363: #ifdef __unix__
                    364:                if(stdio)
                    365:                        i=read(STDIN_FILENO,&ch,sizeof(ch));
                    366:                else
                    367: #endif
                    368:                        i=recv(sock,&ch,sizeof(ch),0);
                    369: 
                    370:                if(i!=sizeof(ch)) {
                    371:                        if(i==0) {
                    372:                                lprintf(LOG_WARNING,"Socket Disconnected");
                    373:                        } else
                    374:                                lprintf(LOG_ERR,"recv error %d (%d)",i,ERROR_VALUE);
                    375:                        return(NOINP); 
                    376:                }
                    377: 
                    378:                if(telnet) {
                    379:                        if(ch==TELNET_IAC) {
                    380: #if DEBUG_TELNET
                    381:                                lprintf(LOG_DEBUG,"T<%s> ",telnet_cmd_desc(ch));
                    382: #endif
                    383:                                if(telnet_cmdlen==0) {
                    384:                                        telnet_cmdlen=1;
                    385:                                        continue;
                    386:                                }
                    387:                                if(telnet_cmdlen==1) {
                    388:                                        telnet_cmdlen=0;
                    389:                                        if(debug_rx)
                    390:                                                lprintf(LOG_DEBUG,"RX: %s",chr(TELNET_IAC));
                    391:                                        return(TELNET_IAC);
                    392:                                }
                    393:                        }
                    394:                        if(telnet_cmdlen) {
                    395:                                telnet_cmdlen++;
                    396: #if DEBUG_TELNET
                    397:                                if(telnet_cmdlen==2)
                    398:                                        lprintf(LOG_DEBUG,"T<%s> ",telnet_cmd_desc(ch));
                    399:                                else
                    400:                                        lprintf(LOG_DEBUG,"T<%s> ",telnet_opt_desc(ch));
                    401: #endif
                    402:                                if(debug_telnet && telnet_cmdlen==3)
                    403:                                        lprintf(LOG_DEBUG,"Received telnet command: %s %s"
                    404:                                                ,telnet_cmd_desc(telnet_cmd),telnet_opt_desc(ch));
                    405:                                if(telnet_cmdlen==3 && telnet_cmd==TELNET_DO)
                    406:                                        send_telnet_cmd(sock, TELNET_WILL,ch);
                    407:        /*
                    408:                                else if(telnet_cmdlen==3 && telnet_cmd==TELNET_WILL)
                    409:                                        send_telnet_cmd(sock, TELNET_DO,ch);
                    410:        */
                    411:                                telnet_cmd=ch;
                    412:                                if((telnet_cmdlen==2 && ch<TELNET_WILL) || telnet_cmdlen>2) {
                    413:                                        telnet_cmdlen=0;
                    414:                                        /* Code disabled.  Why?  ToDo */
                    415:                                        /* break; */
                    416:                                }
                    417:                                continue;
                    418:                        }
                    419:                }
                    420:                if(debug_rx)
                    421:                        lprintf(LOG_DEBUG,"RX: %s",chr(ch));
                    422:                return(ch);
                    423:        }
                    424: 
                    425:        return(NOINP);
                    426: }
                    427: 
                    428: #if !SINGLE_THREADED
                    429: /*************************/
                    430: /* Send a byte to remote */
                    431: /*************************/
                    432: int send_byte(void* unused, uchar ch, unsigned timeout)
                    433: {
                    434:        uchar           buf[2] = { TELNET_IAC, TELNET_IAC };
                    435:        unsigned        len=1;
                    436:        DWORD           result;
                    437: 
                    438:        if(telnet && ch==TELNET_IAC)    /* escape IAC char */
                    439:                len=2;
                    440:        else
                    441:                buf[0]=ch;
                    442: 
                    443:        if(RingBufFree(&outbuf)<len) {
                    444:                fprintf(statfp,"FLOW");
                    445:                flows++;
                    446:                result=WaitForEvent(outbuf_empty,timeout*1000);
                    447:                fprintf(statfp,"\b\b\b\b    \b\b\b\b");
                    448:                if(result!=WAIT_OBJECT_0) {
                    449:                        fprintf(statfp
                    450:                                ,"\n!TIMEOUT (%d) waiting for output buffer to flush (%u seconds, %u bytes)\n"
                    451:                                ,result, timeout, RingBufFull(&outbuf));
                    452:                        newline=TRUE;
                    453:                        if(RingBufFree(&outbuf)<len)
                    454:                                return(-1);
                    455:                }
                    456:        }
                    457: 
                    458:        RingBufWrite(&outbuf,buf,len);
                    459: #if !defined(RINGBUF_EVENT)
                    460:        ResetEvent(outbuf_empty);
                    461: #endif
                    462: 
                    463: #if 0
                    464:        if(debug_tx)
                    465:                lprintf(LOG_DEBUG,"TX: %s",chr(ch));
                    466: #endif
                    467:        return(0);
                    468: }
                    469: 
                    470: #else
                    471: 
                    472: /*************************/
                    473: /* Send a byte to remote */
                    474: /*************************/
                    475: int send_byte(void* unused, uchar ch, unsigned timeout)
                    476: {
                    477:        uchar           buf[2] = { TELNET_IAC, TELNET_IAC };
                    478:        int                     len=1;
                    479:        int                     i;
                    480:        fd_set          socket_set;
                    481:        struct timeval  tv;
                    482: 
                    483:        FD_ZERO(&socket_set);
                    484: #ifdef __unix__
                    485:        if(stdio)
                    486:                FD_SET(STDOUT_FILENO,&socket_set);
                    487:        else
                    488: #endif
                    489:                FD_SET(sock,&socket_set);
                    490:        tv.tv_sec=timeout;
                    491:        tv.tv_usec=0;
                    492: 
                    493:        if(select(sock+1,NULL,&socket_set,NULL,&tv)<1)
                    494:                return(ERROR_VALUE);
                    495: 
                    496:        if(telnet && ch==TELNET_IAC)    /* escape IAC char */
                    497:                len=2;
                    498:        else
                    499:                buf[0]=ch;
                    500: 
                    501: #ifdef __unix__
                    502:        if(stdio)
                    503:                i=write(STDOUT_FILENO,buf,len);
                    504:        else
                    505: #endif
                    506:                i=sendsocket(sock,buf,len);
                    507:        
                    508:        if(i==len) {
                    509:                if(debug_tx)
                    510:                        lprintf(LOG_DEBUG,"TX: %s",chr(ch));
                    511:                return(0);
                    512:        }
                    513: 
                    514:        return(-1);
                    515: }
                    516: #endif
                    517: 
                    518: static void output_thread(void* arg)
                    519: {
                    520:        char            stats[128];
                    521:     BYTE               buf[MAX_OUTBUF_SIZE];
                    522:        int                     i;
                    523:     ulong              avail;
                    524:        ulong           total_sent=0;
                    525:        ulong           total_pkts=0;
                    526:        ulong           short_sends=0;
                    527:     ulong              bufbot=0;
                    528:     ulong              buftop=0;
                    529:        fd_set          socket_set;
                    530:        struct timeval tv;
                    531: 
                    532: #if 0 /* def _DEBUG */
                    533:        fprintf(statfp,"output thread started\n");
                    534: #endif
                    535: 
                    536:        while(sock!=INVALID_SOCKET && !terminate) {
                    537: 
                    538:                if(bufbot==buftop)
                    539:                avail=RingBufFull(&outbuf);
                    540:                else
                    541:                avail=buftop-bufbot;
                    542: 
                    543:                if(!avail) {
                    544: #if !defined(RINGBUF_EVENT)
                    545:                        SetEvent(outbuf_empty);
                    546: #endif
                    547:                        sem_wait(&outbuf.sem);
                    548:                        if(outbuf.highwater_mark)
                    549:                                sem_trywait_block(&outbuf.highwater_sem,outbuf_drain_timeout);
                    550:                        continue; 
                    551:                }
                    552: 
                    553:                /* Check socket for writability (using select) */
                    554:                tv.tv_sec=0;
                    555:                tv.tv_usec=1000;
                    556: 
                    557:                FD_ZERO(&socket_set);
                    558: #ifdef __unix__
                    559:                if(stdio)
                    560:                        FD_SET(STDOUT_FILENO,&socket_set);
                    561:                else
                    562: #endif
                    563:                        FD_SET(sock,&socket_set);
                    564: 
                    565:                i=select(sock+1,NULL,&socket_set,NULL,&tv);
                    566:                if(i==SOCKET_ERROR) {
                    567:                        lprintf(LOG_ERR,"ERROR %d selecting socket %u for send"
                    568:                                ,ERROR_VALUE,sock);
                    569:                        break;
                    570:                }
                    571:                if(i<1) {
                    572:                        select_errors++;
                    573:                        continue;
                    574:                }
                    575: 
                    576:         if(bufbot==buftop) { /* linear buf empty, read from ring buf */
                    577:             if(avail>sizeof(buf)) {
                    578:                 lprintf(LOG_ERR,"Insufficient linear output buffer (%lu > %lu)"
                    579:                                        ,avail, sizeof(buf));
                    580:                 avail=sizeof(buf);
                    581:             }
                    582:             buftop=RingBufRead(&outbuf, buf, avail);
                    583:             bufbot=0;
                    584:         }
                    585: #ifdef __unix__
                    586:                if(stdio)
                    587:                        i=write(STDOUT_FILENO, (char*)buf+bufbot, buftop-bufbot);
                    588:                else
                    589: #endif
                    590:                        i=sendsocket(sock, (char*)buf+bufbot, buftop-bufbot);
                    591:                if(i==SOCKET_ERROR) {
                    592:                if(ERROR_VALUE == ENOTSOCK)
                    593:                 lprintf(LOG_ERR,"client socket closed on send");
                    594:             else if(ERROR_VALUE==ECONNRESET) 
                    595:                                lprintf(LOG_ERR,"connection reset by peer on send");
                    596:             else if(ERROR_VALUE==ECONNABORTED) 
                    597:                                lprintf(LOG_ERR,"connection aborted by peer on send");
                    598:                        else
                    599:                                lprintf(LOG_ERR,"ERROR %d sending on socket %d"
                    600:                        ,ERROR_VALUE, sock);
                    601:                        break;
                    602:                }
                    603: 
                    604:                if(debug_tx)
                    605:                        dump(buf+bufbot,i);
                    606: 
                    607:                if(i!=(int)(buftop-bufbot)) {
                    608:                        lprintf(LOG_ERR,"Short socket send (%u instead of %u)"
                    609:                                ,i ,buftop-bufbot);
                    610:                        short_sends++;
                    611:                }
                    612:                bufbot+=i;
                    613:                total_sent+=i;
                    614:                total_pkts++;
                    615:     }
                    616: 
                    617:        if(total_sent)
                    618:                sprintf(stats,"(sent %lu bytes in %lu blocks, %lu average, %lu short, %lu errors)"
                    619:                        ,total_sent, total_pkts, total_sent/total_pkts, short_sends, select_errors);
                    620:        else
                    621:                stats[0]=0;
                    622: 
                    623:        lprintf(LOG_DEBUG,"output thread terminated\n%s", stats);
                    624: }
                    625: 
                    626: BOOL is_connected(void* unused)
                    627: {
                    628:        return socket_check(sock,NULL,NULL,0);
                    629: }
                    630: 
                    631: BOOL data_waiting(void* unused, unsigned timeout)
                    632: {
                    633:        BOOL rd;
                    634: 
                    635:        if(!socket_check(sock,&rd,NULL,timeout))
                    636:                return(FALSE);
                    637:        return(rd);
                    638: }
                    639: 
                    640: /****************************************************************************/
                    641: /* Returns the number of blocks required to send len bytes                                     */
                    642: /****************************************************************************/
                    643: unsigned num_blocks(ulong len, unsigned block_size)
                    644: {
                    645:        ulong blocks;
                    646: 
                    647:        blocks=len/block_size;
                    648:        if(len%block_size)
                    649:                blocks++;
                    650:        return(blocks);
                    651: }
                    652: 
                    653: /************************************************/
                    654: /* Dump the current block contents - for debug  */
                    655: /************************************************/
                    656: void dump_block(long block_size)
                    657: {
                    658:        long l;
                    659: 
                    660:        for(l=0;l<block_size;l++)
                    661:                fprintf(statfp,"%02X  ",block[l]);
                    662:        fprintf(statfp,"\n");
                    663: }
                    664: 
                    665: void xmodem_progress(void* unused, unsigned block_num, ulong offset, ulong fsize, time_t start)
                    666: {
                    667:        unsigned        cps;
                    668:        unsigned        total_blocks;
                    669:        long            l;
                    670:        long            t;
                    671:        time_t          now;
                    672:        static time_t last_progress;
                    673: 
                    674:        now=time(NULL);
                    675:        if(now-last_progress>=progress_interval || offset >= fsize || newline) {
                    676:                t=now-start;
                    677:                if(t<=0)
                    678:                        t=1;
                    679:                if((cps=offset/t)==0)
                    680:                        cps=1;                  /* cps so far */
                    681:                l=fsize/cps;            /* total transfer est time */
                    682:                l-=t;                           /* now, it's est time left */
                    683:                if(l<0) l=0;
                    684:                if(mode&SEND) {
                    685:                        total_blocks=num_blocks(fsize,xm.block_size);
                    686:                        fprintf(statfp,"\rBlock (%lu%s): %lu/%lu  Byte: %lu  "
                    687:                                "Time: %lu:%02lu/%lu:%02lu  %u cps  %lu%% "
                    688:                                ,xm.block_size%1024L ? xm.block_size: xm.block_size/1024L
                    689:                                ,xm.block_size%1024L ? "" : "K"
                    690:                                ,block_num
                    691:                                ,total_blocks
                    692:                                ,offset
                    693:                                ,t/60L
                    694:                                ,t%60L
                    695:                                ,l/60L
                    696:                                ,l%60L
                    697:                                ,cps
                    698:                                ,(long)(((float)offset/(float)fsize)*100.0)
                    699:                                );
                    700:                } else if(mode&YMODEM) {
                    701:                        fprintf(statfp,"\rBlock (%lu%s): %lu  Byte: %lu  "
                    702:                                "Time: %lu:%02lu/%lu:%02lu  %u cps  %lu%% "
                    703:                                ,xm.block_size%1024L ? xm.block_size: xm.block_size/1024L
                    704:                                ,xm.block_size%1024L ? "" : "K"
                    705:                                ,block_num
                    706:                                ,offset
                    707:                                ,t/60L
                    708:                                ,t%60L
                    709:                                ,l/60L
                    710:                                ,l%60L
                    711:                                ,cps
                    712:                                ,(long)(((float)offset/(float)fsize)*100.0)
                    713:                                );
                    714:                } else { /* XModem receive */
                    715:                        fprintf(statfp,"\rBlock (%lu%s): %lu  Byte: %lu  "
                    716:                                "Time: %lu:%02lu  %u cps "
                    717:                                ,xm.block_size%1024L ? xm.block_size: xm.block_size/1024L
                    718:                                ,xm.block_size%1024L ? "" : "K"
                    719:                                ,block_num
                    720:                                ,offset
                    721:                                ,t/60L
                    722:                                ,t%60L
                    723:                                ,cps
                    724:                                );
                    725:                }
                    726:                newline=FALSE;
                    727:                last_progress=now;
                    728:        }
                    729: }
                    730: 
                    731: /* 
                    732:  * show the progress of the transfer like this:
                    733:  * zmtx: sending file "garbage" 4096 bytes ( 20%)
                    734:  */
                    735: void zmodem_progress(void* cbdata, ulong current_pos)
                    736: {
                    737:        unsigned        cps;
                    738:        long            l;
                    739:        long            t;
                    740:        time_t          now;
                    741:        static time_t last_progress;
                    742: 
                    743:        now=time(NULL);
                    744:        if(now-last_progress>=progress_interval || current_pos >= zm.current_file_size || newline) {
                    745:                t=now-zm.transfer_start_time;
                    746:                if(t<=0)
                    747:                        t=1;
                    748:                if(zm.transfer_start_pos>current_pos)
                    749:                        zm.transfer_start_pos=0;
                    750:                if((cps=(current_pos-zm.transfer_start_pos)/t)==0)
                    751:                        cps=1;          /* cps so far */
                    752:                l=zm.current_file_size/cps;     /* total transfer est time */
                    753:                l-=t;                   /* now, it's est time left */
                    754:                if(l<0) l=0;
                    755:                fprintf(statfp,"\rKByte: %lu/%lu  %u/CRC-%u  "
                    756:                        "Time: %lu:%02lu/%lu:%02lu  %u cps  %lu%% "
                    757:                        ,current_pos/1024
                    758:                        ,zm.current_file_size/1024
                    759:                        ,zm.block_size
                    760:                        ,mode&RECV ? (zm.receive_32bit_data ? 32:16) : 
                    761:                                (zm.can_fcs_32 && !zm.want_fcs_16) ? 32:16
                    762:                        ,t/60L
                    763:                        ,t%60L
                    764:                        ,l/60L
                    765:                        ,l%60L
                    766:                        ,cps
                    767:                        ,(long)(((float)current_pos/(float)zm.current_file_size)*100.0)
                    768:                        );
                    769:                newline=FALSE;
                    770:                last_progress=now;
                    771:        }
                    772: }
                    773: 
                    774: static int send_files(char** fname, uint fnames)
                    775: {
                    776:        char    path[MAX_PATH+1];
                    777:        int             i;
                    778:        uint    errors;
                    779:        uint    fnum;
                    780:        uint    cps;
                    781:        glob_t  g;
                    782:        int             gi;
                    783:        BOOL    success=TRUE;
                    784:        long    fsize;
                    785:        ulong   sent_bytes;
                    786:        ulong   total_bytes=0;
                    787:        time_t  t,startfile;
                    788:        time_t  startall;
                    789:        FILE*   fp;
                    790: 
                    791:        startall=time(NULL);
                    792: 
                    793:        /****************************************************/
                    794:        /* Search through all to find total files and bytes */
                    795:        /****************************************************/
                    796:        for(fnum=0;fnum<fnames;fnum++) {
                    797:                if(glob(fname[fnum],0,NULL,&g)) {
                    798:                        lprintf(LOG_WARNING,"%s not found",fname[fnum]);
                    799:                        continue;
                    800:                }
                    801:                for(i=0;i<(int)g.gl_pathc;i++) {
                    802:                        if(isdir(g.gl_pathv[i]))
                    803:                                continue;
                    804:                        xm.total_files++;
                    805:                        xm.total_bytes+=flength(g.gl_pathv[i]);
                    806:                } 
                    807:                globfree(&g);
                    808:        }
                    809: 
                    810:        if(xm.total_files<1) {
                    811:                lprintf(LOG_ERR,"No files to send");
                    812:                return(-1);
                    813:        }
                    814:        if(xm.total_files>1)
                    815:                lprintf(LOG_INFO,"Sending %u files (%lu KB total)"
                    816:                        ,xm.total_files,xm.total_bytes/1024);
                    817: 
                    818:        zm.files_remaining = xm.total_files;
                    819:        zm.bytes_remaining = xm.total_bytes;
                    820: 
                    821:        /***********************************************/
                    822:        /* Send every file matching names or filespecs */
                    823:        /***********************************************/
                    824:        for(fnum=0;fnum<fnames;fnum++) {
                    825:                if(glob(fname[fnum],0,NULL,&g)) {
                    826:                        lprintf(LOG_WARNING,"%s not found",fname[fnum]);
                    827:                        continue;
                    828:                }
                    829:                for(gi=0;gi<(int)g.gl_pathc;gi++) {
                    830:                        SAFECOPY(path,g.gl_pathv[gi]);
                    831:                        if(isdir(path))
                    832:                                continue;
                    833: 
                    834:                        if((fp=fnopen(NULL,path,O_RDONLY|O_BINARY))==NULL
                    835:                                && (fp=fopen(path,"rb"))==NULL) {
                    836:                                lprintf(LOG_ERR,"Error %d opening %s for read",errno,path);
                    837:                                continue;
                    838:                        }
                    839:                        setvbuf(fp,NULL,_IOFBF,0x10000);
                    840: 
                    841:                        fsize=filelength(fileno(fp));
                    842: 
                    843:                        errors=0;
                    844:                        success=FALSE;
                    845:                        startfile=time(NULL);
                    846: 
                    847:                        lprintf(LOG_INFO,"Sending %s (%lu KB) via %s"
                    848:                                ,path,fsize/1024
                    849:                                ,mode&XMODEM ? "Xmodem" : mode&YMODEM ? "Ymodem" : "Zmodem");
                    850: 
                    851:                        if(mode&ZMODEM)
                    852:                                        success=zmodem_send_file(&zm, path, fp, /* ZRQINIT? */fnum==0, &startfile, &sent_bytes);
                    853:                        else    /* X/Ymodem */
                    854:                                        success=xmodem_send_file(&xm, path, fp, &startfile, &sent_bytes);
                    855: 
                    856:                        fclose(fp);
                    857: 
                    858:                        if((t=time(NULL)-startfile)<=0) 
                    859:                                t=1;
                    860:                        if((cps=sent_bytes/t)==0)
                    861:                                cps=1;
                    862:                        if(success) {
                    863:                                xm.sent_files++;
                    864:                                xm.sent_bytes+=fsize;
                    865:                                lprintf(LOG_INFO,"Successful - Time: %lu:%02lu  CPS: %lu"
                    866:                                                ,t/60,t%60,cps);
                    867: 
                    868:                                if(xm.total_files-xm.sent_files)
                    869:                                        lprintf(LOG_INFO,"Remaining - Time: %lu:%02lu  Files: %u  KBytes: %lu"
                    870:                                                ,((xm.total_bytes-xm.sent_bytes)/cps)/60
                    871:                                                ,((xm.total_bytes-xm.sent_bytes)/cps)%60
                    872:                                                ,xm.total_files-xm.sent_files
                    873:                                                ,(xm.total_bytes-xm.sent_bytes)/1024
                    874:                                                );
                    875:                        } else
                    876:                                lprintf(LOG_WARNING,"File Transfer %s", aborted ? "Aborted" : "Failure");
                    877: 
                    878:                        /* DSZLOG entry */
                    879:                        if(logfp) {
                    880:                                lprintf(LOG_DEBUG,"Updating DSZLOG: %s", dszlog);
                    881:                                fprintf(logfp,"%c %7lu %5u bps %6lu cps %3u errors %5u %4u "
                    882:                                        "%s -1\n"
                    883:                                        ,success ? (mode&ZMODEM ? 'z':'S') 
                    884:                                                : (mode&ZMODEM && zm.file_skipped) ? 's' 
                    885:                                                : 'E'
                    886:                                        ,sent_bytes
                    887:                                        ,115200 /* baud */
                    888:                                        ,cps
                    889:                                        ,mode&ZMODEM ? zm.errors : xm.errors
                    890:                                        ,flows
                    891:                                        ,mode&ZMODEM ? zm.block_size : xm.block_size
                    892:                                        ,dszlog_filename(path)); 
                    893:                                fflush(logfp);
                    894:                        }
                    895:                        total_bytes += sent_bytes;
                    896: 
                    897:                        if(aborted) {
                    898:                                xm.cancelled=FALSE;
                    899:                                xmodem_cancel(&xm);
                    900:                                break;
                    901:                        }
                    902: 
                    903:                        if(xm.cancelled || zm.cancelled)
                    904:                                break;
                    905: 
                    906:                } /* while(gi<(int)g.gl_pathc) */
                    907: 
                    908:                if(gi<(int)g.gl_pathc)/* error occurred */
                    909:                        break;
                    910:        }
                    911: 
                    912:        if(mode&ZMODEM && !zm.cancelled && is_connected(NULL))
                    913:                zmodem_get_zfin(&zm);
                    914: 
                    915:        if(fnum<fnames) /* error occurred */
                    916:                return(-1);
                    917: 
                    918:        if(!success)
                    919:                return(-1);
                    920: 
                    921:        if(mode&XMODEM)
                    922:                return(0);
                    923:        if(mode&YMODEM) {
                    924: 
                    925:                if(xmodem_get_mode(&xm)) {
                    926: 
                    927:                        lprintf(LOG_INFO,"Sending Ymodem termination block");
                    928: 
                    929:                        memset(block,0,128);    /* send short block for terminator */
                    930:                        xmodem_put_block(&xm, block, 128 /* block_size */, 0 /* block_num */);
                    931:                        if(!xmodem_get_ack(&xm,6,0)) {
                    932:                                lprintf(LOG_WARNING,"Failed to receive ACK after terminating block"); 
                    933:                        } 
                    934:                }
                    935:        }
                    936:        if(xm.total_files>1) {
                    937:                t=time(NULL)-startall;
                    938:                if(!t) t=1;
                    939:                lprintf(LOG_INFO,"Overall - Time %02lu:%02lu  KBytes: %lu  CPS: %lu"
                    940:                        ,t/60,t%60,total_bytes/1024,total_bytes/t); 
                    941:        }
                    942:        return(0);      /* success */
                    943: }
                    944: 
                    945: static int receive_files(char** fname_list, int fnames)
                    946: {
                    947:        char    str[MAX_PATH+1];
                    948:        char    fname[MAX_PATH+1];
                    949:        int             i;
                    950:        int             fnum=0;
                    951:        uint    errors;
                    952:        uint    total_files=0;
                    953:        uint    cps;
                    954:        uint    wr;
                    955:        BOOL    success=FALSE;
                    956:        long    fmode;
                    957:        long    serial_num=-1;
                    958:        ulong   file_bytes=0,file_bytes_left=0;
                    959:        ulong   total_bytes=0;
                    960:        FILE*   fp;
                    961:        time_t  t,startfile,ftime;
                    962: 
                    963:        if(fnames>1)
                    964:                lprintf(LOG_INFO,"Receiving %u files",fnames);
                    965: 
                    966:        outbuf.highwater_mark=0;        /* don't delay ACK/NAK transmits */
                    967: 
                    968:        /* Purge input buffer */
                    969:        while(is_connected(NULL) && (i=recv_byte(NULL,0))!=NOINP)
                    970:                lprintf(LOG_WARNING,"Throwing out received: %s",chr((uchar)i));
                    971: 
                    972:        while(is_connected(NULL)) {
                    973:                if(mode&XMODEM) {
                    974:                        SAFECOPY(str,fname_list[0]);    /* we'll have at least one fname */
                    975:                        file_bytes=file_bytes_left=0x7fffffff;
                    976:                }
                    977: 
                    978:                else {
                    979:                        if(mode&YMODEM) {
                    980:                                lprintf(LOG_INFO,"Fetching Ymodem header block");
                    981:                                for(errors=0;errors<=xm.max_errors && !xm.cancelled;errors++) {
                    982:                                        if(errors>(xm.max_errors/2) && mode&CRC && !(mode&GMODE))
                    983:                                                mode&=~CRC;
                    984:                                        xmodem_put_nak(&xm, /* expected_block: */ 0);
                    985:                                        if(xmodem_get_block(&xm, block, /* expected_block: */ 0) == 0) {
                    986:                                                send_byte(NULL,ACK,10);
                    987:                                                break; 
                    988:                                        } 
                    989:                                }
                    990:                                if(errors>=xm.max_errors || xm.cancelled) {
                    991:                                        lprintf(LOG_ERR,"Error fetching Ymodem header block");
                    992:                                        xmodem_cancel(&xm);
                    993:                                        return(1); 
                    994:                                }
                    995:                                if(!block[0]) {
                    996:                                        lprintf(LOG_INFO,"Received Ymodem termination block");
                    997:                                        return(0); 
                    998:                                }
                    999:                                file_bytes=ftime=total_files=total_bytes=0;
                   1000:                                i=sscanf(block+strlen(block)+1,"%ld %lo %lo %lo %d %ld"
                   1001:                                        ,&file_bytes                    /* file size (decimal) */
                   1002:                                        ,&ftime                                 /* file time (octal unix format) */
                   1003:                                        ,&fmode                                 /* file mode (not used) */
                   1004:                                        ,&serial_num                    /* program serial number */
                   1005:                                        ,&total_files                   /* remaining files to be sent */
                   1006:                                        ,&total_bytes                   /* remaining bytes to be sent */
                   1007:                                        );
                   1008:                                lprintf(LOG_DEBUG,"Ymodem header (%u fields): %s", i, block+strlen(block)+1);
                   1009:                                SAFECOPY(fname,block);
                   1010: 
                   1011:                        } else {        /* Zmodem */
                   1012:                                lprintf(LOG_INFO,"Waiting for Zmodem sender...");
                   1013: 
                   1014:                                i=zmodem_recv_init(&zm);
                   1015: 
                   1016:                                if(zm.cancelled)
                   1017:                                        return(1);
                   1018:                                if(i<0)
                   1019:                                        return(-1);
                   1020:                                switch(i) {
                   1021:                                        case ZFILE:
                   1022:                                                SAFECOPY(fname,zm.current_file_name);
                   1023:                                                file_bytes = zm.current_file_size;
                   1024:                                                ftime = zm.current_file_time;
                   1025:                                                total_files = zm.files_remaining;
                   1026:                                                total_bytes = zm.bytes_remaining;
                   1027:                                                break;
                   1028:                                        case ZFIN:
                   1029:                                        case ZCOMPL:
                   1030:                                                return(!success);
                   1031:                                        default:
                   1032:                                                return(-1);
                   1033:                                }
                   1034:                        }
                   1035: 
                   1036:                        if(!file_bytes)
                   1037:                                file_bytes=0x7fffffff;
                   1038:                        file_bytes_left=file_bytes;
                   1039:                        if(!total_files)
                   1040:                                total_files=fnames-fnum;
                   1041:                        if(!total_files)
                   1042:                                total_files=1;
                   1043:                        if(total_bytes<file_bytes)
                   1044:                                total_bytes=file_bytes;
                   1045: 
                   1046:                        lprintf(LOG_DEBUG,"Incoming filename: %.64s ",fname);
                   1047: 
                   1048:                        if(mode&RECVDIR)
                   1049:                                sprintf(str,"%s%s",fname_list[0],getfname(fname));
                   1050:                        else {
                   1051:                                SAFECOPY(str,getfname(fname));
                   1052:                                for(i=0;i<fnames;i++) {
                   1053:                                        if(!fname_list[i][0])   /* name blank or already used */
                   1054:                                                continue;
                   1055:                                        if(!stricmp(getfname(fname_list[i]),str)) {
                   1056:                                                SAFECOPY(str,fname_list[i]);
                   1057:                                                fname_list[i][0]=0;
                   1058:                                                break; 
                   1059:                                        } 
                   1060:                                }
                   1061:                                if(i==fnames) {                                 /* Not found in list */
                   1062:                                        if(fnames)
                   1063:                                                fprintf(statfp," - Not in receive list!");
                   1064:                                        if(!fnames || fnum>=fnames || !fname_list[fnum][0])
                   1065:                                                SAFECOPY(str,getfname(fname));  /* worst case */
                   1066:                                        else {
                   1067:                                                SAFECOPY(str,fname_list[fnum]);
                   1068:                                                fname_list[fnum][0]=0; 
                   1069:                                        } 
                   1070:                                } 
                   1071:                        }
                   1072:                        fprintf(statfp,"File size: %lu bytes\n", file_bytes);
                   1073:                        if(total_files>1)
                   1074:                                fprintf(statfp,"Remaining: %lu bytes in %u files\n", total_bytes, total_files);
                   1075:                }
                   1076: 
                   1077:                lprintf(LOG_DEBUG,"Receiving: %.64s ",str);
                   1078: 
                   1079:                fnum++;
                   1080: 
                   1081:                if(!(mode&RECVDIR) && fnames && fnum>fnames) {
                   1082:                        lprintf(LOG_WARNING,"Attempt to send more files than specified");
                   1083:                        xmodem_cancel(&xm);
                   1084:                        break; 
                   1085:                }
                   1086: 
                   1087:                if(fexistcase(str) && !(mode&OVERWRITE)) {
                   1088:                        lprintf(LOG_WARNING,"%s already exists",str);
                   1089:                        if(mode&ZMODEM) {
                   1090:                                zmodem_send_zskip(&zm);
                   1091:                                continue;
                   1092:                        }
                   1093:                        xmodem_cancel(&xm);
                   1094:                        return(1); 
                   1095:                }
                   1096:                if((fp=fnopen(NULL,str,O_WRONLY|O_CREAT|O_TRUNC|O_BINARY))==NULL
                   1097:                        && (fp=fopen(str,"wb"))==NULL) {
                   1098:                        lprintf(LOG_ERR,"Error %d creating %s",errno,str);
                   1099:                        if(mode&ZMODEM) {
                   1100:                                zmodem_send_zskip(&zm);
                   1101:                                continue;
                   1102:                        }
                   1103:                        xmodem_cancel(&xm);
                   1104:                        return(1); 
                   1105:                }
                   1106: 
                   1107:                if(mode&XMODEM)
                   1108:                        lprintf(LOG_INFO,"Receiving %s via Xmodem %s"
                   1109:                                ,str
                   1110:                                ,mode&CRC ? "CRC-16":"Checksum");
                   1111:                else
                   1112:                        lprintf(LOG_INFO,"Receiving %s (%lu KB) via %s %s"
                   1113:                                ,str
                   1114:                                ,file_bytes/1024
                   1115:                                ,mode&YMODEM ? mode&GMODE ? "Ymodem-G" : "Ymodem" :"Zmodem"
                   1116:                                ,mode&ZMODEM ? "" : (mode&CRC ? "CRC-16" : "Checksum"));
                   1117: 
                   1118:                startfile=time(NULL);
                   1119:                success=FALSE;
                   1120:                if(mode&ZMODEM) {
                   1121: 
                   1122:                        errors=zmodem_recv_file_data(&zm,fp,0);
                   1123: 
                   1124:                        /*
                   1125:                         * wait for the eof header
                   1126:                         */
                   1127: 
                   1128:                        for(;errors<=zm.max_errors && !success && !zm.cancelled; errors++) {
                   1129:                                if(zmodem_recv_header_and_check(&zm))
                   1130:                                        success=TRUE;
                   1131:                        } 
                   1132: 
                   1133:                } else {
                   1134:                        errors=0;
                   1135:                        block_num=1;
                   1136:                        xmodem_put_nak(&xm, block_num);
                   1137:                        while(is_connected(NULL)) {
                   1138:                                xmodem_progress(NULL,block_num,ftell(fp),file_bytes,startfile);
                   1139:                                i=xmodem_get_block(&xm, block, block_num);      
                   1140: 
                   1141:                                if(i!=0) {
                   1142:                                        if(i==EOT)      {               /* end of transfer */
                   1143:                                                success=TRUE;
                   1144:                                                xmodem_put_ack(&xm);
                   1145:                                                break;
                   1146:                                        }
                   1147:                                        if(i==CAN) {            /* Cancel */
                   1148:                                                xm.cancelled=TRUE;
                   1149:                                                break;
                   1150:                                        }
                   1151: 
                   1152:                                        if(mode&GMODE)
                   1153:                                                return(-1);
                   1154: 
                   1155:                                        if(++errors>=xm.max_errors) {
                   1156:                                                lprintf(LOG_ERR,"Too many errors (%u)",errors);
                   1157:                                                xmodem_cancel(&xm);
                   1158:                                                break;
                   1159:                                        }
                   1160:                                        if(block_num==1 && errors>(xm.max_errors/2) && mode&CRC && !(mode&GMODE))
                   1161:                                                mode&=~CRC;
                   1162:                                        xmodem_put_nak(&xm, block_num);
                   1163:                                        continue;
                   1164:                                }
                   1165:                                if(!(mode&GMODE))
                   1166:                                        send_byte(NULL,ACK,10);
                   1167:                                if(file_bytes_left<=0L)  { /* No more bytes to send */
                   1168:                                        lprintf(LOG_WARNING,"Attempt to send more byte specified in header");
                   1169:                                        break; 
                   1170:                                }
                   1171:                                wr=xm.block_size;
                   1172:                                if(wr>file_bytes_left)
                   1173:                                        wr=file_bytes_left;
                   1174:                                if(fwrite(block,1,wr,fp)!=wr) {
                   1175:                                        lprintf(LOG_ERR,"Error writing %u bytes to file at offset %lu"
                   1176:                                                ,wr,ftell(fp));
                   1177:                                        xmodem_cancel(&xm);
                   1178:                                        return(1); 
                   1179:                                }
                   1180:                                file_bytes_left-=wr; 
                   1181:                                block_num++;
                   1182:                        }
                   1183:                }
                   1184: 
                   1185:                /* Use correct file size */
                   1186:                fflush(fp);
                   1187:                if(file_bytes < (ulong)filelength(fileno(fp))) {
                   1188:                        lprintf(LOG_INFO,"Truncating file to %lu bytes", file_bytes);
                   1189:                        chsize(fileno(fp),file_bytes);
                   1190:                } else
                   1191:                        file_bytes = filelength(fileno(fp));
                   1192:                fclose(fp);
                   1193:                
                   1194:                t=time(NULL)-startfile;
                   1195:                if(!t) t=1;
                   1196:                if(success)
                   1197:                        lprintf(LOG_INFO,"Successful - Time: %lu:%02lu  CPS: %lu"
                   1198:                                ,t/60,t%60,file_bytes/t);       
                   1199:                else
                   1200:                        lprintf(LOG_ERR,"File Transfer %s", aborted ? "Aborted":"Failure");
                   1201: 
                   1202:                if(!(mode&XMODEM) && ftime)
                   1203:                        setfdate(str,ftime); 
                   1204: 
                   1205:                if(logfp) {
                   1206:                        lprintf(LOG_DEBUG,"Updating DSZLOG: %s", dszlog);
                   1207:                        fprintf(logfp,"%c %6lu %5u bps %4lu cps %3u errors %5u %4u "
                   1208:                                "%s %d\n"
                   1209:                                ,success ? (mode&ZMODEM ? 'Z' : 'R') : 'E'
                   1210:                                ,file_bytes
                   1211:                                ,115200 /* baud */
                   1212:                                ,file_bytes/t
                   1213:                                ,errors
                   1214:                                ,flows
                   1215:                                ,mode&ZMODEM ? zm.block_size : xm.block_size
                   1216:                                ,dszlog_filename(str)
                   1217:                                ,serial_num); 
                   1218:                        fflush(logfp);
                   1219:                }
                   1220: 
                   1221:                if(aborted) {
                   1222:                        lprintf(LOG_DEBUG,"Locally aborted, sending cancel to remote");
                   1223:                        if(mode&ZMODEM)
                   1224:                                zmodem_abort_receive(&zm);
                   1225:                        xm.cancelled=FALSE;
                   1226:                        xmodem_cancel(&xm);
                   1227:                        break;
                   1228:                }
                   1229: 
                   1230:                if(mode&XMODEM) /* maximum of one file */
                   1231:                        break;
                   1232:                if((cps=file_bytes/t)==0)
                   1233:                        cps=1;
                   1234:                total_files--;
                   1235:                total_bytes-=file_bytes;
                   1236:                if(total_files>1 && total_bytes)
                   1237:                        lprintf(LOG_INFO,"Remaining - Time: %lu:%02lu  Files: %u  KBytes: %lu"
                   1238:                                ,(total_bytes/cps)/60
                   1239:                                ,(total_bytes/cps)%60
                   1240:                                ,total_files
                   1241:                                ,total_bytes/1024
                   1242:                                );
                   1243:        }
                   1244:        return(!success);       /* 0=success */
                   1245: }
                   1246: 
                   1247: void bail(int code)
                   1248: {
                   1249:        if(logfp!=NULL)
                   1250:                fclose(logfp);
                   1251:        if(pause_on_exit || (pause_on_abend && code!=0)) {
                   1252:                printf("Hit enter to continue...");
                   1253:                getchar();
                   1254:        }
                   1255:        exit(code);
                   1256: }
                   1257: 
                   1258: static const char* usage=
                   1259:        "usage: sexyz <socket> [-opts] <cmd> [file | path | @list]\n"
                   1260:        "\n"
                   1261: #ifdef __unix__
                   1262:        "socket = TCP socket descriptor (leave blank for stdio mode)\n"
                   1263: #else
                   1264:        "socket = TCP socket descriptor\n"
                   1265: #endif
                   1266:        "\n"
                   1267:        "opts   = -y  to overwrite files when receiving\n"
                   1268:        "         -o  disable Zmodem CRC-32 mode (use CRC-16)\n"
                   1269:        "         -s  disable Zmodem streaming (Slow Zmodem)\n"
                   1270:        "         -2  set maximum Zmodem block size to 2K\n"
                   1271:        "         -4  set maximum Zmodem block size to 4K\n"
                   1272:        "         -8  set maximum Zmodem block size to 8K (ZedZap)\n"
                   1273:        "         -!  to pause after abnormal exit (error)\n"
                   1274:        "         -telnet to enable Telnet mode (the default)\n"
                   1275:        "         -rlogin or -ssh or -raw to disable Telnet mode\n"
                   1276:        "\n"
                   1277:        "cmd    = v  to display detailed version information\n"
                   1278:        "         sx to send Xmodem     rx to recv Xmodem\n"
                   1279:        "         sX to send Xmodem-1K  rc to recv Xmodem-CRC\n"
                   1280:        "         sy to send Ymodem     ry to recv Ymodem\n"
                   1281:        "         sY to send Ymodem-1K  rg to recv Ymodem-G\n"
                   1282:        "         sz to send Zmodem     rz to recv Zmodem\n"
                   1283:        "\n"
                   1284:        "file   = filename to send or receive\n"
                   1285:        "path   = directory to receive files into\n"
                   1286:        "list   = name of text file with list of filenames to send or receive\n";
                   1287: 
                   1288: /***************/
                   1289: /* Entry Point */
                   1290: /***************/
                   1291: int main(int argc, char **argv)
                   1292: {
                   1293:        char    str[MAX_PATH+1];
                   1294:        char    fname[MAX_PATH+1];
                   1295:        char    ini_fname[MAX_PATH+1];
                   1296:        char*   p;
                   1297:        char*   arg;
                   1298:        int     i;
                   1299:        int             retval;
                   1300:        uint    fnames=0;
                   1301:        FILE*   fp;
                   1302:        BOOL    tcp_nodelay;
                   1303:        char    compiler[32];
                   1304:        str_list_t fname_list;
                   1305: 
                   1306:        fname_list=strListInit();
                   1307: 
                   1308:        DESCRIBE_COMPILER(compiler);
                   1309: 
                   1310:        errfp=stderr;
                   1311: #ifdef __unix__
                   1312:        statfp=stderr;
                   1313: #else
                   1314:        statfp=stdout;
                   1315: #endif
                   1316: 
                   1317:        sscanf("$Revision: 1.77 $", "%*s %s", revision);
                   1318: 
                   1319:        fprintf(statfp,"\nSynchronet External X/Y/Zmodem  v%s-%s"
                   1320:                "  Copyright %s Rob Swindell\n\n"
                   1321:                ,revision
                   1322:                ,PLATFORM_DESC
                   1323:                ,__DATE__+7
                   1324:                );
                   1325: 
                   1326:        xmodem_init(&xm,NULL,&mode,lputs,xmodem_progress,send_byte,recv_byte,is_connected,NULL);
                   1327:        zmodem_init(&zm,NULL,lputs,zmodem_progress,send_byte,recv_byte,is_connected,NULL,data_waiting);
                   1328: 
                   1329:        /* Generate path/sexyz[.host].ini from path/sexyz[.exe] */
                   1330:        SAFECOPY(str,argv[0]);
                   1331:        p=getfname(str);
                   1332:        SAFECOPY(fname,p);
                   1333:        *p=0;
                   1334:        if((p=getfext(fname))!=NULL) 
                   1335:                *p=0;
                   1336:        strcat(fname,".ini");
                   1337:        
                   1338:        iniFileName(ini_fname,sizeof(ini_fname),str,fname);
                   1339:        if((fp=fopen(ini_fname,"r"))!=NULL)
                   1340:                fprintf(statfp,"Reading %s\n",ini_fname);
                   1341: 
                   1342:        tcp_nodelay                             =iniReadBool(fp,ROOT_SECTION,"TCP_NODELAY",TRUE);
                   1343: 
                   1344:        telnet                                  =iniReadBool(fp,ROOT_SECTION,"Telnet",TRUE);
                   1345:        debug_tx                                =iniReadBool(fp,ROOT_SECTION,"DebugTx",FALSE);
                   1346:        debug_rx                                =iniReadBool(fp,ROOT_SECTION,"DebugRx",FALSE);
                   1347:        debug_telnet                    =iniReadBool(fp,ROOT_SECTION,"DebugTelnet",FALSE);
                   1348: 
                   1349:        pause_on_exit                   =iniReadBool(fp,ROOT_SECTION,"PauseOnExit",FALSE);
                   1350:        pause_on_abend                  =iniReadBool(fp,ROOT_SECTION,"PauseOnAbend",FALSE);
                   1351: 
                   1352:        log_level                               =iniReadLogLevel(fp,ROOT_SECTION,"LogLevel",log_level);
                   1353: 
                   1354:        outbuf.highwater_mark   =iniReadInteger(fp,ROOT_SECTION,"OutbufHighwaterMark",1100);
                   1355:        outbuf_drain_timeout    =iniReadInteger(fp,ROOT_SECTION,"OutbufDrainTimeout",10);
                   1356:        outbuf_size                             =iniReadInteger(fp,ROOT_SECTION,"OutbufSize",16*1024);
                   1357: 
                   1358:        progress_interval               =iniReadInteger(fp,ROOT_SECTION,"ProgressInterval",1);
                   1359: 
                   1360:        if(iniReadBool(fp,ROOT_SECTION,"Debug",FALSE))
                   1361:                log_level=LOG_DEBUG;
                   1362: 
                   1363:        xm.send_timeout                 =iniReadInteger(fp,"Xmodem","SendTimeout",xm.send_timeout);     /* seconds */
                   1364:        xm.recv_timeout                 =iniReadInteger(fp,"Xmodem","RecvTimeout",xm.recv_timeout);     /* seconds */
                   1365:        xm.byte_timeout                 =iniReadInteger(fp,"Xmodem","ByteTimeout",xm.byte_timeout);     /* seconds */
                   1366:        xm.ack_timeout                  =iniReadInteger(fp,"Xmodem","AckTimeout",xm.ack_timeout);       /* seconds */
                   1367:        xm.block_size                   =iniReadInteger(fp,"Xmodem","BlockSize",xm.block_size);         /* 128 or 1024 */
                   1368:        xm.max_errors                   =iniReadInteger(fp,"Xmodem","MaxErrors",xm.max_errors);
                   1369:        xm.g_delay                              =iniReadInteger(fp,"Xmodem","G_Delay",xm.g_delay);
                   1370: 
                   1371:        zm.init_timeout                 =iniReadInteger(fp,"Zmodem","InitTimeout",zm.init_timeout);     /* seconds */
                   1372:        zm.send_timeout                 =iniReadInteger(fp,"Zmodem","SendTimeout",zm.send_timeout);     /* seconds */
                   1373:        zm.recv_timeout                 =iniReadInteger(fp,"Zmodem","RecvTimeout",zm.recv_timeout);     /* seconds */
                   1374:        zm.crc_timeout                  =iniReadInteger(fp,"Zmodem","CrcTimeout",zm.crc_timeout);       /* seconds */
                   1375:        zm.block_size                   =iniReadInteger(fp,"Zmodem","BlockSize",zm.block_size);                 /* 1024  */
                   1376:        zm.max_block_size               =iniReadInteger(fp,"Zmodem","MaxBlockSize",zm.max_block_size);  /* 1024 or 8192 */
                   1377:        zm.max_errors                   =iniReadInteger(fp,"Zmodem","MaxErrors",zm.max_errors);
                   1378:        zm.recv_bufsize                 =iniReadInteger(fp,"Zmodem","RecvBufSize",0);
                   1379:        zm.no_streaming                 =!iniReadBool(fp,"Zmodem","Streaming",TRUE);
                   1380:        zm.want_fcs_16                  =!iniReadBool(fp,"Zmodem","CRC32",TRUE);
                   1381:        zm.escape_telnet_iac    =iniReadBool(fp,"Zmodem","EscapeTelnetIAC",TRUE);
                   1382:        zm.escape_8th_bit               =iniReadBool(fp,"Zmodem","Escape8thBit",FALSE);
                   1383:        zm.escape_ctrl_chars    =iniReadBool(fp,"Zmodem","EscapeCtrlChars",FALSE);
                   1384: 
                   1385:        dszlog_path                             =iniReadBool(fp,"DSZLOG","Path",TRUE);
                   1386:        dszlog_short                    =iniReadBool(fp,"DSZLOG","Short",FALSE);
                   1387:        dszlog_quotes                   =iniReadBool(fp,"DSZLOG","Quotes",FALSE);
                   1388: 
                   1389:        if(fp!=NULL)
                   1390:                fclose(fp);
                   1391: 
                   1392:        if(zm.recv_bufsize > 0xffff)
                   1393:                zm.recv_bufsize = 0xffff;
                   1394: 
                   1395:        if(outbuf_size < MIN_OUTBUF_SIZE)
                   1396:                outbuf_size = MIN_OUTBUF_SIZE;
                   1397:        else if(outbuf_size > MAX_OUTBUF_SIZE)
                   1398:                outbuf_size = MAX_OUTBUF_SIZE;
                   1399:        
                   1400:        fprintf(statfp,"Output buffer size: %u\n", outbuf_size);
                   1401:        RingBufInit(&outbuf, outbuf_size);
                   1402: 
                   1403: #if !defined(RINGBUF_EVENT)
                   1404:        outbuf_empty=CreateEvent(NULL,/* ManualReset */TRUE, /*InitialState */TRUE,NULL);
                   1405: #endif
                   1406: 
                   1407: #if 0
                   1408:        if(argc>1) {
                   1409:                fprintf(statfp,"Command line: ");
                   1410:                for(i=1;i<argc;i++)
                   1411:                        fprintf(statfp,"%s ",argv[i]);
                   1412:                fprintf(statfp,"\n",statfp);
                   1413:        }
                   1414: #endif
                   1415: 
                   1416: 
                   1417:        for(i=1;i<argc;i++) {
                   1418: 
                   1419:                if(sock==INVALID_SOCKET && isdigit(argv[i][0])) {
                   1420:                        sock=atoi(argv[i]);
                   1421:                        continue;
                   1422:                }
                   1423: 
                   1424:                if(!(mode&(SEND|RECV))) {
                   1425:                        if(toupper(argv[i][0])=='S' || toupper(argv[i][0])=='R') { /* cmd */
                   1426:                                if(toupper(argv[i][0])=='R')
                   1427:                                        mode|=RECV;
                   1428:                                else
                   1429:                                        mode|=SEND;
                   1430: 
                   1431:                                switch(argv[i][1]) {
                   1432:                                        case 'c':
                   1433:                                        case 'C':
                   1434:                                                mode|=XMODEM|CRC;
                   1435:                                                break;
                   1436:                                        case 'x':
                   1437:                                                xm.block_size=128;
                   1438:                                        case 'X':
                   1439:                                                mode|=XMODEM;
                   1440:                                                break;
                   1441:                                        case 'b':       /* sz/rz compatible */
                   1442:                                        case 'B':
                   1443:                                        case 'y':
                   1444:                                                xm.block_size=128;
                   1445:                                        case 'Y':
                   1446:                                                mode|=(YMODEM|CRC);
                   1447:                                                break;
                   1448:                                        case 'g':
                   1449:                                        case 'G':
                   1450:                                                mode|=(YMODEM|CRC|GMODE);
                   1451:                                                break;
                   1452:                                        case 'z':
                   1453:                                        case 'Z':
                   1454:                                                mode|=(ZMODEM|CRC);
                   1455:                                                break;
                   1456:                                        default:
                   1457:                                                fprintf(statfp,"Unrecognized command '%s'\n\n",argv[i]);
                   1458:                                                fprintf(statfp,usage);
                   1459:                                                bail(1); 
                   1460:                                } 
                   1461:                                continue;
                   1462:                        }
                   1463: 
                   1464:                        if(toupper(argv[i][0])=='V') {
                   1465: 
                   1466:                                fprintf(statfp,"%-8s %s\n",getfname(__FILE__)           ,revision);
                   1467:                                fprintf(statfp,"%-8s %s\n",getfname(xmodem_source()),xmodem_ver(str));
                   1468:                                fprintf(statfp,"%-8s %s\n",getfname(zmodem_source()),zmodem_ver(str));
                   1469: #ifdef _DEBUG
                   1470:                                fprintf(statfp,"Debug\n");
                   1471: #endif
                   1472:                                fprintf(statfp,"Compiled %s %.5s with %s\n",__DATE__,__TIME__,compiler);
                   1473:                                fprintf(statfp,"%s\n",os_version(str));
                   1474:                                bail(0);
                   1475:                        }
                   1476: 
                   1477:                        arg=argv[i];
                   1478:                        if(*arg=='-') {
                   1479:                                while(*arg=='-')
                   1480:                                        arg++;
                   1481:                                if(stricmp(arg,"telnet")==0) {
                   1482:                                        telnet=TRUE;
                   1483:                                        continue;
                   1484:                                }
                   1485:                                if(stricmp(arg,"rlogin")==0 || stricmp(arg,"ssh")==0 || stricmp(arg,"raw")==0) {
                   1486:                                        telnet=FALSE;
                   1487:                                        continue;
                   1488:                                }
                   1489:                                if(stricmp(arg,"debug")==0) {
                   1490:                                        log_level=LOG_DEBUG;
                   1491:                                        continue;
                   1492:                                }
                   1493:                                if(stricmp(arg,"quotes")==0) {
                   1494:                                        dszlog_quotes=TRUE;
                   1495:                                        continue;
                   1496:                                }
                   1497:                                switch(toupper(*arg)) {
                   1498:                                        case 'K':       /* sz/rz compatible */
                   1499:                                                xm.block_size=1024;
                   1500:                                                break;
                   1501:                                        case 'C':       /* sz/rz compatible */
                   1502:                                                mode|=CRC;
                   1503:                                                break;
                   1504:                                        case '2':
                   1505:                                                zm.max_block_size=2048;
                   1506:                                                break;
                   1507:                                        case '4':
                   1508:                                                zm.max_block_size=4096;
                   1509:                                                break;
                   1510:                                        case '8':       /* ZedZap */
                   1511:                                                zm.max_block_size=8192;
                   1512:                                                break;
                   1513:                                        case 'O':       /* disable Zmodem CRC-32 */
                   1514:                                                zm.want_fcs_16=TRUE;
                   1515:                                                break;
                   1516:                                        case 'S':       /* disable Zmodem streaming */
                   1517:                                                zm.no_streaming=TRUE;
                   1518:                                                break;
                   1519:                                        case 'G':       /* Ymodem-G */
                   1520:                                                mode|=GMODE;
                   1521:                                                break;
                   1522:                                        case 'Y':
                   1523:                                                mode|=OVERWRITE;
                   1524:                                                break;
                   1525:                                        case '!':
                   1526:                                                pause_on_abend=TRUE;
                   1527:                                                break;
                   1528:                                }
                   1529:                        }
                   1530:                }
                   1531: 
                   1532:                else if((argv[i][0]=='+' || argv[i][0]=='@') && fexist(argv[i]+1)) {
                   1533:                        if(mode&RECVDIR) {
                   1534:                                fprintf(statfp,"!Cannot specify both directory and filename\n");
                   1535:                                bail(1); 
                   1536:                        }
                   1537:                        sprintf(str,"%s",argv[i]+1);
                   1538:                        if((fp=fopen(str,"r"))==NULL) {
                   1539:                                fprintf(statfp,"!Error %d opening filelist: %s\n",errno,str);
                   1540:                                bail(1); 
                   1541:                        }
                   1542:                        while(!feof(fp) && !ferror(fp)) {
                   1543:                                if(!fgets(str,sizeof(str),fp))
                   1544:                                        break;
                   1545:                                truncsp(str);
                   1546:                                strListAppend(&fname_list,strdup(str),fnames++);
                   1547:                        }
                   1548:                        fclose(fp); 
                   1549:                }
                   1550: 
                   1551:                else if(mode&(SEND|RECV)){
                   1552:                        if(isdir(argv[i])) { /* is a directory */
                   1553:                                if(mode&RECVDIR) {
                   1554:                                        fprintf(statfp,"!Only one directory can be specified\n");
                   1555:                                        bail(1); 
                   1556:                                }
                   1557:                                if(fnames) {
                   1558:                                        fprintf(statfp,"!Cannot specify both directory and filename\n");
                   1559:                                        bail(1); 
                   1560:                                }
                   1561:                                if(mode&SEND) {
                   1562:                                        fprintf(statfp,"!Cannot send directory '%s'\n",argv[i]);
                   1563:                                        bail(1);
                   1564:                                }
                   1565:                                mode|=RECVDIR; 
                   1566:                        }
                   1567:                        strListAppend(&fname_list,argv[i],fnames++);
                   1568:                } 
                   1569:        }
                   1570: 
                   1571:        if(!telnet)
                   1572:                zm.escape_telnet_iac = FALSE;
                   1573: 
                   1574:        if(sock==INVALID_SOCKET || sock<1) {
                   1575: #ifdef __unix__
                   1576:                if(STDOUT_FILENO > STDIN_FILENO)
                   1577:                        sock=STDOUT_FILENO;
                   1578:                else
                   1579:                        sock=STDIN_FILENO;
                   1580:                stdio=TRUE;
                   1581:                
                   1582:                fprintf(statfp,"No socket descriptor specified, using STDIO\n");
                   1583:                telnet=FALSE;
                   1584: #else
                   1585:                fprintf(statfp,"!No socket descriptor specified\n\n");
                   1586:                fprintf(errfp,usage);
                   1587:                bail(1);
                   1588: #endif
                   1589:        }
                   1590: #ifdef __unix__
                   1591:        else
                   1592:                statfp=stdout;
                   1593: #endif
                   1594: 
                   1595:        if(!(mode&(SEND|RECV))) {
                   1596:                fprintf(statfp,"!No command specified\n\n");
                   1597:                fprintf(statfp,usage);
                   1598:                bail(1); 
                   1599:        }
                   1600: 
                   1601:        if(mode&(SEND|XMODEM) && !fnames) { /* Sending with any or recv w/Xmodem */
                   1602:                fprintf(statfp,"!Must specify filename or filelist\n\n");
                   1603:                fprintf(statfp,usage);
                   1604:                bail(1); 
                   1605:        }
                   1606: 
                   1607: #ifdef __unix__
                   1608:        if(stdio) {
                   1609:                struct termios term;
                   1610:                memset(&term,0,sizeof(term));
                   1611:                cfsetispeed(&term,B19200);
                   1612:                cfsetospeed(&term,B19200);
                   1613:                term.c_iflag &= ~(IMAXBEL|IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
                   1614:                term.c_oflag &= ~OPOST;
                   1615:                term.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
                   1616:                term.c_cflag &= ~(CSIZE|PARENB);
                   1617:                term.c_cflag |= CS8;
                   1618:                atexit(resetterm);
                   1619:                tcgetattr(STDOUT_FILENO, &origterm);
                   1620:                tcsetattr(STDOUT_FILENO, TCSADRAIN, &term);
                   1621:        }
                   1622: #endif
                   1623: 
                   1624:        /* Code disabled.  Why?  ToDo */
                   1625: /*     if(mode&RECVDIR)
                   1626:                backslash(fname[0]); */
                   1627: 
                   1628:        if(!winsock_startup())
                   1629:                bail(-1);
                   1630: 
                   1631:        /* Enable the Nagle Algorithm */
                   1632: #ifdef __unix__
                   1633:        if(!stdio) {
                   1634: #endif
                   1635:                lprintf(LOG_DEBUG,"Setting TCP_NODELAY to %d",tcp_nodelay);
                   1636:                setsockopt(sock,IPPROTO_TCP,TCP_NODELAY,(char*)&tcp_nodelay,sizeof(tcp_nodelay));
                   1637: #ifdef __unix__
                   1638:        }
                   1639: #endif
                   1640: 
                   1641:        if(!socket_check(sock, NULL, NULL, 0)) {
                   1642:                lprintf(LOG_WARNING,"No socket connection");
                   1643:                bail(-1); 
                   1644:        }
                   1645: 
                   1646:        if((dszlog=getenv("DSZLOG"))!=NULL) {
                   1647:                if((logfp=fopen(dszlog,"w"))==NULL) {
                   1648:                        lprintf(LOG_WARNING,"Error %d opening DSZLOG file: %s",errno,dszlog);
                   1649:                        bail(-1); 
                   1650:                }
                   1651:        }
                   1652: 
                   1653:        /* Install Ctrl-C/Break signal handler here */
                   1654: #if defined(_WIN32)
                   1655:        SetConsoleCtrlHandler(ControlHandler, TRUE /* Add */);
                   1656: #elif defined(__unix__)
                   1657:        signal(SIGQUIT,break_handler);
                   1658:        signal(SIGINT,break_handler);
                   1659:        signal(SIGTERM,break_handler);
                   1660: 
                   1661:        signal(SIGHUP,SIG_IGN);
                   1662: 
                   1663:        /* Don't die on SIGPIPE  */
                   1664:        signal(SIGPIPE,SIG_IGN);
                   1665: #endif
                   1666: 
                   1667: #if !SINGLE_THREADED
                   1668:        _beginthread(output_thread,0,NULL);
                   1669: #endif
                   1670: 
                   1671:        if(mode&RECV)
                   1672:                retval=receive_files(fname_list, fnames);
                   1673:        else
                   1674:                retval=send_files(fname_list, fnames);
                   1675: 
                   1676: #if !SINGLE_THREADED
                   1677:        lprintf(LOG_DEBUG,"Waiting for output buffer to empty... ");
                   1678:        if(WaitForEvent(outbuf_empty,5000)!=WAIT_OBJECT_0)
                   1679:                lprintf(LOG_DEBUG,"FAILURE");
                   1680: #endif
                   1681: 
                   1682:        terminate=TRUE; /* stop output thread */
                   1683:        /* Code disabled.  Why?  ToDo */
                   1684: /*     sem_post(outbuf.sem);
                   1685:        sem_post(outbuf.highwater_sem); */
                   1686: 
                   1687:        fprintf(statfp,"Exiting - Error level: %d, flows: %u, select_errors=%u"
                   1688:                ,retval, flows, select_errors);
                   1689:        fprintf(statfp,"\n");
                   1690: 
                   1691:        bail(retval);
                   1692: }
                   1693: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.