int main(int argc, char **argv) { char str[MAX_PATH+1]; char fname[MAX_PATH+1]; char ini_fname[MAX_PATH+1]; char* p; char* arg; int i; int retval; uint fnames=0; FILE* fp; BOOL tcp_nodelay; char compiler[32]; str_list_t fname_list; fname_list=strListInit(); DESCRIBE_COMPILER(compiler); errfp=stderr; #ifdef __unix__ statfp=stderr; #else statfp=stdout; #endif sscanf("$Revision: 1.77 $", "%*s %s", revision); fprintf(statfp,"\nSynchronet External X/Y/Zmodem v%s-%s" " Copyright %s Rob Swindell\n\n" ,revision ,PLATFORM_DESC ,__DATE__+7 ); xmodem_init(&xm,NULL,&mode,lputs,xmodem_progress,send_byte,recv_byte,is_connected,NULL); zmodem_init(&zm,NULL,lputs,zmodem_progress,send_byte,recv_byte,is_connected,NULL,data_waiting); /* Generate path/sexyz[.host].ini from path/sexyz[.exe] */ SAFECOPY(str,argv[0]); p=getfname(str); SAFECOPY(fname,p); *p=0; if((p=getfext(fname))!=NULL) *p=0; strcat(fname,".ini"); iniFileName(ini_fname,sizeof(ini_fname),str,fname); if((fp=fopen(ini_fname,"r"))!=NULL) fprintf(statfp,"Reading %s\n",ini_fname); tcp_nodelay =iniReadBool(fp,ROOT_SECTION,"TCP_NODELAY",TRUE); telnet =iniReadBool(fp,ROOT_SECTION,"Telnet",TRUE); debug_tx =iniReadBool(fp,ROOT_SECTION,"DebugTx",FALSE); debug_rx =iniReadBool(fp,ROOT_SECTION,"DebugRx",FALSE); debug_telnet =iniReadBool(fp,ROOT_SECTION,"DebugTelnet",FALSE); pause_on_exit =iniReadBool(fp,ROOT_SECTION,"PauseOnExit",FALSE); pause_on_abend =iniReadBool(fp,ROOT_SECTION,"PauseOnAbend",FALSE); log_level =iniReadLogLevel(fp,ROOT_SECTION,"LogLevel",log_level); outbuf.highwater_mark =iniReadInteger(fp,ROOT_SECTION,"OutbufHighwaterMark",1100); outbuf_drain_timeout =iniReadInteger(fp,ROOT_SECTION,"OutbufDrainTimeout",10); outbuf_size =iniReadInteger(fp,ROOT_SECTION,"OutbufSize",16*1024); progress_interval =iniReadInteger(fp,ROOT_SECTION,"ProgressInterval",1); if(iniReadBool(fp,ROOT_SECTION,"Debug",FALSE)) log_level=LOG_DEBUG; xm.send_timeout =iniReadInteger(fp,"Xmodem","SendTimeout",xm.send_timeout); /* seconds */ xm.recv_timeout =iniReadInteger(fp,"Xmodem","RecvTimeout",xm.recv_timeout); /* seconds */ xm.byte_timeout =iniReadInteger(fp,"Xmodem","ByteTimeout",xm.byte_timeout); /* seconds */ xm.ack_timeout =iniReadInteger(fp,"Xmodem","AckTimeout",xm.ack_timeout); /* seconds */ xm.block_size =iniReadInteger(fp,"Xmodem","BlockSize",xm.block_size); /* 128 or 1024 */ xm.max_errors =iniReadInteger(fp,"Xmodem","MaxErrors",xm.max_errors); xm.g_delay =iniReadInteger(fp,"Xmodem","G_Delay",xm.g_delay); zm.init_timeout =iniReadInteger(fp,"Zmodem","InitTimeout",zm.init_timeout); /* seconds */ zm.send_timeout =iniReadInteger(fp,"Zmodem","SendTimeout",zm.send_timeout); /* seconds */ zm.recv_timeout =iniReadInteger(fp,"Zmodem","RecvTimeout",zm.recv_timeout); /* seconds */ zm.crc_timeout =iniReadInteger(fp,"Zmodem","CrcTimeout",zm.crc_timeout); /* seconds */ zm.block_size =iniReadInteger(fp,"Zmodem","BlockSize",zm.block_size); /* 1024 */ zm.max_block_size =iniReadInteger(fp,"Zmodem","MaxBlockSize",zm.max_block_size); /* 1024 or 8192 */ zm.max_errors =iniReadInteger(fp,"Zmodem","MaxErrors",zm.max_errors); zm.recv_bufsize =iniReadInteger(fp,"Zmodem","RecvBufSize",0); zm.no_streaming =!iniReadBool(fp,"Zmodem","Streaming",TRUE); zm.want_fcs_16 =!iniReadBool(fp,"Zmodem","CRC32",TRUE); zm.escape_telnet_iac =iniReadBool(fp,"Zmodem","EscapeTelnetIAC",TRUE); zm.escape_8th_bit =iniReadBool(fp,"Zmodem","Escape8thBit",FALSE); zm.escape_ctrl_chars =iniReadBool(fp,"Zmodem","EscapeCtrlChars",FALSE); dszlog_path =iniReadBool(fp,"DSZLOG","Path",TRUE); dszlog_short =iniReadBool(fp,"DSZLOG","Short",FALSE); dszlog_quotes =iniReadBool(fp,"DSZLOG","Quotes",FALSE); if(fp!=NULL) fclose(fp); if(zm.recv_bufsize > 0xffff) zm.recv_bufsize = 0xffff; if(outbuf_size < MIN_OUTBUF_SIZE) outbuf_size = MIN_OUTBUF_SIZE; else if(outbuf_size > MAX_OUTBUF_SIZE) outbuf_size = MAX_OUTBUF_SIZE; fprintf(statfp,"Output buffer size: %u\n", outbuf_size); RingBufInit(&outbuf, outbuf_size); #if !defined(RINGBUF_EVENT) outbuf_empty=CreateEvent(NULL,/* ManualReset */TRUE, /*InitialState */TRUE,NULL); #endif #if 0 if(argc>1) { fprintf(statfp,"Command line: "); for(i=1;i<argc;i++) fprintf(statfp,"%s ",argv[i]); fprintf(statfp,"\n",statfp); } #endif for(i=1;i<argc;i++) { if(sock==INVALID_SOCKET && isdigit(argv[i][0])) { sock=atoi(argv[i]); continue; } if(!(mode&(SEND|RECV))) { if(toupper(argv[i][0])=='S' || toupper(argv[i][0])=='R') { /* cmd */ if(toupper(argv[i][0])=='R') mode|=RECV; else mode|=SEND; switch(argv[i][1]) { case 'c': case 'C': mode|=XMODEM|CRC; break; case 'x': xm.block_size=128; case 'X': mode|=XMODEM; break; case 'b': /* sz/rz compatible */ case 'B': case 'y': xm.block_size=128; case 'Y': mode|=(YMODEM|CRC); break; case 'g': case 'G': mode|=(YMODEM|CRC|GMODE); break; case 'z': case 'Z': mode|=(ZMODEM|CRC); break; default: fprintf(statfp,"Unrecognized command '%s'\n\n",argv[i]); fprintf(statfp,usage); bail(1); } continue; } if(toupper(argv[i][0])=='V') { fprintf(statfp,"%-8s %s\n",getfname(__FILE__) ,revision); fprintf(statfp,"%-8s %s\n",getfname(xmodem_source()),xmodem_ver(str)); fprintf(statfp,"%-8s %s\n",getfname(zmodem_source()),zmodem_ver(str)); #ifdef _DEBUG fprintf(statfp,"Debug\n"); #endif fprintf(statfp,"Compiled %s %.5s with %s\n",__DATE__,__TIME__,compiler); fprintf(statfp,"%s\n",os_version(str)); bail(0); } arg=argv[i]; if(*arg=='-') { while(*arg=='-') arg++; if(stricmp(arg,"telnet")==0) { telnet=TRUE; continue; } if(stricmp(arg,"rlogin")==0 || stricmp(arg,"ssh")==0 || stricmp(arg,"raw")==0) { telnet=FALSE; continue; } if(stricmp(arg,"debug")==0) { log_level=LOG_DEBUG; continue; } if(stricmp(arg,"quotes")==0) { dszlog_quotes=TRUE; continue; } switch(toupper(*arg)) { case 'K': /* sz/rz compatible */ xm.block_size=1024; break; case 'C': /* sz/rz compatible */ mode|=CRC; break; case '2': zm.max_block_size=2048; break; case '4': zm.max_block_size=4096; break; case '8': /* ZedZap */ zm.max_block_size=8192; break; case 'O': /* disable Zmodem CRC-32 */ zm.want_fcs_16=TRUE; break; case 'S': /* disable Zmodem streaming */ zm.no_streaming=TRUE; break; case 'G': /* Ymodem-G */ mode|=GMODE; break; case 'Y': mode|=OVERWRITE; break; case '!': pause_on_abend=TRUE; break; } } } else if((argv[i][0]=='+' || argv[i][0]=='@') && fexist(argv[i]+1)) { if(mode&RECVDIR) { fprintf(statfp,"!Cannot specify both directory and filename\n"); bail(1); } sprintf(str,"%s",argv[i]+1); if((fp=fopen(str,"r"))==NULL) { fprintf(statfp,"!Error %d opening filelist: %s\n",errno,str); bail(1); } while(!feof(fp) && !ferror(fp)) { if(!fgets(str,sizeof(str),fp)) break; truncsp(str); strListAppend(&fname_list,strdup(str),fnames++); } fclose(fp); } else if(mode&(SEND|RECV)){ if(isdir(argv[i])) { /* is a directory */ if(mode&RECVDIR) { fprintf(statfp,"!Only one directory can be specified\n"); bail(1); } if(fnames) { fprintf(statfp,"!Cannot specify both directory and filename\n"); bail(1); } if(mode&SEND) { fprintf(statfp,"!Cannot send directory '%s'\n",argv[i]); bail(1); } mode|=RECVDIR; } strListAppend(&fname_list,argv[i],fnames++); } } if(!telnet) zm.escape_telnet_iac = FALSE; if(sock==INVALID_SOCKET || sock<1) { #ifdef __unix__ if(STDOUT_FILENO > STDIN_FILENO) sock=STDOUT_FILENO; else sock=STDIN_FILENO; stdio=TRUE; fprintf(statfp,"No socket descriptor specified, using STDIO\n"); telnet=FALSE; #else fprintf(statfp,"!No socket descriptor specified\n\n"); fprintf(errfp,usage); bail(1); #endif } #ifdef __unix__ else statfp=stdout; #endif if(!(mode&(SEND|RECV))) { fprintf(statfp,"!No command specified\n\n"); fprintf(statfp,usage); bail(1); } if(mode&(SEND|XMODEM) && !fnames) { /* Sending with any or recv w/Xmodem */ fprintf(statfp,"!Must specify filename or filelist\n\n"); fprintf(statfp,usage); bail(1); } #ifdef __unix__ if(stdio) { struct termios term; memset(&term,0,sizeof(term)); cfsetispeed(&term,B19200); cfsetospeed(&term,B19200); term.c_iflag &= ~(IMAXBEL|IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON); term.c_oflag &= ~OPOST; term.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); term.c_cflag &= ~(CSIZE|PARENB); term.c_cflag |= CS8; atexit(resetterm); tcgetattr(STDOUT_FILENO, &origterm); tcsetattr(STDOUT_FILENO, TCSADRAIN, &term); } #endif /* Code disabled. Why? ToDo */ /* if(mode&RECVDIR) backslash(fname[0]); */ if(!winsock_startup()) bail(-1); /* Enable the Nagle Algorithm */ #ifdef __unix__ if(!stdio) { #endif lprintf(LOG_DEBUG,"Setting TCP_NODELAY to %d",tcp_nodelay); setsockopt(sock,IPPROTO_TCP,TCP_NODELAY,(char*)&tcp_nodelay,sizeof(tcp_nodelay)); #ifdef __unix__ } #endif if(!socket_check(sock, NULL, NULL, 0)) { lprintf(LOG_WARNING,"No socket connection"); bail(-1); } if((dszlog=getenv("DSZLOG"))!=NULL) { if((logfp=fopen(dszlog,"w"))==NULL) { lprintf(LOG_WARNING,"Error %d opening DSZLOG file: %s",errno,dszlog); bail(-1); } } /* Install Ctrl-C/Break signal handler here */ #if defined(_WIN32) SetConsoleCtrlHandler(ControlHandler, TRUE /* Add */); #elif defined(__unix__) signal(SIGQUIT,break_handler); signal(SIGINT,break_handler); signal(SIGTERM,break_handler); signal(SIGHUP,SIG_IGN); /* Don't die on SIGPIPE */ signal(SIGPIPE,SIG_IGN); #endif #if !SINGLE_THREADED _beginthread(output_thread,0,NULL); #endif if(mode&RECV) retval=receive_files(fname_list, fnames); else retval=send_files(fname_list, fnames); #if !SINGLE_THREADED lprintf(LOG_DEBUG,"Waiting for output buffer to empty... "); if(WaitForEvent(outbuf_empty,5000)!=WAIT_OBJECT_0) lprintf(LOG_DEBUG,"FAILURE"); #endif terminate=TRUE; /* stop output thread */ /* Code disabled. Why? ToDo */ /* sem_post(outbuf.sem); sem_post(outbuf.highwater_sem); */ fprintf(statfp,"Exiting - Error level: %d, flows: %u, select_errors=%u" ,retval, flows, select_errors); fprintf(statfp,"\n"); bail(retval); }
int main( int argc, char *argv[] ) { int opt, file_count = 0; pname = basename(argv[0]); if ( argc < 2 ) { Puterr( "insufficient arguments\n" ); exit(1); } prefix[0] = '\0'; /* No prefix and forced file name off by default */ logfile[0] = '\0'; /* No activity log file by default */ force = newer = relaxed = today = verbose = quiet = qterm = FALSE; make_dir = TRUE; onesec = ONESEC; retry_limit = RETRY_MAX; if (optind==0) /* 16-bit */ ++optind; /* Skip over command name */ if ( *argv[optind] == '/' ) { /*-- Check for a device over-ride ----*/ if ( ( mdm = open( argv[1], O_RDWR ) ) == -1 ) { Puterr( "unable to open device '%s'\n", argv[1] ); exit( 1 ); } ++optind; /* Skip over specified device name */ } else { /*-- No device override so use stdin/stdout to communicate ----*/ struct stat statbuf; strcpy( device, ttyname( 0 ) ); if( fstat( 0, &statbuf ) != -1 && S_ISSOCK(statbuf.st_mode) ) { socket = 1; mdm = 0; } else if ( ( mdm = open( device, O_RDWR ) ) == -1 ) { Puterr( "unable to open stdin as r/w\n" ); exit( 1 ); } use_stdin = TRUE; } signal( SIGALRM, (void *)&timeout ); init_mdm(); /* Setup the selected modem port and initialize */ /* any variables associated with the protocol. */ if ( ( *argv[optind] | ' ' ) == 'r') sending = FALSE; else if ( ( *argv[optind] | ' ' ) == 's' && argc > 2 ) sending = TRUE; else { Puterr( "Invalid argument '%s' (must be 'se' or 're')\n", argv[optind] ); exit( 1 ); } ++optind; /*---- Ready for command line options ----*/ while( ( opt = getopt( argc, argv, "FmnqrtuvVQf:l:p:s:" ) ) != -1 ) { switch( opt ) { case 'F': flashfile = TRUE; break; case 'f': strcpy( prefix, optarg ); force = TRUE; break; case 'l': strcpy( logfile, optarg ); break; case 'm': make_dir = FALSE; break; case 'n': newer = TRUE; break; case 'r': relaxed = TRUE; onesec <<= 2; /* Timeouts 4 times larger */ retry_limit <<= 1; /* Twice as many retries */ break; case 's': sub_packet_size = atoi( optarg ); sub_packet_size >>= 3; /* Divide by 8 for sub_packet */ if ( !sub_packet_size ) { Puterr( "packet size too small\n" ); exit( 1 ); } if ( sub_packet_size > MAXSIZE ) { Puterr( "packet size too large (max %d)\n", MAXSIZE*8); exit( 1 ); } break; case 't': today = TRUE; break; case 'u': unlink_file = TRUE; break; case 'V': case 'v': verbose = TRUE; break; case 'q': quiet = TRUE; break; case 'Q': qterm = TRUE; break; case 'p': strcpy( prefix, optarg ); break; case '?': if ( !extra_option( (char *)&optopt ) ) { Puterr( "unknown option '%s'\n", optopt ); exit( 1 ); } break; default: ++file_count; /* Count filenames */ continue; /* but don't null them */ } } if ( file_count > 1 ) multi_send_check(); /* Check if multi-send OK */ final_init(); /* Last changes before starting */ #ifndef __QNXNTO__ if ( !use_stdin ) dev_mode( 0, 0, _DEV_MODES ); /* Raw console input for abort requests */ #endif if ( sending ) send_files( argc - optind, (signed char **)(argv + optind) ); else receive_files( argc - optind, (signed char **)(argv + optind) ); done( 0 ); /* Protocol dependant termination routine */ return 0; }