Annotation of sbbs/src/sbbs3/sexyz.c, revision 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.