#ifdef NT char *ckxv = "Win32 Communications I/O, 8.0.229, 29 Dec 2005"; #else char *ckxv = "OS/2 Communications I/O, 8.0.229, 29 Dec 2005"; #endif /* NT */ /* Expiration Information */ #ifdef BETATEST int expyear = 137, /* years from 1900 */ expmon = 0, /* 0 = Jan */ expday = 1; /* 1 - 31 */ #else int expyear = 137, /* years from 1900 */ expmon = 0, /* 0 = Jan */ expday = 1; /* 1 - 31 */ #endif /* BETATEST */ int downloaded=0; /* Is this a downloaded demo? */ int expired=0; /* Has demo expired? */ /* Define the following symbol to allow setting the title bar... */ /* Not recommended in OS/2 because the call to do this is undocumented. */ #define CK_SETTITLE /* C K O T I O -- Kermit communications I/O support for OS/2 systems */ /* Also contains code to emulate the UNIX alarm() function under OS/2 and a set of opendir/readdir/closedir, etc, functions. */ /* Authors: Jeffrey E Altman (jaltman@secure-endpoints.com), Secure Endpoints Inc., New York City Frank da Cruz (fdc@columbia.edu), Columbia University Academic Information Systems, New York City. Copyright (C) 1985, 2004, Trustees of Columbia University in the City of New York. All rights reserved. Originally adapted to OS/2 by Chris Adie , Edinburgh University Computing Service, 1988. Adapted to Kermit 5A by Kai Uwe Rommel , 1992-93. */ /* Includes */ #include "ckcdeb.h" /* Typedefs, debug formats, etc */ #include "ckcasc.h" /* ASCII character names */ #include "ckcker.h" /* Kermit definitions */ #include "ckcnet.h" /* Kermit definitions */ #include "ckcxla.h" #include "ckuxla.h" /* Translation tables */ #include "ckuusr.h" /* Command definitions - needed for ckokey.h */ #include /* Character types */ #include /* Standard i/o */ #include /* File io function declarations */ #include #include /* Process-control functions */ #include /* String manipulation declarations */ #include #include #include /* Time functions */ #include #ifdef NT #include #endif /* NT */ #ifdef OS2ONLY #include #endif /* OS2ONLY */ #include #ifdef NT #include #else /* NT */ #include #endif /* NT */ #include "ckodir.h" /* macros we might need */ #ifndef _O_APPEND #define _O_APPEND O_APPEND #endif #ifndef _O_WRONLY #define _O_WRONLY O_WRONLY #endif #ifndef _O_CREAT #define _O_CREAT O_CREAT #endif #ifndef _O_TEXT #define _O_TEXT O_TEXT #endif #ifndef _SH_DENYNO #define _SH_DENYNO SH_DENYNO #endif #ifndef _O_BINARY #define _O_BINARY O_BINARY #endif #ifndef _S_IFMT #define _S_IFMT S_IFMT #endif #ifndef _S_IFDIR #define _S_IFDIR S_IFDIR #endif #ifdef NT #include #include #include #include #include "cknwin.h" #include "ckntap.h" #ifdef CK_TAPI int TAPIAvail = 0 ; /* is TAPI Installed */ extern int tttapi ; /* is Line TAPI? */ extern int tapipass; /* TAPI Passthrough */ #endif /* CK_TAPI */ #ifdef KUI #include "ikui.h" struct _kui_init kui_init = {0,0,0,0,NULL,0,0,0,0,0,0,1}; #endif /* KUI */ _PROTOTYP( void DisplayCommProperties, (HANDLE)); #define popen _popen #define pclose _pclose #endif /* NT */ /* Version herald(s) */ #include "ckuver.h" #ifdef CK_AUTHENTICATION #include "ckuath.h" #endif /* CK_AUTHENTICATION */ char ckxsystem[256] = HERALD; char *ckxsys = HERALD; #ifdef CK_UTSNAME char unm_nam[80]=""; char unm_rel[80]=""; char unm_mch[80]=""; char unm_ver[80]=""; char unm_mod[80]=""; #endif /* CK_UTSNAME */ static char *ckxrev = "32-bit"; /* OS/2 system header files & related stuff */ #ifndef NT #define INCL_WIN #define INCL_WINSWITCHLIST #define INCL_ERRORS #define INCL_KBD #ifdef OS2MOUSE #define INCL_MOU #endif /* OS2MOUSE */ #define INCL_VIO #define INCL_DOSMISC #define INCL_DOSPROCESS #define INCL_DOSSEMAPHORES #define INCL_DOSQUEUES #define INCL_DOSEXCEPTIONS #define INCL_DOSSIGNALS #define INCL_DOSDEVICES #define INCL_DOSDEVIOCTL #define INCL_DOSNLS #define INCL_DOSASYNCTIMER #define INCL_DOSDATETIME #define INCL_DOSNMPIPES #include /* This pulls in a whole load of stuff */ #ifdef CK_REXX #define INCL_REXXSAA #include #endif /* CK_REXX */ #undef COMMENT #endif /* NT */ #include "ckowin.h" #include "ckcuni.h" #include "ckocon.h" #include "ckcsig.h" #include "ckokey.h" #include "ckoslp.h" #ifdef CK_XYZ #include "p.h" #include "ckop.h" #ifdef XYZ_DLL int p_avail = 0 ; /* Must load the DLL */ #else int p_avail = 1 ; /* No DLL to load - built-in */ #endif /* XYZ_DLL */ #endif /* CK_XYZ */ HKBD KbdHandle = 0 ; TID tidKbdHandler = (TID) 0, tidRdComWrtScr = (TID) 0, tidConKbdHandler = (TID) 0, tidTermScrnUpd = (TID) 0; #ifdef NT TID tidCommand = (TID) 0 ; DWORD CommandID = 0 ; int ckconraw = 0 ; HINSTANCE hInstance = NULL ; extern HWND hwndConsole; #endif /* NT */ BOOL KbdActive = 0 ; int Shutdown = FALSE; extern int tt_status[VNUM] ; int k95stdin=0,k95stdout=0; extern int inserver, local; #ifdef CHAR #undef CHAR #endif /* CHAR */ /* Variables available to outside world: dftty -- Pointer to default tty name string, like "/dev/tty". dfloc -- 0 if dftty is console, 1 if external line. dfprty -- Default parity dfflow -- Default flow control ckxech -- Flag for who echoes console typein: 1 - The program (system echo is turned off) 0 - The system (or front end, or terminal). functions that want to do their own echoing should check this flag before doing so. Functions for assigned communication line (either external or console tty): sysinit() -- System dependent program initialization syscleanup() -- System dependent program Shutdown ttopen(ttname,local,mdmtyp) -- Open the named tty for exclusive access. ttclos() -- Close & reset the tty, releasing any access lock. ttpkt(speed,flow,parity)-- Put the tty in packet mode or in DIALING or CONNECT modem control state. ttvt(speed,flow) -- Put the tty in virtual terminal mode. ttinl(dest,max,timo,...) -- Timed read packet from the tty. ttinc(timo) -- Timed read character from tty. ttchk() -- See how many characters in tty input buffer. ttxin(n,buf) -- Read n characters from tty (untimed). ttol(string,length) -- Write a string to the tty. ttxout(string,length) -- Write a string to the tty (with conversions). ttoc(c) -- Write a character to the tty. ttflui() -- Flush tty input buffer. ttgspd() -- Speed of tty line. Functions for console terminal: conraw() -- Set console into Raw mode concooked() -- Set console into Cooked mode conoc(c) -- Unbuffered output, one character to console. conol(s) -- Unbuffered output, null-terminated string to the console. conola(s) -- Unbuffered output, array of strings to the console. conxo(n,s) -- Unbuffered output, n characters to the console. conchk() -- Check if characters available at console (bsd 4.2). Check if escape char (^\) typed at console (System III/V). coninc(timo) -- Timed get a character from the console. Following routines are dummies: congm() -- Get console terminal mode. concb() -- Put console into single char mode with no echo. conres() -- Restore console to congm mode. conint() -- Enable console terminal interrupts. connoi() -- No console interrupts. Time functions sleep(t) -- Like UNIX sleep msleep(m) -- Millisecond sleep ztime(&s) -- Return pointer to date/time string rtimer() -- Reset timer gtimer() -- Get elapsed time since last call to rtimer() */ /* Defines */ #define HUPTIME 1000 /* Milliseconds for hangup */ #ifndef DEVNAMLEN #ifdef NETCONN /* Allow for long network hostnames */ #define DEVNAMLEN 128 #else /* No networks, applies to OS/2 device names only. */ #define DEVNAMLEN 14 #endif /* NETCONN */ #endif /* DEVNAMLEN */ /* definitions hiding 32-bit / 16-bit differences */ #ifdef __32BIT__ #ifndef NT USHORT DosDevIOCtl32(PVOID pData, USHORT cbData, PVOID pParms, USHORT cbParms, USHORT usFunction, USHORT usCategory, HFILE hDevice) { ULONG ulParmLengthInOut = cbParms, ulDataLengthInOut = cbData; return (USHORT) DosDevIOCtl(hDevice, usCategory, usFunction, pParms, cbParms, &ulParmLengthInOut, pData, cbData, &ulDataLengthInOut); } #endif /* NT */ typedef ULONG U_INT; #define FILEFINDBUF FILEFINDBUF3 #define FSQBUFFER FSQBUFFER2 #define DosFindFirst(p1, p2, p3, p4, p5, p6) \ DosFindFirst(p1, p2, p3, p4, p5, p6, 1) #define DosDevIOCtl DosDevIOCtl32 #endif /* Declarations */ /* dftty is the device name of the default device for file transfer */ /* dfloc is 0 if dftty is the user's console terminal, 1 if an external line */ extern long speed; extern int parity, fcharset, flow, ttcarr, isinterrupted; extern MACRO *macrotab; #ifdef OS2PM extern int os2pm; #endif /* OS2PM */ #ifndef K95G /* This is to allow remote operation */ char *dftty = "0"; /* stdin */ int dfloc = 0; #else char *dftty = "com1"; /* COM1 */ int dfloc = 1; #endif /* K95G */ int OSVer = 0; int nt351 = 0; #ifdef NTSIG int TlsIndex = 0; #endif /* NTSIG */ #ifdef OS2ONLY bool ttslip = 0 ; /* Equals 1 if being used as a replacement for SLIPTERM */ bool ttppp = 0 ; /* Equals 1 if being used as a replacement for SLATTACH */ #endif /* OS2ONLY */ bool ttshare = 0; /* do not open devices in shared mode */ int ttyfd = -1; /* TTY file descriptor (not open yet) */ int dfprty = 0; /* Default parity (0 = none) */ int ttprty = 0; /* Parity in use. */ int ttmdm = 0; /* Modem in use. */ int dfflow = FLO_AUTO; /* Default flow is AUTO-DETECT */ int backgrd = 0; /* Assume in foreground */ int ttcarr = CAR_AUT; /* Carrier handling mode. */ int ckxech = 1; /* 0 if system normally echoes console characters, else 1 */ extern int tcsl ; /* Local character set */ extern int tt_inpacing ; /* Input pacing */ extern int exithangup; #ifdef NETCONN extern int network, nettype, ttnproto, tn_exit, xitsta ; #endif extern int wasclosed; extern int exitonclose; extern int quiet; int ck_sleepint = CK_SLEEPINT ; char startupdir[CKMAXPATH] = "./"; char exedir[CKMAXPATH] = "./"; char usertitle[64] = ""; /* Declarations of variables global within this module */ static struct rdchbuf_rec { /* Buffer for serial characters */ unsigned char buffer[32768]; U_INT length, index; } rdchbuf; int ttpush=-1; /* So we can perform a peek */ static ULONG tcount; /* Elapsed time counter */ static int conmode, consaved; static int ttpmsk = 0377; /* Parity stripping mask. */ static char ttnmsv[DEVNAMLEN+1]; int islocal; int ishandle=0; int pid = 0; #ifdef NT static DCB ttydcb ; static LPCOMMCONFIG ttycfg=NULL; static DWORD cfgsize=0; #else /* NT */ static DCBINFO ttydcb; #endif /* NT */ int quitonbreak = FALSE ; /* Should SIGBREAK result in Quit */ static int nOldCP; static char szOldTitle[80]; #ifdef NT HANDLE #else HVIO #endif /* NT */ VioHandle = 0; #ifndef NOLOCAL #ifndef KUI static CK_VIDEOMODEINFO StartupConsoleModeInfo ; #endif /* KUI */ #endif /* NOLOCAL */ #ifndef NT HAB hab = 0 ; /* Handle to an Anchor Block */ #endif /* NT */ TID tidAlarm = (TID) 0 ; #define THRDSTKSIZ (2*131072) #ifdef NT /* Overlapped I/O structures */ #define MAXOW 7 int maxow_usr = MAXOW; int maxow = MAXOW; /* only use 1; otherwise, serial ports are overdriven */ /* This was caused because the default TX buffer size is guess what? */ /* ZERO. Set the TX Buffer Size to be the largest packet size or */ /* larger with SetupComm() and things work great! */ static OVERLAPPED overlapped_write[30] = { {0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1}, {0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1}, {0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1}, {0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1}, {0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1}, {0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1}, {0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1}, {0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1}, {0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1}, {0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1} }; static char * ow_ptr[30] = { NULL, NULL, NULL, NULL, NULL,NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,NULL, NULL, NULL, NULL, NULL }; static int ow_size[30] = { 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0 }; static int ow_inuse[30] = { 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0 }; int nActuallyWritten ; /* Even though we allocate all of these read structs only the first one is */ /* ever used unless NEWRDCH is defined. */ static OVERLAPPED overlapped_read[30] = { {0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1}, {0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1}, {0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1}, {0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1}, {0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1}, {0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1}, {0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1}, {0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1}, {0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1}, {0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1} }; static char * or_ptr[30] = { NULL, NULL, NULL, NULL, NULL,NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,NULL, NULL, NULL, NULL, NULL }; static int or_size[30] = { 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0 }; static int or_inuse[30] = { 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0 }; static int or_read[30] = { 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0 }; int nActuallyRead ; /* Lets try owwait = FALSE and see if anybody notices */ int owwait = FALSE ; #endif /* NT */ char OS2CmdFile[256] = ""; /* a copy of cmdfile if specified */ #ifdef SESLIMIT static time_t start_time = 0; static char warn[4]; #endif /* SESLIMIT */ #define TT_MODE_NONE 0 #define TT_MODE_VT 1 #define TT_MODE_PKT 2 #define TT_MODE_NORM 3 static int tt_mode = TT_MODE_NONE; /* Forward declarations */ _PROTOTYP( static int os2setdtr, (int) ); _PROTOTYP( static int os2setcarr, (int) ); _PROTOTYP( static int ttsettings, (int, int) ); _PROTOTYP( int ttsetspd, (long) ); _PROTOTYP( int concooked, (void) ); _PROTOTYP( int os2rexxinit, (void) ); _PROTOTYP( int os2setcp, (int) ); _PROTOTYP( int os2getcplist, (int *, int) ); _PROTOTYP( int os2getcp, (void) ); _PROTOTYP( int os2settitle, (char *, int) ); _PROTOTYP( int os2gettitle, (char *, int) ); #ifndef NOLOCAL _PROTOTYP( int StartConnectThreads, ( void ) ); _PROTOTYP( int StopConnectThreads, (int) ); #endif /* NOLOCAL */ #ifndef NT _PROTOTYP( APIRET ConnectToPM, (void) ); _PROTOTYP( APIRET ReadFromPM, (char *, ULONG, ULONG *) ); _PROTOTYP( APIRET DisconnectFromPM, (void) ); #endif /* OS2PM */ #ifdef HWPARITY /* Unfortunately we must do this with global variables rather than through the tt...() APIs to avoid changing the APIs and the many modules that use them. If hwparity != 0, this indicates 8 data bits + parity, rather than 7 data bits + parity or 8 data bits and no parity, and overrides the regular parity variable, which is communicated to this module thru ttpkt(), and represented locally by the ttprty variable. */ extern int hwparity; /* Hardware parity */ extern int stopbits; /* Stop bits */ #endif /* HWPARITY */ #ifdef CKNTSIG /* Our own SIGNAL routine, to avoid calling C runtime library. */ static SIGTYP (*siginthandler)(int) = NULL; /* Pointer to SIGINT handler */ static BOOL cknthandler(DWORD dummy) { debug(F100,"cknthandler","",0); (*siginthandler)(SIGINT); return(TRUE); } SIGTYP (* ckntsignal(int sig, SIGTYP (*f)(int)))(int) { debug(F101,"ckntsignal sig","",sig); if (f == SIG_DFL) { siginthandler = NULL; #ifndef KUI SetConsoleCtrlHandler(NULL, FALSE); #endif /* KUI */ } else if (f == SIG_IGN) { siginthandler = NULL; #ifndef KUI SetConsoleCtrlHandler(NULL, FALSE); #endif /* KUI */ } else { siginthandler = f; #ifndef KUI SetConsoleCtrlHandler((PHANDLER_ROUTINE) cknthandler, TRUE); #endif /* KUI */ } } #endif /* CKNTSIG */ /* Saving/restoring of hot handles */ static int savedtty = 0; #ifdef NT static DCB saveddcb ; static LPCOMMCONFIG savedcfg=NULL; static DWORD savedcfgsize=0; #else /* NT */ static long savedspeed; static LINECONTROL savedlc; static DCBINFO saveddcb; static BYTE savedstat; #endif /* NT */ #ifdef NT /* d e b u g C o m m -- generate a debug log entry for the */ /* current state of the DCB and TIMEOUT structures */ void debugComm( char * msg, DCB * lpDCB, COMMTIMEOUTS * timeouts ) { if ( !deblog ) return; debug(F110,"debugComm",msg,0); if ( lpDCB ) { debug(F101," BaudRate ","",lpDCB->BaudRate); debug(F101," Binary Mode (no EOF check) ","",lpDCB->fBinary); debug(F101," Enable Parity Checking ","",lpDCB->fParity); debug(F101," CTS Handshaking on output ","",lpDCB->fOutxCtsFlow); debug(F101," DSR Handshaking on output ","",lpDCB->fOutxDsrFlow); debug(F101," DTR Flow Control ","",lpDCB->fDtrControl); debug(F101," DSR Sensitivity ","",lpDCB->fDsrSensitivity); debug(F101," Continue TX when Xoff sent ","",lpDCB->fTXContinueOnXoff); debug(F101," Enable output X-ON/X-OFF ","",lpDCB->fOutX); debug(F101," Enable input X-ON/X-OFF ","",lpDCB->fInX); debug(F101," Enable Err Replacement ","",lpDCB->fErrorChar); debug(F101," Enable Null stripping ","",lpDCB->fNull); debug(F101," RTS flow control ","",lpDCB->fRtsControl); debug(F101," Abort all I/O on Error ","",lpDCB->fAbortOnError); debug(F101," Transmit X-ON threshold ","",lpDCB->XonLim); debug(F101," Transmit X-OFF threshold ","",lpDCB->XoffLim); debug(F101," Num of bits/byte, 4-8 ","",lpDCB->ByteSize); debug(F101," Parity (0-4=N,O,E,M,S) ","",lpDCB->Parity); debug(F101," StopBits (0,1,2 = 1, 1.5, 2)","",lpDCB->StopBits); debug(F101," Tx and Rx X-ON character ","",lpDCB->XonChar); debug(F101," Tx and Rx X-OFF character ","",lpDCB->XoffChar); debug(F101," Error replacement char ","",lpDCB->ErrorChar); debug(F101," End of Input character ","",lpDCB->EofChar); debug(F101," Received Event character ","",lpDCB->EvtChar); } if ( timeouts ) { debug(F101," ReadIntervalTimeout ","",timeouts->ReadIntervalTimeout); debug(F101," ReadTotalTimeoutMultiplier ","",timeouts->ReadTotalTimeoutMultiplier); debug(F101," ReadTotalTimeoutConstant ","",timeouts->ReadTotalTimeoutConstant); debug(F101," WriteTotalTimeoutMultiplier","",timeouts->WriteTotalTimeoutMultiplier); debug(F101," WriteTotalTimeoutConstant ","",timeouts->WriteTotalTimeoutConstant); } } #endif /* NT */ int savetty() { if (ttyfd != -1) { #ifdef NT saveddcb.DCBlength = sizeof(DCB); GetCommState( (HANDLE) ttyfd, &saveddcb ) ; if ( deblog ) debugComm( "savetty initial values", &ttydcb, NULL ); savedcfg->dwSize = 1024; savedcfgsize = 1024; GetCommConfig( (HANDLE) ttyfd, savedcfg, &savedcfgsize ); #else /* NT */ savedspeed = ttgspd(); DosDevIOCtl(&savedlc,sizeof(savedlc),NULL,0, ASYNC_GETLINECTRL,IOCTL_ASYNC,ttyfd); DosDevIOCtl(&saveddcb,sizeof(saveddcb),NULL,0, ASYNC_GETDCBINFO,IOCTL_ASYNC,ttyfd); DosDevIOCtl(&savedstat,sizeof(savedstat),NULL,0, ASYNC_GETMODEMOUTPUT,IOCTL_ASYNC,ttyfd); #endif /* NT */ savedtty = 1; } return 0; } int restoretty() { #ifndef NT MODEMSTATUS ms; UINT cmd = 0, data = 0 ; #endif /* NT */ if (savedtty) { #ifdef NT #ifdef COMMENT SetCommState( (HANDLE) ttyfd, &saveddcb ) ; #else SetCommConfig( (HANDLE) ttyfd, savedcfg, savedcfgsize ); #endif #else /* NT */ ttsetspd(savedspeed); DosDevIOCtl(&data,sizeof(data),&cmd,sizeof(cmd), DEV_FLUSHOUTPUT,IOCTL_GENERAL,ttyfd); DosDevIOCtl(NULL,0,&savedlc,sizeof(savedlc), ASYNC_SETLINECTRL,IOCTL_ASYNC,ttyfd); ms.fbModemOn = 0; ms.fbModemOff = 255; if (savedstat & DTR_ON) ms.fbModemOn |= DTR_ON; else ms.fbModemOff &= DTR_OFF; if (savedstat & RTS_ON) ms.fbModemOn |= RTS_ON; else ms.fbModemOff &= RTS_OFF; DosDevIOCtl(&data,sizeof(data),&ms,sizeof(ms), ASYNC_SETMODEMCTRL,IOCTL_ASYNC,ttyfd); DosDevIOCtl(NULL,0,&saveddcb,sizeof(saveddcb), ASYNC_SETDCBINFO,IOCTL_ASYNC,ttyfd); #endif /* NT */ } return 0; } /* Code Page functions */ int os2getcp() { #ifdef NT #ifdef KUI return GetACP(); #else /* KUI */ return GetConsoleCP() ; #endif /* KUI */ #else /* NT */ U_INT cbData, nCodePage[8]; return (DosQueryCp(sizeof(nCodePage), nCodePage, &cbData) == 0) ? nCodePage[0] : 0; #endif /* NT */ } #ifdef COMMENT int os2checkcp(cp) int cp; { #ifdef NT return FALSE ; #else /* NT */ U_INT cbData, nCodePage[8], nCnt; if (DosQueryCp(sizeof(nCodePage), nCodePage, &cbData)) return FALSE; for (nCnt = 1; nCnt < cbData / sizeof(nCodePage[0]); nCnt++) if (nCodePage[nCnt] == cp) return TRUE; return FALSE; #endif /* NT */ } #endif /* COMMENT */ #ifdef NT static int * CPList ; static int CPListSize ; static int CPListIndex ; BOOL CALLBACK enumproc( LPSTR cpstr ) { CPList[CPListIndex] = atoi(cpstr) ; if ( ++CPListIndex < CPListSize ) return TRUE ; else return FALSE ; } #endif /* NT */ int os2getcplist(cplist, size) int *cplist; int size; { #ifdef NT int i ; CPList = cplist ; CPListSize = size / sizeof(int) ; CPListIndex = 1 ; for ( i=0 ; i 1) EnumSystemCodePages( enumproc, CP_INSTALLED ) ; return CPListIndex ; #else /* NT */ U_INT cbData; if (DosQueryCp(size, (U_INT *) cplist, &cbData)) return 0; return cbData / sizeof(int); #endif /* NT */ } int /* Change code page */ os2setcp(cp) int cp; { #ifdef NT #ifdef KUI return 1; /* Code Pages do not apply */ #else /* KUI */ return SetConsoleOutputCP( cp ) && SetConsoleCP( cp ) ; #endif /* KUI */ #else /* NT */ if ( k95stdout ) /* Can't set Code Page for stdio */ return 0; /* This has the affect of blocking */ /* and never returning if we have a */ /* getchar() in progress. */ return((VioSetCp(0, cp, VioHandle) == 0) && (KbdSetCp(0, cp, KbdHandle) == 0) && (DosSetProcessCp(cp) == 0)); #endif /* NT */ } void DisableHardErrors( void ) { #ifdef NT SetErrorMode( SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS ) ; #else /* NT */ DosError(FERR_DISABLEHARDERR | FERR_DISABLEEXCEPTION); #endif /* NT */ } APIRET os2getpid(void) { #ifdef NT return GetCurrentProcessId(); #else PTIB pptib; PPIB pppib; DosGetInfoBlocks(&pptib, &pppib); return pppib -> pib_ulpid; #endif } #ifdef NT int setOSVer( void ) { OSVERSIONINFO osverinfo ; osverinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO) ; GetVersionEx( &osverinfo ) ; OSVer = osverinfo.dwPlatformId ; if ( osverinfo.dwMajorVersion < 4 ) nt351 = 1; return(OSVer); } #endif /* NT */ char * getcpu( void ) { static char buffer[64] = "unknown" ; #ifdef NT SYSTEM_INFO si ; char numstr[32] ; memset( &si, 0, sizeof(si) ) ; GetSystemInfo( &si ) ; if ( isWin95() && !si.wProcessorLevel ) { switch ( si.dwProcessorType ) { case 386: strcpy( buffer, "intel-386" ) ; break; case 486: strcpy( buffer, "intel-486" ) ; break; case 586: strcpy( buffer, "intel-pentium" ) ; break; default: strcpy( buffer, "intel-" ) ; _itoa( si.dwProcessorType, numstr, 10 ) ; ckstrncat( buffer, numstr, 64 ) ; } } else { switch ( si.wProcessorArchitecture ) { case PROCESSOR_ARCHITECTURE_INTEL: ckstrncpy( buffer, "intel-", 64 ) ; switch ( si.wProcessorLevel ) { case 3: ckstrncat( buffer, "386", 64 ) ; break; case 4: ckstrncat( buffer, "486", 64 ) ; break; case 5: ckstrncat( buffer, "pentium", 64 ) ; break; default: _itoa( si.wProcessorLevel, numstr, 10 ) ; ckstrncat( buffer, numstr, 64 ); } break; case PROCESSOR_ARCHITECTURE_PPC: ckstrncpy( buffer, "ppc-", 64 ) ; switch ( si.wProcessorLevel ) { case 1: ckstrncat( buffer, "601", 64 ) ; break; case 3: ckstrncat( buffer, "603", 64 ) ; break; case 4: ckstrncat( buffer, "604", 64 ) ; break; case 6: ckstrncat( buffer, "603+", 64 ) ; break; case 9: ckstrncat( buffer, "604+", 64 ) ; break; case 20: ckstrncat( buffer, "620", 64 ) ; break; default: _itoa( si.wProcessorLevel, numstr, 10 ) ; ckstrncat( buffer, numstr, 64 ); } break; case PROCESSOR_ARCHITECTURE_MIPS: ckstrncpy( buffer, "mips-", 64 ) ; switch ( si.wProcessorLevel ) { case 4: ckstrncat( buffer, "r4000", 64 ) ; break; default: _itoa( si.wProcessorLevel, numstr, 10 ) ; ckstrncat( buffer, numstr, 64 ); } break; case PROCESSOR_ARCHITECTURE_ALPHA: ckstrncpy( buffer, "alpha-", 64 ) ; switch ( si.wProcessorLevel ) { default: _itoa( si.wProcessorLevel, numstr, 10 ) ; ckstrncat( buffer, numstr, 64 ); } break; case PROCESSOR_ARCHITECTURE_UNKNOWN: ckstrncpy( buffer, "unknown", 64 ) ; break; } } #else /* NT */ ckstrncpy( buffer, CKCPU, 64 ) ; #endif return buffer ; } static void term_signal(int sig) { debug(F101,"term_signal handler","",sig); #ifndef NOLOCAL SetConnectMode(0,CSX_KILL_SIG); #endif /* NOLOCAL */ printf("\n!!! Received KILL signal !!!\n"); bleep(BP_FAIL); #ifndef NODIAL if (mdmhup() < 1) #endif /* NODIAL */ tthang(); doexit(BAD_EXIT,-1); signal(SIGTERM, SIG_DFL); } #ifdef NT BOOL CloseHandler( DWORD dwCtrlType ) { // control signal type extern unsigned long startflags; debug(F111,"Win32 Close Handler","dwCtrlType",dwCtrlType); switch ( dwCtrlType ) { case CTRL_LOGOFF_EVENT: if ( startflags & 128 ) return TRUE; doexit(BAD_EXIT,0); return TRUE; case CTRL_CLOSE_EVENT: case CTRL_SHUTDOWN_EVENT: doexit(BAD_EXIT,0); return TRUE; default: return FALSE; } } #ifdef COMMENT /* If we were MS-DOS Kermit we could use these functions. But we are a Win32 app, so we can't. */ BOOL Win95QueryClose( void ) { short rc ; __asm { mov ah, 16h ; mov al, 8Fh ; mov dh, 1 ; mov dl, 0 ; int 2Fh ; mov rc, ax ; } return !rc; } BOOL Win95AcknowledgeClose( void ) { short rc ; __asm { mov ah, 16h ; mov al, 8Fh ; mov dh, 2 ; mov dl, 0 ; int 2Fh ; or ax, ax ; mov rc, ax ; } return rc ; } BOOL Win95CancelClose( void ) { short rc ; __asm { mov ah, 16h ; mov al, 8Fh ; mov dh, 3 ; mov dl, 0 ; int 2Fh ; or ax, ax ; mov rc, ax ; } return rc; } BOOL Win95EnableClose( void ) { short rc ; __asm { mov ah, 16h ; mov al, 8Fh ; mov dh, 0 ; mov dl, 01h ; int 2Fh ; or ax, ax ; mov rc, ax ; } return rc; } BOOL Win95DisableClose( void ) { short rc ; __asm { mov ah, 16h ; mov al, 8Fh ; mov dh, 0 ; mov dl, 00h ; int 2Fh ; or ax, ax ; mov rc, ax ; } return rc; } #endif /* COMMENT */ #endif /* NT */ #ifdef NT void Win95AltGrInit( void ) { /* Performing a grep ALTGRUSED *.ASM in the ddk\keyb\samples\driver\layout directory show that at least of the samples only three layouts do not have an AltGr key. So if we can read the layout, lets initialize the win95altgr variable to 1 if the layout is not one of those three. And 0 if we are unable to read the layout. Btw, 4NT.EXE just assumes that every layout has an AltGr key. */ extern int win95altgr; CHAR lpLayoutName[KL_NAMELENGTH]=""; int rc ; rc = GetKeyboardLayoutName(lpLayoutName); debug(F111,"Win95 Keyboard Layout Name",lpLayoutName,rc); if ( lpLayoutName[0] ) { if ( !strcmp("00000409",lpLayoutName) ) /* US 101 */ win95altgr = 0; else if ( !strcmp("00020409",lpLayoutName) ) /* US Dvorak */ win95altgr = 0; else if ( !strcmp("00000411",lpLayoutName) ) /* Japan 101 */ win95altgr = 0; else win95altgr = 1; } else win95altgr = 0; debug(F101,"Win95 AltGr Initialized","",win95altgr); } void Win95DisplayLocale( void ) { LCID Locale = LOCALE_SYSTEM_DEFAULT ; LCTYPE LCType = 0; CHAR lpLCDATA[1024]=""; int cchData=1024; int rc=0; int i=0; HKL KBLayout=0; CHAR lpLayoutName[KL_NAMELENGTH]=""; KBLayout = GetKeyboardLayout(0); GetKeyboardLayoutName(lpLayoutName); printf("Keyboard Layout = %s [%u]\n",lpLayoutName,(unsigned short)KBLayout); printf("Locale Information:\n"); for ( LCType=0 ; LCType<= 0x5A ; LCType++ ) { rc = GetLocaleInfo( LOCALE_SYSTEM_DEFAULT,LCType,lpLCDATA,cchData); printf(" LCType 0x%08x = \"%-25s\"",LCType,lpLCDATA); rc = GetLocaleInfo( LOCALE_USER_DEFAULT,LCType,lpLCDATA,cchData); printf(" \"%-25s\"\n",lpLCDATA); } } #endif /* NT */ char * GetLocalUser() { static char localuser[UIDBUFLEN]=""; /* Initialize the Username buffer if possible */ /* Allow environment variable to override the OS value */ char * user; if (localuser[0]) return(localuser); user = getenv( "USER" ); if ( user ) { ckstrncpy( localuser, user, UIDBUFLEN ); } else localuser[0] = '\0'; #ifdef NT if (!localuser[0]) { DWORD uidlen = UIDBUFLEN ; GetUserName( localuser, &uidlen ); } #endif /* NT */ return(localuser); } #ifdef NT VOID firsttime(void) { /* * What we will do is check to see if the Common and User App Data * directories exist. If they do not, we will create them. */ char dir[CKMAXPATH+1], file[CKMAXPATH+1], *common, *appdata, *personal; common = (char *)GetAppData(1); if ( common ) { ckmakmsg(dir,CKMAXPATH+1,(char *)common, "Kermit 95/", NULL, NULL); if ( !isdir(dir) ) { zmkdir(dir); ckmakmsg(dir,CKMAXPATH+1,(char *)common, "Kermit 95/SSH/", NULL, NULL); zmkdir(dir); ckmakmsg(dir,CKMAXPATH+1,(char *)common, "Kermit 95/CERTS/", NULL, NULL); zmkdir(dir); ckmakmsg(dir,CKMAXPATH+1,(char *)common, "Kermit 95/CRLS/", NULL, NULL); zmkdir(dir); ckmakmsg(dir,CKMAXPATH+1,(char *)common, "Kermit 95/KEYMAPS/", NULL, NULL); zmkdir(dir); ckmakmsg(dir,CKMAXPATH+1,(char *)common, "Kermit 95/PHONES/", NULL, NULL); zmkdir(dir); ckmakmsg(dir,CKMAXPATH+1,(char *)common, "Kermit 95/SCRIPTS/", NULL, NULL); zmkdir(dir); } } appdata = (char *)GetAppData(0); if ( appdata ) { ckmakmsg(dir,CKMAXPATH+1,(char *)appdata, "Kermit 95/", NULL, NULL); if ( !isdir(dir) ) { zmkdir(dir); if ( common = (char *)GetAppData(1) ) { ckmakmsg(file,CKMAXPATH+1,(char *)common, "Kermit 95/K95CUSTOM.INI", NULL, NULL); zcopy(file,dir); appdata = (char *)GetAppData(0); } ckmakmsg(dir,CKMAXPATH+1,(char *)appdata, "Kermit 95/SSH/", NULL, NULL); zmkdir(dir); ckmakmsg(dir,CKMAXPATH+1,(char *)appdata, "Kermit 95/CERTS/", NULL, NULL); zmkdir(dir); ckmakmsg(dir,CKMAXPATH+1,(char *)appdata, "Kermit 95/CRLS/", NULL, NULL); zmkdir(dir); ckmakmsg(dir,CKMAXPATH+1,(char *)appdata, "Kermit 95/KEYMAPS/", NULL, NULL); zmkdir(dir); ckmakmsg(dir,CKMAXPATH+1,(char *)appdata, "Kermit 95/PHONES/", NULL, NULL); zmkdir(dir); ckmakmsg(dir,CKMAXPATH+1,(char *)appdata, "Kermit 95/SCRIPTS/", NULL, NULL); zmkdir(dir); } personal = (char *)GetPersonal(); if ( personal ) { ckmakmsg(dir,CKMAXPATH+1,(char *)personal, "DOWNLOAD/", NULL, NULL); if ( !isdir(dir) ) zmkdir(dir); } } } #endif /* NT */ /* S Y S I N I T -- System-dependent program initialization. */ int SysInited = 0; int sysinit() { extern char uidbuf[] ; extern struct ck_p ptab[] ; extern int priority; extern int tt_mouse ; extern int tt_modechg; char *ptr; int n; extern unsigned long startflags; extern int DeleteStartupFile; extern int StartedFromDialer; extern int fdispla; extern int initvik; extern int tt_type; /* we raise the priority here because when we are not in connect mode, there is only thread (this one) which performs any serial or Network I/O. So this has to be a server priority thread. Upon entering connect mode we will lower the priority of this thread, and then raise upon exiting. This should provide snappy ckermit performance without too much damage to other processes. That is because this thread remains blocked most of time waiting on our keyboard (event) buffer semaphore. So even though the KbdHandler is Ready (at regular priority), this thread will be blocked unless we are waiting for serial or network I/O. */ #ifdef NT int WinThreadInit=0; DWORD mode ; #ifndef NOTERM extern int tt_attr_bug ; #endif /* NOTERM */ connoi() ; ck_sleepint = isWin95() ? CK_SLEEPINT : CK_SLEEPINT * 2; SetFileApisToOEM() ; /* Otherwise, filenames are translated */ /* Allocate memory for COMMCONFIG structure */ savedcfg = (LPCOMMCONFIG) malloc( 1024 ); if ( savedcfg ) { memset( savedcfg, 0, 1024 ); savedcfg->dwSize = 1024; } ttycfg = (LPCOMMCONFIG) malloc( 1024 ); if (ttycfg) { memset( ttycfg, 0, 1024 ); ttycfg->dwSize = 1024; } #ifndef NOLOCAL #ifndef KUI Win32ConsoleInit() ; /* Initialize the Console, Stdin, Stdout */ #endif /* KUI */ #endif /* NT */ #endif /* NOLOCAL */ /* Construct the system ID string */ #ifdef NT { OSVERSIONINFO osverinfo ; osverinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO) ; GetVersionEx( &osverinfo ) ; if ( startflags & 1 ) OSVer = VER_PLATFORM_WIN32_NT; else OSVer = osverinfo.dwPlatformId ; sprintf(ckxsystem, " %s %1d.%02d(%1d)%s%s", ( osverinfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS ? (osverinfo.dwMinorVersion == 0 ? "Windows 95" : "Windows 98") : osverinfo.dwPlatformId == VER_PLATFORM_WIN32_NT ? (osverinfo.dwMajorVersion < 5 ? "Windows NT" : "Windows 2000/XP") : "Windows Unknown" ), osverinfo.dwMajorVersion, osverinfo.dwMinorVersion, LOWORD(osverinfo.dwBuildNumber), osverinfo.szCSDVersion && osverinfo.szCSDVersion[0] ? " " : "", osverinfo.szCSDVersion ? osverinfo.szCSDVersion : ""); #ifdef CK_UTSNAME sprintf(unm_nam, ( osverinfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS ? (osverinfo.dwMinorVersion == 0 ? "Windows 95" : "Windows 98") : osverinfo.dwPlatformId == VER_PLATFORM_WIN32_NT ? (osverinfo.dwMajorVersion < 5 ? "Windows NT" : "Windows 2000/XP") : "Windows Unknown" )); sprintf(unm_rel,"%1d.%02d", osverinfo.dwMajorVersion, osverinfo.dwMinorVersion); sprintf(unm_ver,"(%1d)%s%s", LOWORD(osverinfo.dwBuildNumber), osverinfo.szCSDVersion && osverinfo.szCSDVersion[0] ? " " : "", osverinfo.szCSDVersion ? osverinfo.szCSDVersion : ""); #endif /* CK_UTSNAME */ #ifdef KUI InitCommonControls(); #endif /* KUI */ } #else /* NT */ { ULONG StartIndex = QSV_VERSION_MAJOR ; /* Major Version Number */ ULONG EndIndex = QSV_VERSION_REVISION ; /* Revision Letter */ ULONG DataBuf[3] ; ULONG DataBufLen = 3 * sizeof(ULONG) ; DosQuerySysInfo( StartIndex, EndIndex, DataBuf, DataBufLen ); sprintf(ckxsystem, " %s OS/2 %1d.%02d", ckxrev, _osmajor / 10, _osminor); #ifdef CK_UTSNAME sprintf(unm_nam,"OS/2"); sprintf(unm_rel,"%1d.%02d", _osmajor / 10, _osminor); sprintf(unm_ver,"%c",DataBuf[2]); #endif /* CK_UTSNAME */ } #endif /* NT */ #ifdef CK_UTSNAME sprintf(unm_mch,getcpu()); #endif /* CK_UTSNAME */ debug(F110,"Operating System",ckxsystem,0); #ifdef NT setlocale(LC_ALL, "" ); /* Import locale from OS */ #endif /* NT */ if ( StartedFromDialer ) /* We delete the cmdfile by default */ DeleteStartupFile = 1; /* only when started from the dialer */ k95stdin = (startflags & 32) ? 1 : 0; k95stdout = (startflags & 64) ? 1 : 0; if ( k95stdout ) { extern int interm; interm = 0; /* SET INPUT TERMINAL OFF */ } if ( k95stdin ) { #ifdef NT _setmode(_fileno(stdin),_O_BINARY); #else setmode(fileno(stdin),_O_BINARY); #endif /* NT */ } if ( k95stdout ) { #ifdef NT _setmode(_fileno(stdout),_O_TEXT); #else setmode(fileno(stdout),_O_TEXT); #endif /* NT */ setbuf(stdout,NULL); fdispla = XYFD_S; } #ifdef OS2ONLY if ( IsOS2FullScreen() ) { extern int trueunderline; extern int trueblink; trueunderline = FALSE; trueblink = FALSE; } #endif /* OS2ONLY */ #ifdef NTSIG TlsIndex = TlsAlloc(); #endif /* NTSIG */ CreateAlarmMutex( FALSE ) ; #ifndef NOLOCAL CreateScreenMutex( FALSE ) ; CreateVscrnMutex( FALSE ) ; CreateVscrnDirtyMutex( FALSE ); CreateConnectModeMutex( FALSE ) ; #endif /* NOLOCAL */ CreateThreadMgmtMutex( FALSE ); CreateTCPIPMutex( FALSE ); CreateDebugMutex( FALSE ) ; CreateTelnetMutex( FALSE ) ; CreateCommMutex( FALSE ); #ifdef CK_SSL CreateSSLMutex( FALSE ); #endif /* CK_SSL */ CreateAlarmSem( FALSE ) ; #ifndef NOLOCAL CreateCommandModeSem( TRUE ); CreateTerminalModeSem( FALSE ); CreateAlarmSem( FALSE ) ; CreateRdComWrtScrThreadSem( FALSE ) ; CreateTermScrnUpdThreadSem( FALSE ) ; CreateConKbdHandlerThreadSem( FALSE ) ; CreateRdComWrtScrThreadDownSem( FALSE ) ; CreateTermScrnUpdThreadDownSem( FALSE ) ; CreateConKbdHandlerThreadDownSem( FALSE ) ; CreateKeyMapInitSem( FALSE ) ; CreateVscrnDirtySem( TRUE ); #endif /* NOLOCAL */ #ifndef NOSETKEY keymapinit(); /* Initialize key maps */ keynaminit(); /* Initialize key names */ #endif /* NOSETKEY */ #ifdef OS2MOUSE mousemapinit(-1,-1); /* Initialize mouse maps */ #endif /* OS2MOUSE */ #ifndef NOKVERBS initvik = 1; /* Remember that we did */ #endif /* NOKVERBS */ #ifdef NT #ifndef NOTERM tt_attr_bug = isWin95(); #endif /* NOTERM */ #ifndef KUI hInstance = GetModuleHandle(NULL) ; debug(F101,"hInstance","",hInstance); hwndConsole = GetConsoleHwnd() ; if ( isWin95() ) { MENUITEMINFO info; HMENU hMenu; hMenu = GetSystemMenu(hwndConsole, FALSE); info.cbSize = sizeof(info); RemoveMenu(hMenu, SC_CLOSE, MF_BYCOMMAND); DrawMenuBar(hwndConsole); CloseHandle(hMenu); } #endif /* KUI */ WinThreadInit = WindowThreadInit( (void *) hInstance ); #endif /* NT */ #ifdef OS2ONLY hab = WinInitialize(0); debug ( F101, "WinInitialize hab","",hab) ; ConnectToPM(); #endif /* OS2ONLY */ pid = os2getpid() ; DisableHardErrors() ; le_init(); alarm(0) ; /* We must start the alarm thread */ keybufinit() ; /* Must come before the KbdHandler */ #ifndef NOLOCAL #ifndef KUI #ifdef IKSD if ( !inserver ) #endif /* IKSD */ KbdHandlerInit() ; #endif /* KUI */ #endif /* NOLOCAL */ #ifdef NT CreateSerialMutex( FALSE ) ; #ifndef KUI #ifdef COMMENT VioHandle = GetStdHandle( STD_OUTPUT_HANDLE ) ; #else if ( !k95stdout ) VioHandle = CreateFile( "CONOUT$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0) ; #endif /* COMMENT */ #endif /* KUI */ DuplicateHandle(GetCurrentProcess(),GetCurrentThread(), GetCurrentProcess(),&tidCommand, 0,FALSE, DUPLICATE_SAME_ACCESS ); debug(F101,"Command Thread Handle","",tidCommand); CommandID = GetCurrentThreadId() ; debug(F101,"Command Thread ID","",CommandID) ; #endif /* NT */ #ifndef NOLOCAL #ifndef KUI if ( !k95stdout ) { #ifdef NT CK_VIDEOMODEINFO mi; #endif /* NT */ GetMode( &StartupConsoleModeInfo ); #ifdef NT if ( StartupConsoleModeInfo.col != StartupConsoleModeInfo.sbcol || StartupConsoleModeInfo.row != StartupConsoleModeInfo.sbrow ) { memcpy(&mi, &StartupConsoleModeInfo, sizeof(CK_VIDEOMODEINFO)); mi.sbcol = mi.col; mi.sbrow = mi.row; SetMode( &mi ); } #endif /* NT */ } #endif /* KUI */ #ifndef NT OpenClipboardServer() ; #endif /* NT */ getcmdcolor(); os2gettitle(szOldTitle, sizeof(szOldTitle)); debug(F110,"sysinit szOldTitle",szOldTitle,0); os2settitle("", TRUE); #endif /* NOLOCAL */ nOldCP = os2getcp(); switch (nOldCP) { case 437: tcsl = TX_CP437 ; fcharset = FC_CP437; break; case 850: tcsl = TX_CP850; fcharset = FC_CP850; break; case 858: tcsl = TX_CP858; fcharset = FC_CP850; break; case 855: tcsl = TX_CP855; break; case 856: tcsl = TX_CP856; break; case 852: tcsl = TX_CP852; fcharset = FC_CP852; break; case 862: tcsl = TX_CP862; fcharset = FC_CP862; break; case 866: tcsl = TX_CP866; fcharset = FC_CP866; break; case 1004: /* Windows 3.1 - supposed to be Latin-1 */ tcsl = TX_8859_1; fcharset = FC_1LATIN; break; case 1252: /* Win32 - like Latin-1 */ tcsl = TX_CP1252; fcharset = FC_1LATIN; break; #ifdef KUI default: tcsl = TX_CP1252; fcharset = FC_1LATIN; #else default: tcsl = TX_CP437 ; fcharset = FC_CP437; #endif } #ifdef __IBMC__ setvbuf(stdout, NULL, _IONBF, 0); setmode(1, _O_TEXT); #endif /* __IBMC__ */ #ifdef NT { char * p = GetLoadPath(); DWORD len; len = GetShortPathName(p,exedir,CKMAXPATH); if ( len == 0 || len > CKMAXPATH ) ckstrncpy(exedir, p, CKMAXPATH); } #else ckstrncpy(exedir, GetLoadPath(), CKMAXPATH); #endif /* NT */ if ( (ptr = strrchr(exedir, '\\')) != NULL ) *ptr = 0; for (ptr = exedir; *ptr; ptr++) /* Convert backslashes to slashes */ if (*ptr == '\\') *ptr = '/'; n = (int)strlen(exedir); /* Add slash to end if necessary */ if (n > -1 && n < CKMAXPATH) { if (exedir[n-1] != '/') { exedir[n] = '/'; exedir[n+1] = '\0'; } } #ifdef NT { char * p = zgtdir(); DWORD len; len = GetShortPathName(p,startupdir,CKMAXPATH); if ( len == 0 || len > CKMAXPATH ) ckstrncpy(startupdir, p, CKMAXPATH); } #else ckstrncpy(startupdir, zgtdir(), CKMAXPATH); #endif /* NT */ for (ptr = startupdir; *ptr; ptr++) { /* Convert backslashes to slashes */ if (*ptr == '\\') *ptr = '/'; } n = (int)strlen(startupdir); /* Add slash to end if necessary */ if (n > -1 && n < CKMAXPATH) { if (startupdir[n-1] != '/') { startupdir[n] = '/'; startupdir[n+1] = '\0'; } } ckstrncpy(ttnmsv, dftty, DEVNAMLEN+1); islocal = is_a_tty(0) && !ttiscom(0); if (!islocal) { os2setdtr(1); ttsettings(dfprty,stopbits); ttsetflow(flow); os2settimo(0,0); os2setcarr(ttcarr == CAR_ON); } else concooked(); /* Initialize keyboard */ #ifndef NOLOCAL if ( !k95stdout ) { extern int row_init, col_init; ttgcwsz() ; if ( !row_init && !col_init ) ttgwsiz() ; } debug(F100,"about to VscrnInit()","",0); /* Setup the Virtual Screens */ VscrnInit( VCMD ) ; VscrnInit( VTERM ) ; /* VscrnInit( VCS ) ; */ VscrnInit( VSTATUS ) ; settermtype(tt_type,1); #endif /* NOLOCAL */ #ifdef KUI /* This does more than just display the Splash Screen */ KuiInit( (void *) hInstance, &kui_init ); hwndConsole = KuiThreadInit( (void *) hInstance ) ; #endif /* KUI */ #ifdef CK_REXX os2rexxinit() ; #endif /* CK_REXX */ #ifdef CK_SECURITY ck_security_loaddll(); #endif /* CK_SECURITY */ #ifdef CK_TAPI debug(F100,"Initializing TAPI","",0); if ( WinThreadInit && !(startflags & 4)) { /* TAPI requires a Window Handle */ TAPIAvail = cktapiinit() ; if ( TAPIAvail ) { cktapiopen(); #ifndef NODIAL CopyTapiLocationInfoToKermitDialCmd(); #endif /* NODIAL */ } } #endif /* CK_TAPI */ #ifdef CK_XYZ #ifdef XYZ_DLL if ( !(startflags & 16) ) { debug(F100,"Initializing P_DLL","",0); p_avail = !load_p_dll() ; if ( !p_avail ) { bleep(BP_WARN); #ifdef NT printf("Unable to load P95.DLL - X,Y,Zmodem is unavailable\n"); #else /* NT */ printf("Unable to load P2.DLL - X,Y,Zmodem is unavailable\n"); #endif /* NT */ } } #endif /* XYZ_DLL */ #endif /* CK_XYZ */ #ifndef NOLOCAL #ifndef KUI #ifdef ONETERMUPD if ( !(inserver && k95stdout) ) tidTermScrnUpd = (TID) ckThreadBegin( &TermScrnUpd, THRDSTKSIZ, 0, TRUE, 0 ) ; #endif /* ONETERMUPD */ #endif /* KUI */ #endif /* NOLOCAL */ #ifndef NOTERM updanswerbk(); #endif /* NOTERM */ SetThreadPrty(priority,0); #ifdef NT #ifndef KUI debug(F100,"About to SetConsoleCtrlHandler","",0); if (SetConsoleCtrlHandler( (PHANDLER_ROUTINE) CloseHandler, TRUE )) debug(F100,"SetConsoleCtrlHandler succeeded","",0); else debug(F101,"SetConsoleCtrlHandler failed","",GetLastError()); #endif /* KUI */ #endif /* NT */ #ifndef KUI #ifdef OS2MOUSE if (tt_mouse) os2_mouseon() ; #endif /* OS2MOUSE */ #endif /* KUI */ if ( quitonbreak ) signal(SIGBREAK,term_signal); signal(SIGTERM,term_signal); #ifdef IKSD if ( !inserver ) #endif /* IKSD */ #ifndef NOLOCAL StartConnectThreads(); #endif /* NOLOCAL */ #ifdef CK_ENVIRONMENT { extern char tn_env_acct[], tn_env_disp[], tn_env_job[], tn_env_prnt[], tn_env_sys[], uidbuf[]; char *p; if (p = getenv("USER")) { ckstrncpy(uidbuf,p,UIDBUFLEN); } if (p = getenv("JOB")) { ckstrncpy(tn_env_job,p,64); } if (p = getenv("ACCT")) { ckstrncpy(tn_env_acct,p,64); } if (p = getenv("PRINTER")) { ckstrncpy(tn_env_prnt,p,64); } if (p = getenv("DISPLAY")) { ckstrncpy(tn_env_disp,p,64); } #ifdef NT strcpy(tn_env_sys,"WIN32"); #else strcpy(tn_env_sys,"OS2"); #endif /* NT */ } #endif /* CK_ENVIRONMENT */ #ifdef CK_SNDLOC { extern char * tn_loc; char *p; if (p = getenv("LOCATION")) makestr(&tn_loc,p); } #endif /* CK_SNDLOC */ #ifndef NOLOCAL os2InitFromRegistry(); #endif /* NOLOCAL */ #ifdef NT if ( isWin95() ) { #ifdef BETADEBUG Win95DisplayLocale(); #endif /* BETADEBUG */ Win95AltGrInit(); } #endif /* NT */ #ifdef NETCONN netinit(); #endif /* NETCONN */ #ifdef IKSD if ( !inserver ) #endif /* ISKD */ ckstrncpy( uidbuf, GetLocalUser(), UIDBUFLEN ); #ifdef NT #ifdef BETADEBUG printf("Console Window Handle=0x%x\n",hwndConsole); printf("WM_GETFONT=0x%x\n",(ULONG)SendMessage(hwndConsole,WM_GETFONT,0,0)); #endif /* BETADEBUG */ #endif /* NT */ #ifdef OS2ONLY if (getenv ("TZ") == NULL) /* Default New York time. */ { printf("Warning: TZ environment variable not set. Using EST5EDT.\n\n"); bleep(BP_WARN); _timezone = 18000; _daylight = 1; _tzname[0] = "EST"; _tzname[1] = "EDT"; } else #endif /* OS2ONLY */ _tzset() ; #ifdef NT if ( isWin95() ) { /* Check TMP,TEMP,K95TMP */ char * p = NULL; int warning = 0; p = getenv("K95TMP"); if ( p ) { if ( strlen(p) == 3 && p[1] == ':' && p[2] == '\\' ) { printf("\n WARNING: K95TMP = %s\n",p); warning = 1; } } p = getenv("TEMP"); if ( p ) { if ( strlen(p) == 3 && p[1] == ':' && p[2] == '\\' ) { if ( !warning ) printf("\n"); printf(" WARNING: TEMP = %s\n",p); warning = 1; } } p = getenv("TMP"); if ( p ) { if ( strlen(p) == 3 && p[1] == ':' && p[2] == '\\' ) { if ( !warning ) printf("\n"); printf(" WARNING: TMP = %s\n",p); warning = 1; } } if ( warning ) { printf(" The directory for temporary files in Windows 95 must be a subdirectory\n"); printf(" to avoid problems with Kerberos, Tapi, and other subsystems.\n\n"); bleep(BP_WARN); } } /* Check to make sure we have the default directory heirarchy */ if ( !inserver ) firsttime(); #endif /* NT */ #ifndef NOLOCAL VscrnForceFullUpdate(); /* Just in case command screen did not write */ #endif /* NOLOCAL */ SysInited = 1; debug(F100,"sysinit complete","",0); chkexp(); return(0); } /* S Y S C L E A N U P -- System-dependent program cleanup. */ int syscleanup() { extern int printtimo; if (!SysInited) return(0); SysInited = 0; printtimo = 0; /* Turn off delayed print closure */ printeroff(); /* Close printer if open */ #ifdef NT #ifdef NEWRDCH OverlappedReadCleanup(); #endif /* NEWRDCH */ #endif /* NT */ #ifdef COMMENt #ifndef NOLOCAL StopConnectThreads(0); #endif /* NOLOCAL */ #endif /* COMMENT */ #ifdef NT #ifdef CK_TAPI if ( TAPIAvail ) { debug(F100,"Close TAPI starting","",0); cktapiclose(); cktapiunload() ; debug(F100,"Close TAPI done","",0); } #endif /* CK_TAPI */ #ifndef KUI WindowThreadClose(); #endif /* KUI */ #endif /* NT */ #ifdef KUI KuiThreadCleanup( (void *) hInstance ) ; #endif /* KUI */ #ifdef CK_SECURITY ck_security_unloaddll(); #endif /* CK_SECURITY */ #ifdef NETCONN netcleanup() ; #endif /* NETCONN */ os2settitle(szOldTitle,FALSE); os2setcp(nOldCP); signal(SIGINT, SIG_DFL); signal(SIGBREAK, SIG_DFL); signal(SIGTERM, SIG_DFL); #ifndef KUI #ifndef NOLOCAL if ( !k95stdout ) { #ifdef NT if ( StartupConsoleModeInfo.sbrow != VscrnGetHeight(VCMD) || StartupConsoleModeInfo.sbcol != VscrnGetWidth(VCMD) ) { clearcmdscreen(); SetMode( &StartupConsoleModeInfo ); } #else /* NT */ if ( StartupConsoleModeInfo.row != VscrnGetHeight(VCMD) || StartupConsoleModeInfo.col != VscrnGetWidth(VCMD) ) { clearcmdscreen(); SetMode( &StartupConsoleModeInfo ); } #endif /* NT */ } KbdHandlerCleanup() ; /* must come after os2settitle */ debug(F100,"KbdHandlerCleanup done","",0); if ( isWin95() ) /* Win95 needs time to let the kbdthread die */ msleep(50); keybufcleanup() ; debug(F100,"keybufcleanup done","",0); #endif /* NOLOCAL */ le_clean(); CloseAlarmMutex() ; #ifndef NOLOCAL CloseScreenMutex() ; CloseVscrnMutex() ; CloseVscrnDirtyMutex() ; CloseConnectModeMutex() ; CloseCommandModeSem() ; CloseTerminalModeSem() ; #endif /* NOLOCAL */ CloseCommMutex(); CloseThreadMgmtMutex(); CloseDebugMutex() ; CloseTelnetMutex() ; CloseTCPIPMutex() ; CloseAlarmSem() ; #ifdef CK_SSL CloseSSLMutex() ; #endif /* CK_SSL */ #ifndef NOLOCAL CloseRdComWrtScrThreadSem() ; CloseConKbdHandlerThreadSem() ; CloseTermScrnUpdThreadSem() ; CloseRdComWrtScrThreadDownSem() ; CloseConKbdHandlerThreadDownSem() ; CloseTermScrnUpdThreadDownSem() ; CloseKeyMapInitSem() ; CloseVscrnDirtySem() ; #endif /* NOLOCAL */ #endif /* KUI */ #ifdef NT CloseSerialMutex() ; if ( !stdout ) CloseHandle(VioHandle); VioHandle = 0 ; #endif /* NT */ CloseThreadMgmtMutex() ; debug(F100,"Close Mutexes and Semaphores done","",0); #ifndef NOLOCAL #ifndef NT CloseClipboardServer() ; debug(F100,"Close Clipboard done","",0); #endif /* NT */ #endif /* NOLOCAL */ #ifdef NTSIG TlsFree(TlsIndex); TlsIndex = 0; debug(F100,"Free Thread Local Memory done","",0); #endif /* NTSIG */ #ifdef OS2ONLY WinTerminate(hab) ; DisconnectFromPM(); #endif /* OS2ONLY */ #ifdef CK_XYZ #ifdef XYZ_DLL if ( p_avail ) unload_p_dll() ; debug(F100,"Zmodem released","",0); #endif /* XYZ_DLL */ #endif /* CK_XYZ */ return(0); } /* Timeout handler for communication line input functions */ static ckjmpbuf kbbuf; /* Timeout longjmp targets */ static ckjmpbuf sjbuf; #ifndef __EMX__ unsigned alarm(unsigned); /* Prototype */ #endif /* __EMX__ */ #ifdef OS2 SIGTYP (* volatile saval)(int) = NULL; /* For saving alarm() handler */ #else /* OS2 */ SIGTYP (*saval)(int) = NULL; /* For saving alarm() handler */ #endif /* OS2 */ VOID ttimoff() { /* Turn off any timer interrupts */ int xx; xx = alarm(0); if (saval) { /* Restore any previous */ signal(SIGALRM,saval); /* alarm handler. */ saval = NULL; } else { signal(SIGALRM,SIG_IGN); } } /* O S 2 S E T T I M O -- set read and write timeouts */ int os2settimo(int spd, int modem) { #ifdef NT COMMTIMEOUTS timeouts ; #endif /* NT */ debug(F111,"os2settimo","spd",spd); debug(F111,"os2settimo","modem",modem); #ifdef NT /* Calculate the max overlapeed writes for this connection */ /* A rethinking of how this number is calculated. * The fastest modem connection is 53,000 bits per second (6625 bytes per second) * the largest kermit packet is 9024 bytes. Therefore, we can never process more * than one write/second therefore it makes no sense for this value to be anything * but 2 for modems. For non-modems, use bytes/sec/max-packet */ if ( modem > 0 ) maxow = 2; else maxow = 1 + (spd / 8 / 9024) ; if ( maxow > maxow_usr ) maxow = maxow_usr; #ifdef CK_TAPI if ( tttapi && !tapipass ) { HANDLE hModem = NULL; LPDEVCFG lpDevCfg = NULL; LPCOMMCONFIG lpCommConfig = NULL; LPMODEMSETTINGS lpModemSettings = NULL; DCB * lpDCB = NULL; hModem = GetModemHandleFromLine( (HLINE) 0 ); if ( hModem == NULL ) return(-1); if (!GetCommTimeouts( hModem, &timeouts )) { CloseHandle( hModem ); return -1 ; } /* Timeouts for Overlapped I/O from MS TTY.C example */ timeouts.ReadIntervalTimeout = MAXDWORD; timeouts.ReadTotalTimeoutMultiplier = MAXDWORD /* 0 */ ; timeouts.ReadTotalTimeoutConstant = 1 ; timeouts.WriteTotalTimeoutMultiplier = (modem > 0 ? 250 : (2500000 / spd)); timeouts.WriteTotalTimeoutConstant = (modem > 0 ? 90000 : 0); if (!SetCommTimeouts( hModem, &timeouts )) { CloseHandle( hModem ); return -1 ; } CloseHandle(hModem); return(0); } #endif /* CK_TAPI */ if (!GetCommTimeouts( (HANDLE) ttyfd, &timeouts )) return -1 ; if ( deblog ) debugComm( "os2settimo initial values", NULL, &timeouts ); /* Timeouts for Overlapped I/O from MS TTY.C example */ timeouts.ReadIntervalTimeout = MAXDWORD; timeouts.ReadTotalTimeoutMultiplier = MAXDWORD /* 0 */; timeouts.ReadTotalTimeoutConstant = 1 ; timeouts.WriteTotalTimeoutMultiplier = (modem > 0 ? 250 : (2500000 / spd)); timeouts.WriteTotalTimeoutConstant = (modem > 0 ? 90000 : 0); debug(F111,"os2settimo SetCommTimeouts","WriteTotalTimeoutMultiplier", timeouts.WriteTotalTimeoutMultiplier); debug(F111,"os2settimo SetCommTimeouts","WriteTotalTimeoutConstant", timeouts.WriteTotalTimeoutConstant); if (!SetCommTimeouts( (HANDLE) ttyfd, &timeouts )) return -1 ; #else /* not NT */ /* Get the current settings */ if (DosDevIOCtl(&ttydcb,sizeof(ttydcb),NULL,0, ASYNC_GETDCBINFO,IOCTL_ASYNC,ttyfd)) return(-1); /* set write timeout */ ttydcb.fbTimeout &= ~MODE_NO_WRITE_TIMEOUT; #ifdef COMMENT ttydcb.usWriteTimeout = 15 * 100; /* 15-second timeout */ #else ttydcb.usWriteTimeout = ((100 / spd) + 1) * MAXSP + (modem > 0 ? 60 * 100 : 0); #endif /* COMMENT */ /* Read "some" data from line mode */ ttydcb.fbTimeout &= ~MODE_NOWAIT_READ_TIMEOUT; ttydcb.fbTimeout |= MODE_WAIT_READ_TIMEOUT; /* Set DCB */ if (DosDevIOCtl(NULL,0,&ttydcb,sizeof(ttydcb), ASYNC_SETDCBINFO,IOCTL_ASYNC,ttyfd)) return(-1); #endif /* NT */ return(0); } /* T T S E T F L O W -- set flow state of tty */ int ttsetflow(int nflow) { #ifdef NT DWORD mode ; #endif /* NT */ debug(F101,"setflow","",nflow) ; #ifdef TN_COMPORT if (network) return(tnsetflow(nflow)); #endif /* TN_COMPORT */ #ifdef NT #ifdef CK_TAPI if ( tttapi && !tapipass ) { HANDLE hModem = NULL; LPDEVCFG lpDevCfg = NULL; LPCOMMCONFIG lpCommConfig = NULL; LPMODEMSETTINGS lpModemSettings = NULL; DCB * lpDCB = NULL; hModem = GetModemHandleFromLine( (HLINE) 0 ); if ( hModem == NULL ) return(-1); if (!cktapiGetModemSettings(&lpDevCfg,&lpModemSettings, &lpCommConfig,&lpDCB)) { CloseHandle( hModem ); return -1 ; } if ( deblog ) debugComm( "ttsetflow initial values", lpDCB, NULL ); lpDCB->fDsrSensitivity = FALSE ; lpDCB->fDtrControl = DTR_CONTROL_ENABLE ; switch(nflow) { case FLO_XONX: lpDCB->fOutX = TRUE ; lpDCB->fInX = TRUE ; lpDCB->fRtsControl = RTS_CONTROL_ENABLE ; lpDCB->fOutxCtsFlow = FALSE ; lpDCB->fTXContinueOnXoff = /* TRUE */ FALSE ; break; case FLO_RTSC: lpDCB->fOutX = FALSE ; lpDCB->fInX = FALSE ; lpDCB->fRtsControl = RTS_CONTROL_HANDSHAKE ; lpDCB->fOutxCtsFlow = TRUE ; lpDCB->fTXContinueOnXoff = TRUE ; break; case FLO_KEEP: /* leave things exactly as they are */ break; case FLO_NONE: /* turn off all flow control completely */ lpDCB->fOutX = FALSE ; lpDCB->fInX = FALSE ; lpDCB->fRtsControl = RTS_CONTROL_ENABLE ; lpDCB->fOutxCtsFlow = FALSE ; lpDCB->fTXContinueOnXoff = TRUE ; break; } lpDCB->XonChar = 0x11 ; lpDCB->XoffChar = 0x13; lpDCB->XonLim = 10 ; lpDCB->XoffLim = 10 ; if (!cktapiSetModemSettings(lpDevCfg,lpCommConfig)) { CloseHandle( hModem ); return -1 ; } if ( lpDCB->fRtsControl != RTS_CONTROL_HANDSHAKE ) EscapeCommFunction( hModem, SETRTS ) ; CloseHandle(hModem); return(0); } #endif /* CK_TAPI */ ttydcb.DCBlength = sizeof(DCB); if (!GetCommState( (HANDLE) ttyfd, &ttydcb )) return -1 ; if ( deblog ) debugComm( "ttsetflow initial values", &ttydcb, NULL ); ttydcb.fDsrSensitivity = FALSE ; ttydcb.fDtrControl = DTR_CONTROL_ENABLE ; switch(nflow) { case FLO_XONX: ttydcb.fOutX = TRUE ; ttydcb.fInX = TRUE ; ttydcb.fRtsControl = RTS_CONTROL_ENABLE ; ttydcb.fOutxCtsFlow = FALSE ; ttydcb.fTXContinueOnXoff = /* TRUE */ FALSE ; break; case FLO_RTSC: ttydcb.fOutX = FALSE ; ttydcb.fInX = FALSE ; ttydcb.fRtsControl = RTS_CONTROL_HANDSHAKE ; ttydcb.fOutxCtsFlow = TRUE ; ttydcb.fTXContinueOnXoff = TRUE ; break; case FLO_KEEP: /* leave things exactly as they are */ break; case FLO_NONE: /* turn off all flow control completely */ ttydcb.fOutX = FALSE ; ttydcb.fInX = FALSE ; ttydcb.fRtsControl = RTS_CONTROL_ENABLE ; ttydcb.fOutxCtsFlow = FALSE ; ttydcb.fTXContinueOnXoff = TRUE ; break; } ttydcb.XonChar = 0x11 ; ttydcb.XoffChar = 0x13; ttydcb.XonLim = 10 ; ttydcb.XoffLim = 10 ; if (!SetCommState( (HANDLE) ttyfd, &ttydcb )) return -1 ; if ( ttydcb.fRtsControl != RTS_CONTROL_HANDSHAKE ) EscapeCommFunction( (HANDLE) ttyfd, SETRTS ) ; #else /* not NT */ /* Get the current settings */ if (DosDevIOCtl(&ttydcb,sizeof(ttydcb),NULL,0, ASYNC_GETDCBINFO,IOCTL_ASYNC,ttyfd)) return(-1); ttydcb.fbCtlHndShake = MODE_DTR_CONTROL; ttydcb.fbFlowReplace &= ~(MODE_AUTO_RECEIVE | MODE_AUTO_TRANSMIT | /* clear only a few */ MODE_RTS_CONTROL | MODE_RTS_HANDSHAKE); if (nflow == FLO_XONX) { ttydcb.fbFlowReplace |= (MODE_AUTO_RECEIVE | MODE_AUTO_TRANSMIT | MODE_RTS_CONTROL); } else if (nflow == FLO_RTSC) { ttydcb.fbCtlHndShake |= MODE_CTS_HANDSHAKE; ttydcb.fbFlowReplace |= MODE_RTS_HANDSHAKE; } else if ( nflow != FLO_KEEP ) { ttydcb.fbFlowReplace |= MODE_RTS_CONTROL; } /* Set DCB */ if (DosDevIOCtl(NULL,0,&ttydcb,sizeof(ttydcb), ASYNC_SETDCBINFO,IOCTL_ASYNC,ttyfd)) return(-1); if (nflow != FLO_RTSC && nflow != FLO_KEEP) {/* keep RTS permanently on */ MODEMSTATUS ms; UINT data; ms.fbModemOn = RTS_ON; ms.fbModemOff = 255; DosDevIOCtl(&data,sizeof(data),&ms,sizeof(ms), ASYNC_SETMODEMCTRL,IOCTL_ASYNC,ttyfd); } #endif /* NT */ return(0); } static int os2setcarr(int ncarr) { debug(F101,"setcarr","",ncarr) ; #ifdef NT #ifdef COMMENT ttydcb.DCBlength = sizeof(DCB); if (!GetCommState( (HANDLE) ttyfd, &ttydcb )) return -1 ; if ( deblog ) debugComm( "os2setcarr initial values", &ttydcb, NULL ); if (!SetCommState( (HANDLE) ttyfd, &ttydcb )) return -1 ; #endif /* COMMENT */ #else /* not NT */ /* Get the current settings */ if (DosDevIOCtl(&ttydcb,sizeof(ttydcb),NULL,0, ASYNC_GETDCBINFO,IOCTL_ASYNC,ttyfd)) return(-1); if (ncarr) ttydcb.fbCtlHndShake |= MODE_DCD_HANDSHAKE; else ttydcb.fbCtlHndShake &= ~MODE_DCD_HANDSHAKE; /* Set DCB */ if (DosDevIOCtl(NULL,0,&ttydcb,sizeof(ttydcb), ASYNC_SETDCBINFO,IOCTL_ASYNC,ttyfd)) return(-1); #endif return(0); } /* O S 2 S E T D T R -- set state of DTR signal */ static int os2setdtr(int on) { #ifdef NT DWORD mode = 0; #else /* NT */ MODEMSTATUS ms; UINT data; #endif /* NT */ debug(F101,"setdtr","",on); if (ttyfd == -1 #ifdef CK_TAPI || (tttapi && ttyfd == -2) #endif /* CK_TAPI */ ) return(0); #ifdef TN_COMPORT if (network) { if (istncomport()) { return(tnc_set_dtr_state(on)); } else return(-1); } #endif /* TN_COMPORT */ #ifdef NT #ifdef CK_TAPI if ( tttapi && !tapipass ) { HANDLE hModem = NULL; hModem = GetModemHandleFromLine( (HLINE) 0 ); if ( hModem == NULL ) return(-1); mode = on ? SETDTR : CLRDTR ; if (!EscapeCommFunction( hModem, mode )) { int error = GetLastError() ; debug(F101,"os2setdtr EscapeCommFunction failed","",error) ; CloseHandle( hModem ); return -1 ; } CloseHandle( hModem ); return(0); } #endif /* CK_TAPI */ mode = on ? SETDTR : CLRDTR ; if (!EscapeCommFunction( (HANDLE) ttyfd, mode )) { int error = GetLastError() ; debug(F101,"os2setdtr EscapeCommFunction failed","",error) ; return -1 ; } return 0; #else /* NT */ ms.fbModemOn = on ? DTR_ON : 0; ms.fbModemOff = on ? 255 : DTR_OFF; return(DosDevIOCtl(&data,sizeof(data),&ms,sizeof(ms), ASYNC_SETMODEMCTRL,IOCTL_ASYNC,ttyfd)); #endif } /* T T S E T T I N G S -- Set the device driver parity and stop bits */ static int ttsettings(int par, int stop) { #ifdef OS2ONLY LINECONTROL lc; #endif /* OS2ONLY */ #ifdef TN_COMPORT if (network) return(tnsettings(par,stop)); #endif /* TN_COMPORT */ #ifdef NT #ifdef CK_TAPI if ( tttapi && !tapipass ) { HANDLE hModem = NULL; LPDEVCFG lpDevCfg = NULL; LPCOMMCONFIG lpCommConfig = NULL; LPMODEMSETTINGS lpModemSettings = NULL; DCB * lpDCB = NULL; hModem = GetModemHandleFromLine( (HLINE) 0 ); if ( hModem == NULL ) return(-1); if (!cktapiGetModemSettings(&lpDevCfg,&lpModemSettings, &lpCommConfig,&lpDCB)) { CloseHandle( hModem ); return -1 ; } lpDCB->fBinary = TRUE ; lpDCB->fErrorChar = FALSE ; lpDCB->fAbortOnError = FALSE ; lpDCB->ErrorChar = '?' ; if (hwparity) { switch (hwparity) { case 'e': lpDCB->Parity = EVENPARITY ; break; case 'o': lpDCB->Parity = ODDPARITY ; break; case 'm': lpDCB->Parity = MARKPARITY ; break; case 's': lpDCB->Parity = SPACEPARITY ; break; default: lpDCB->Parity = NOPARITY ; } lpDCB->fParity = TRUE; lpDCB->ByteSize = 8; ttprty = 0; } else { lpDCB->Parity = NOPARITY; lpDCB->fParity = FALSE; lpDCB->ByteSize = 8; ttprty = par; } switch(stop) { case 2: lpDCB->StopBits = TWOSTOPBITS ; break; case 1: lpDCB->StopBits = ONESTOPBIT ; break; default: ; /* no change */ } if (!cktapiSetModemSettings(lpDevCfg,lpCommConfig)) { CloseHandle( hModem ); return -1 ; } CloseHandle( hModem ); return (0); } #endif /* CK_TAPI */ ttydcb.DCBlength = sizeof(DCB); if (!GetCommState( (HANDLE) ttyfd, &ttydcb )) return -1 ; if ( deblog ) debugComm( "ttsettings initial values", &ttydcb, NULL ); ttydcb.fBinary = TRUE ; ttydcb.fErrorChar = FALSE ; ttydcb.fAbortOnError = FALSE ; ttydcb.ErrorChar = '?' ; if (hwparity) { switch (hwparity) { case 'e': ttydcb.Parity = EVENPARITY ; break; case 'o': ttydcb.Parity = ODDPARITY ; break; case 'm': ttydcb.Parity = MARKPARITY ; break; case 's': ttydcb.Parity = SPACEPARITY ; break; default: ttydcb.Parity = NOPARITY ; } ttydcb.fParity = TRUE; ttydcb.ByteSize = 8; ttprty = 0; } else { ttydcb.Parity = NOPARITY; ttydcb.fParity = FALSE; ttydcb.ByteSize = 8; ttprty = par; } switch(stop) { case 2: ttydcb.StopBits = TWOSTOPBITS ; break; case 1: ttydcb.StopBits = ONESTOPBIT ; break; default: ; /* no change */ } if (!SetCommState( (HANDLE) ttyfd, &ttydcb )) return -1 ; #else /* NT */ if (DosDevIOCtl(&lc,sizeof(lc),NULL,0, ASYNC_GETLINECTRL,IOCTL_ASYNC,ttyfd)) return(-1); /* Get line */ #ifdef HWPARITY if (hwparity) { switch (hwparity) { case 'o': lc.bDataBits = 8; /* Data bits */ lc.bParity = 1; break; case 'e': lc.bDataBits = 8; /* Data bits */ lc.bParity = 2; break; case 'm': lc.bDataBits = 8; /* Data bits */ lc.bParity = 3; break; case 's': lc.bDataBits = 8; /* Data bits */ lc.bParity = 4; break; default : lc.bDataBits = 8; /* Data bits */ lc.bParity = 0; /* No parity */ } ttprty = 0; } else #endif /* HWPARITY */ { /* Always let Kermit handle parity itself */ lc.bDataBits = 8; /* Data bits */ lc.bParity = 0; /* No parity */ ttprty = par; } switch (stop) { case 2: lc.bStopBits = 2; /* Two stop bits */ break; case 1: lc.bStopBits = 0; /* One stop bit */ break; default: /* No change */ break; } if (DosDevIOCtl(NULL,0,&lc,sizeof(lc), ASYNC_SETLINECTRL,IOCTL_ASYNC,ttyfd)) return(-1); /* Set line */ #endif /* NT */ return(0); } void ttname2title(char * ttname) { /* Set session title */ char * p, name[72]; /* in window list. */ p = name ; ckstrncpy(name, ttname, 72); while (*p) { /* Uppercase it for emphasis. */ if (islower(*p)) *p = toupper(*p); p++; } os2settitle((char *) name, 1); } /* T T O P E N -- Open a tty for exclusive access. */ /* Returns 0 on success, -1 on failure. */ /* If called with lcl < 0, sets value of lcl as follows: 0: the terminal named by ttname is the job's controlling terminal. 1: the terminal named by ttname is not the job's controlling terminal. But watch out: if a line is already open, or if requested line can't be opened, then lcl remains (and is returned as) -1. */ ttopen(char *ttname, int *lcl, int modem, int spare) { char *x; extern char* ttyname(); int rc=0 ; U_INT action, res; #ifdef NT int i ; SECURITY_ATTRIBUTES security ; char portname[267]; #endif debug(F111,"ttopen DEVNAMLEN","",DEVNAMLEN); debug(F111,"ttopen entry modem",ttname,modem); debug(F101,"ttopen ttyfd","",ttyfd); debug(F111,"ttopen ttnmsv",ttnmsv,(int) strlen(ttnmsv)); debug(F111,"ttopen ttname",ttname,(int) strlen(ttname)); rdchbuf.length = rdchbuf.index = 0; if (ttyfd != -1 #ifdef COMMENT #ifdef CK_TAPI && ttyfd != -2 #endif /* CK_TAPI */ #endif /* COMMENT */ ) { /* if device already opened */ if ((ttname[0] == '_' || ttname[0] == '$' || ttname[0] == '!') && ttyfd == atoi(&ttname[1])) return(0); #ifdef NT /* Support for Pragma Systems Telnet/Terminal Servers */ if (!strcmp(ttname,"0")) { char * p = getenv("PRAGMASYS_INETD_SOCK"); if ( p && ttyfd == atoi(p)) return(0); } #endif /* NT */ if ( strncmp(ttname,ttnmsv,DEVNAMLEN) ) { /* new & old names equal? */ debug(F111,"ttopen closing",ttname,ttyfd); ttclos(0); /* no, close old ttname, open new */ } else { /* else same, ignore this call, */ debug(F111,"ttopen already open",ttname,ttyfd); ttname2title(ttname); /* This next line is a work around in case 'local' gets set */ /* somehow to remote mode which will result in file transfers */ /* failing. */ if (*lcl == -1) { #ifdef IKSD if ( inserver ) *lcl = 0; else #endif /* IKSD */ *lcl = 1; /* we can't open in remote mode */ } return(0); /* and return. */ } } wasclosed = 0; ishandle = 0; ttmdm = modem; /* Make this available to other fns */ /* We need to catch the sequence of commands: * set net type ... * set host ... * set modem type ... * * since that will reset the 'modem' variable to a positive * value. */ if (network && ckstrcmp(ttname,ttnmsv,-1,0) || modem < 0) { network = 1; } else { network = 0; } tt_mode = TT_MODE_NONE; #ifdef NT /* Support for Pragma Systems Telnet/Terminal Servers */ if ( !strcmp(ttname,"0") ) { char * p = getenv("PRAGMASYS_INETD_SOCK"); if ( p ) { /* We are running under PragmaSys Telnetd/Inetd */ extern int reliable; debug(F110,"PRAGMASYS_INETD_SOCK",p,0); ckstrncpy(ttnmsv, ttname, DEVNAMLEN); /* Keep copy of name locally. */ ttyfd = atoi(p); if ( p = getenv("PRAGMASYS_COMPORT") ) { /* * The PragaSys sample code puts a DuplicateHandle here */ debug(F110,"PRAGMASYS_COMPORT",p,0); network = 0; reliable = 0; } else { network = 1; nettype = NET_TCPB; ttnproto = NP_TELNET; reliable = 1; } *lcl = 0; return(0); } } #endif /* NT */ #ifndef NOTERM doreset(1); /* Soft Reset the terminal - clrscreen && home cursor */ #endif /* NOTERM */ #ifdef SESLIMIT start_time = time( NULL ) ; warn[0] = warn[1] = warn[2] = warn[3] = 1; #endif /* SESLIMIT */ #ifdef NETCONN #ifdef TCPSOCKET { extern int tcpsrv_fd; if ( tcpsrv_fd != -1 && ttname[0] != '*') tcpsrv_close(); } #endif /* TCPSOCKET */ if (network) { debug(F100,"ttopen calling os2_netflui()","",0); os2_netflui(); debug(F100,"ttopen calling os2_netopen()","",0); rc = os2_netopen(ttname, lcl, modem < 0 ? -modem : modem); debug(F111,"ttname changed to",ttname,(int) strlen(ttname)); if (!rc) { ckstrncpy(ttnmsv, ttname, DEVNAMLEN); /* Keep copy of name locally. */ ttname2title(ttname); } } else #endif /* NETCONN */ { #ifdef CK_TAPI if ( tttapi ) /* We are trying to open a TAPI Line Device */ { rc = tapi_open(ttname) ; debug(F111,"tapi_open rc",ttname,rc); ckstrncpy(ttnmsv, ttname, DEVNAMLEN ); if (!rc) { *lcl = 1; /* Assume it's local. */ #ifdef COMMENT /* ttmdm is now set in tapi_open() */ if (!tapipass) ttmdm = 38; /* ckudia.c */ #endif /* COMMENT */ } } else #endif /* CK_TAPI */ { /* This code lets you give Kermit an open file descriptor for a serial communication device, rather than a device name. Kermit assumes that the line is already open, conditioned with the right parameters, etc. */ for (x = ttname; isdigit(*x); x++) ; /* Check for all digits */ if (*x == '\0') { ttyfd = atoi(ttname); ishandle = 1; exithangup = 0; /* Do not close on exit */ *lcl = 1; /* Assume it's local. */ if (ttiscom(ttyfd)) { rc = savetty(); if ( !rc ) ttname2title(ttname); return rc; } ttyfd = -1; wasclosed = 1; return(-4); } #ifdef NT memset(&security, 0, sizeof(SECURITY_ATTRIBUTES)); security.nLength = sizeof(SECURITY_ATTRIBUTES); security.lpSecurityDescriptor = NULL ; security.bInheritHandle = TRUE ; /* * If DOS device names terminate with backslash on Windows 95/98 * K95 will crash. */ if ( isWin95() && (!ckstrcmp(ttname,"lpt",3,0) || !ckstrcmp(ttname,"com",3,0) || !ckstrcmp(ttname,"prn",3,0)) ) { while ( ttname[strlen(ttname)-1] == '\\' ) ttname[strlen(ttname)-1] = '\0'; } if ( ttname[0] == '\\' || ttname[strlen(ttname)-1] == '$' ) ckstrncpy(portname,ttname,267); else { strcpy(portname,"\\\\.\\"); ckstrncpy(&portname[4],ttname,263); } if ( (HANDLE)(ttyfd = (int) CreateFile(portname, GENERIC_READ | GENERIC_WRITE, ttshare ? (FILE_SHARE_READ | FILE_SHARE_WRITE) : 0, &security, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL)) == INVALID_HANDLE_VALUE) { debug(F111,"ttopen CreateFile","GetLastError",GetLastError()); ttyfd = -1 ; wasclosed = 1; return -1 ; } #else /* not NT */ if (ttslip) { rc = SlipOpen( ttname ) ; if ( rc ) { PPPSlipClose() ; ttyfd = -1 ; wasclosed = 1; return -6 ; } } else if ( ttppp ) { rc = PPPOpen( ttname ) ; if ( rc ) { PPPSlipClose() ; ttyfd = -1 ; wasclosed = 1; return -6 ; } } if (res = DosOpen(ttname,(PHFILE)&ttyfd,&action,0L,0,FILE_OPEN, OPEN_ACCESS_READWRITE | ( (ttshare || ttppp || ttslip) ? OPEN_SHARE_DENYNONE : OPEN_SHARE_DENYREADWRITE) | OPEN_FLAGS_FAIL_ON_ERROR ,0L)) { debug(F111,"ttopen DosOpen","res",res); if (ttslip) PPPSlipClose() ; ttyfd = -1; wasclosed = 1; return((res == ERROR_SHARING_VIOLATION) ? -5 : -1); } #endif /* NT */ ckstrncpy(ttnmsv, ttname, DEVNAMLEN ); } debug(F111,"ttopen ok",ttname,*lcl); /* Caller wants us to figure out if line is controlling tty */ if (*lcl == -1) { *lcl = 1; /* Can never transfer with console */ } if (*lcl) { if (!ttiscom(ttyfd)) { /* Not a serial port */ ttclos(0); return(-4); } #ifdef NT #ifdef BETADEBUG DisplayCommProperties((HANDLE)ttyfd); #endif /* BETADEBUG */ SetCommMask( (HANDLE) ttyfd, EV_RXCHAR ) ; SetupComm( (HANDLE) ttyfd, 20000, 20000 ) ; PurgeComm( (HANDLE) ttyfd, PURGE_RXABORT | PURGE_TXABORT | PURGE_RXCLEAR | PURGE_TXCLEAR ); #endif /* NT */ savetty(); ttprty = dfprty; /* Make parity the default parity */ if (ttsettings(ttprty,stopbits)) return(-1); rc = ttflui(); #ifdef NT #ifdef NEWRDCH /* Reset the Overlapped I/O structures */ OverlappedWriteInit(); OverlappedReadInit(); #endif #endif } } if ( !rc ) ttname2title(ttname); return rc; } /* T T I S C O M -- Is the given handle an open COM port? */ ttiscom(int f) { #ifdef NT DCB testdcb; #else /* NT */ DCBINFO testdcb; #endif /* NT */ #ifdef COMMENT #ifdef TN_COMPORT /* TELNET REMOTE COM PORT option means we are a com port */ if (istncomport()) return(1); #endif /* TN_COMPORT */ #endif /* COMMENT */ #ifdef NT #ifdef CK_TAPI if ( tttapi && !tapipass ) { HANDLE hModem = NULL; hModem = GetModemHandleFromLine( (HLINE) 0 ); if ( hModem == NULL ) return(0); memset( ttycfg, 0, 1024 ); ttycfg->dwSize = 1024; cfgsize = 1024; if (!GetCommConfig( hModem, ttycfg, &cfgsize )) { CloseHandle(hModem); return 0 ; } CloseHandle( hModem ); return (1); } #endif /* CK_TAPI */ testdcb.DCBlength = sizeof(DCB); if (!GetCommState( (HANDLE) ttyfd, &testdcb)) return(0); #else /* NT */ /* Read DCB */ if (DosDevIOCtl(&testdcb,sizeof(testdcb),NULL,0, ASYNC_GETDCBINFO,IOCTL_ASYNC,f)) { return( 0 ); /* Bad, not a serial port */ } #endif /* NT */ return( 1 ); /* Good */ } /* T T C L O S -- Close the TTY. */ ttclos(int spare) { int rc = 0; if (ttyfd == -1 #ifdef CK_TAPI || (!tttapi && ttyfd == -2) #endif /* CK_TAPI */ ) return(0); /* Wasn't open. */ #ifdef NT /* Support for Pragma Systems Telnet/Terminal Servers */ { char * p = getenv("PRAGMASYS_INETD_SOCK"); if ( p && ttyfd == atoi(p)) { /* We are running under PragmaSys Telnetd/Inetd */ ttyfd = -1; wasclosed = 1; return(0); } } #endif /* NT */ os2settitle("",TRUE); #ifdef NETCONN if (network) { rc = os2_netclos(); } else #endif /* NETCONN */ #ifdef CK_TAPI if ( tttapi ) /* Closing a TAPI Line Device */ { rc = tapi_clos(); } else #endif /* CK_TAPI */ { if (savedtty #ifdef OS2ONLY && !ttslip && !ttppp /* Restoring the line has a tendancy */ /* to drop DTR, which hangs up the */ /* connection, not a good thing */ #endif /* OS2ONLY */ ) restoretty(); if (!ishandle) { #ifdef NT CloseHandle( (HANDLE) ttyfd ) ; #else /* NT */ DosClose(ttyfd); #endif /* NT */ } ishandle = 0; ttyfd = -1; wasclosed = 1; savedtty = 0 ; #ifndef NT PPPSlipClose() ; #endif /* NT */ } return(rc); } /* T T G S P D -- return speed of COM port, or of default line */ long ttgspd() { #ifndef NT long sp = 0; struct { long current_rate; char current_fract; long minimum_rate; char minimum_fract; long maximum_rate; char maximum_fract; } speed; #endif /* NT */ if (ttyfd == -1 #ifdef CK_TAPI || (!tttapi && ttyfd == -2) #endif /* CK_TAPI */ ) return -1 ; #ifdef TN_COMPORT if ( network) { if (istncomport()) { return(tnc_get_baud()); } else return(-1); } #endif /* TN_COMPORT */ #ifdef NT #ifdef CK_TAPI if ( tttapi && !tapipass ) { HANDLE hModem = NULL; hModem = GetModemHandleFromLine( (HLINE) 0 ); if ( hModem == NULL ) return(-1); memset( ttycfg, 0, 1024 ); ttycfg->dwSize = 1024; cfgsize = 1024; if (!GetCommConfig( hModem, ttycfg, &cfgsize )) { CloseHandle( hModem ); return -1 ; } CloseHandle( hModem ); return ttycfg->dcb.BaudRate; } #endif /* CK_TAPI */ ttydcb.DCBlength = sizeof(DCB); if (!GetCommState( (HANDLE) ttyfd, &ttydcb)) return -1 ; else return ttydcb.BaudRate ; #else /* NT */ if (DosDevIOCtl(&speed,sizeof(speed),NULL,0,0x0063,IOCTL_ASYNC,ttyfd) == 0) return speed.current_rate; else if (DosDevIOCtl(&sp,sizeof(sp),NULL,0, ASYNC_GETBAUDRATE,IOCTL_ASYNC,ttyfd) == 0) return sp; else return -1; #endif /* NT */ } ttsetspd(long sp) { #ifdef NT int rc=0; #else struct { long rate; char fract; } speed; #endif /* NT */ if (ttyfd == -1 #ifdef CK_TAPI || (tttapi && ttyfd == -2) #endif /* CK_TAPI */ ) return -1 ; #ifdef TN_COMPORT if ( network) { if (istncomport()) { return(tnc_set_baud(sp)); } else return(-1); } #endif /* TN_COMPORT */ #ifdef NT #ifdef CK_TAPI if ( tttapi && !tapipass ) { HANDLE hModem = NULL; LPDEVCFG lpDevCfg = NULL; LPCOMMCONFIG lpCommConfig = NULL; LPMODEMSETTINGS lpModemSettings = NULL; DCB * lpDCB = NULL; hModem = GetModemHandleFromLine( (HLINE) 0 ); if ( hModem == NULL ) return(-1); if (!cktapiGetModemSettings(&lpDevCfg,&lpModemSettings,&lpCommConfig,&lpDCB)) { CloseHandle( hModem ); return -1 ; } lpDCB->BaudRate = sp ; if (!cktapiSetModemSettings(lpDevCfg,lpCommConfig)) { CloseHandle( hModem ); return -1 ; } CloseHandle( hModem ); return (0); } #endif /* CK_TAPI */ ttydcb.DCBlength = sizeof(DCB); if (!GetCommState( (HANDLE) ttyfd, &ttydcb)) return -1 ; if ( deblog ) debugComm( "ttsetspd initial values", &ttydcb, NULL ); ttydcb.BaudRate = sp ; rc = SetCommState( (HANDLE) ttyfd, &ttydcb ) ; if (!rc) { printf("ttsetspd failed: %d\n", GetLastError()); return -1; } else return 0; #else if (sp > 65535L) { speed.rate = sp; speed.fract = 0; return DosDevIOCtl(NULL,0,&speed,sizeof(speed),0x0043,IOCTL_ASYNC,ttyfd); } else return DosDevIOCtl(NULL,0,&sp,sizeof(sp), ASYNC_SETBAUDRATE,IOCTL_ASYNC,ttyfd); #endif /* NT */ } /* T T H A N G -- Hangup phone line */ tthang() { extern int what; if ( ttyfd == -1 #ifdef CK_TAPI || (tttapi && ttyfd == -2) #endif /* CK_TAPI */ ) return(0); /* Nothing to do */ #ifdef NETCONN if (network #ifdef TN_COMPORT && !istncomport() #endif /* TN_COMPORT */ ) { int rc = os2_netclos(); if (network && tn_exit && ttyfd == -1) { DialerSend(OPT_KERMIT_HANGUP, 0); doexit(GOOD_EXIT,xitsta); /* Exit with good status */ } return rc; } #endif /* NETCONN */ if ( exitonclose && !(what & W_DIALING) && (ttchk() < 0) ) { DialerSend(OPT_KERMIT_HANGUP, 0); doexit(GOOD_EXIT,xitsta); /* Exit with good status */ } #ifdef CK_TAPI if ( tttapi && !tapipass ) return cktapihangup(); #endif /* CK_TAPI */ /* Perhaps better to either let user specify the hangup interval, or else do something with carrier -- e.g. if CD was on when we entered this routine, then cancel the sleep as soon as it goes down, so we don't sleep longer than we need to. */ if (os2setdtr(0)) return -1; msleep(HUPTIME); os2setdtr(1); return 1; } #ifdef PARSENSE static int needpchk = 1; #else /* PARSENSE */ static int needpchk = 0; #endif /* PARSENSE */ #ifdef TCPSOCKET static int nodelay_sav = -1; #endif /* TCPSOCKET */ #ifndef NOTERM static int tt_update_sav = -1; extern int tt_update; #endif /* NOTERM */ #ifdef NT /* For support of Pragma Systems Telnet/Terminal Servers */ HANDLE hPragmaSysInputMutex = NULL; HANDLE hPragmaSysOutputMutex = NULL; #define SET_TELNETD_INPUT_MUTEX(V,P) sprintf( V, "TelnetDInput%dMutex", P ) #define SET_TELNETD_OUTPUT_MUTEX(V,P) sprintf( V, "TelnetDOutput%dMutex", P ) #endif /* NT */ /* T T R E S -- Restore terminal to "normal" mode. */ ttres() { /* Restore the tty to normal. */ if (ttyfd == -1 #ifdef CK_TAPI || (tttapi && ttyfd == -2) #endif /* CK_TAPI */ ) return(-1); /* Not open */ #ifndef NOTERM if ( tt_update_sav > -1 ) { tt_update = tt_update_sav; tt_update_sav = -1; } #endif /* NOTERM */ #ifdef COMMENT if (tt_mode == TT_MODE_NORM) return(0); #endif /* COMMENT */ #ifdef NT /* Support for Pragma Systems Telnet/Terminal Servers */ { char * p = getenv("PRAGMASYS_INETD_SOCK"); if ( p && ttyfd == atoi(p)) { if ( hPragmaSysOutputMutex ) { ReleaseMutex(hPragmaSysOutputMutex); CloseHandle(hPragmaSysOutputMutex); hPragmaSysOutputMutex = NULL; } if ( hPragmaSysInputMutex ) { ReleaseMutex(hPragmaSysInputMutex); CloseHandle(hPragmaSysInputMutex); hPragmaSysInputMutex = NULL; } tt_mode = TT_MODE_NORM; return(0); } } #endif /* NT */ if (network) { #ifdef TCPSOCKET #ifdef TCP_NODELAY if ( network && nettype == NET_TCPB ) { extern int tcp_nodelay; if ( nodelay_sav > -1 ) { no_delay(ttyfd,nodelay_sav); nodelay_sav = -1; } } #endif /* TCP_NODELAY */ #ifdef TN_COMPORT if (network && istncomport()) { int rc = -1; if ((rc = tnsetflow(flow)) < 0) return(rc); if (speed <= 0) speed = tnc_get_baud(); else if ((rc = tnc_set_baud(speed)) < 0) return(rc); tnc_set_datasize(8); if (hwparity) { switch (hwparity) { case 'e': /* Even */ debug(F100,"ttres 8 bits + even parity","",0); tnc_set_parity(3); break; case 'o': /* Odd */ debug(F100,"ttres 8 bits + odd parity","",0); tnc_set_parity(2); break; case 'm': /* Mark */ debug(F100,"ttres 8 bits + invalid parity: mark","",0); tnc_set_parity(4); break; case 's': /* Space */ debug(F100,"ttres 8 bits + invalid parity: space","",0); tnc_set_parity(5); break; } } else { tnc_set_parity(1); /* None */ } tnc_set_stopsize(stopbits); tt_mode = TT_MODE_NORM; return(0); } #endif /* TN_COMPORT */ #endif /* TCPSOCKET */ #ifdef NETDLL if ( network && nettype == NET_DLL ) { extern int (*net_dll_ttres)(void); extern char * (*net_dll_errorstr)(int); int rc = 0; if ( net_dll_ttres ) { rc = net_dll_ttres(); debug(F111,"net_dll_ttres()", (net_dll_errorstr && rc<0)?net_dll_errorstr(rc):"",rc); if (rc < 0) return(-1); } else return(-1); } #endif /* NETDLL */ } ResetThreadPrty(); tt_mode = TT_MODE_NORM; return(0); } /* T T P K T -- Condition the communication line for packets. */ /* or for modem dialing */ /* If called with speed > -1, also set the speed. */ /* Returns 0 on success, -1 on failure. */ ttpkt(long speed, int flow, int parity) { extern int priority; int s; #ifdef NT char * p = NULL; #endif /* NT */ debug(F111,"ttpkt","speed",speed); debug(F111,"ttpkt","flow",flow); debug(F111,"ttpkt","parity",parity); #ifdef HWPARITY debug(F111,"ttpkt","hwparity",hwparity); debug(F111,"ttpkt","stopbits",stopbits); #endif /* HWPARITY */ #ifdef COMMENT if ( tt_mode == TT_MODE_PKT ) return(0); #endif /* COMMENT */ if ( tt_mode != TT_MODE_NORM && tt_mode != TT_MODE_PKT ) ttres(); if (ttyfd == -1 #ifdef CK_TAPI || (tttapi && ttyfd == -2) #endif /* CK_TAPI */ ) return(-1); /* Not open. */ ttprty = parity; ttpmsk = ttprty ? 0177 : 0377; /* Parity stripping mask */ #ifdef PARSENSE needpchk = ttprty ? 0 : 1; /* Parity check needed? */ #else needpchk = 0; #endif /* PARSENSE */ debug(F101,"ttpkt ttpmsk","",ttpmsk); #ifdef NT SetThreadPrty(priority,isWin95() ? 9 : 13); #else /* NT */ SetThreadPrty(priority,3); #endif /* NT */ #ifdef NT /* Support for Pragma Systems Telnet/Terminal Servers */ p = getenv("PRAGMASYS_INETD_SOCK"); if ( p && ttyfd == atoi(p)) { char PragmaSysInputMutexName[MAX_PATH]; char PragmaSysOutputMutexName[MAX_PATH]; p = getenv("PRAGMASYS_TELNETD_PID"); if ( p ) { debug(F111,"ttpkt","PRAGMASYS_TELNETD_PID",atoi(p)); SET_TELNETD_INPUT_MUTEX(PragmaSysInputMutexName,(DWORD)atoi(p)); SET_TELNETD_OUTPUT_MUTEX(PragmaSysOutputMutexName,(DWORD)atoi(p)); debug(F110,"ttpkt",PragmaSysInputMutexName,0); debug(F110,"ttpkt",PragmaSysOutputMutexName,0); hPragmaSysOutputMutex = OpenMutex( SYNCHRONIZE, FALSE, PragmaSysOutputMutexName); if ( hPragmaSysOutputMutex == NULL ) { debug(F111,"ttpkt","PragmaSys unable to OpenMutex(Output)", GetLastError()); return(-1); } if (WaitForSingleObject( hPragmaSysOutputMutex, 5000 ) != WAIT_OBJECT_0) { debug(F111,"ttpkt","PragmaSys unable to WaitForSingleObject(Output)", GetLastError()); CloseHandle(hPragmaSysOutputMutex); hPragmaSysOutputMutex = NULL; return(-1); } hPragmaSysInputMutex = OpenMutex( SYNCHRONIZE, FALSE, PragmaSysInputMutexName); if ( hPragmaSysInputMutex == NULL ) { debug(F111,"ttpkt","PragmaSys unable to OpenMutex(Input)", GetLastError()); CloseHandle(hPragmaSysOutputMutex); hPragmaSysOutputMutex = NULL; return(-1); } if (WaitForSingleObject( hPragmaSysInputMutex, 5000 ) != WAIT_OBJECT_0) { debug(F111,"ttpkt","PragmaSys unable to WaitForSingleObject(Input)", GetLastError()); CloseHandle(hPragmaSysOutputMutex); hPragmaSysOutputMutex = NULL; CloseHandle(hPragmaSysInputMutex); hPragmaSysInputMutex = NULL; return(-1); } debug(F100,"ttpkt success","",0); tt_mode = TT_MODE_PKT; return(0); } debug(F110,"ttpkt","PragmaSys unable to getenv(PRAGMASYS_TELNETD_PID)",0); return(-1); } #endif /* NT */ if (network) { #ifdef TCPSOCKET #ifdef TCP_NODELAY if ( network && nettype == NET_TCPB ) { extern int tcp_nodelay; nodelay_sav = tcp_nodelay; no_delay(ttyfd,1); } #endif /* TCP_NODELAY */ #ifdef TN_COMPORT if (network && istncomport()) { int rc = -1; if ((rc = tnsetflow(flow)) < 0) return(rc); if (speed <= 0) speed = tnc_get_baud(); else if ((rc = tnc_set_baud(speed)) < 0) return(rc); tnc_set_datasize(8); if (hwparity) { switch (hwparity) { case 'e': /* Even */ debug(F100,"ttpkt 8 bits + even parity","",0); tnc_set_parity(3); break; case 'o': /* Odd */ debug(F100,"ttpkt 8 bits + odd parity","",0); tnc_set_parity(2); break; case 'm': /* Mark */ debug(F100,"ttpkt 8 bits + invalid parity: mark","",0); tnc_set_parity(4); break; case 's': /* Space */ debug(F100,"ttpkt 8 bits + invalid parity: space","",0); tnc_set_parity(5); break; } } else { tnc_set_parity(1); /* None */ } tnc_set_stopsize(stopbits); tt_mode = TT_MODE_PKT; return(0); } #endif /* TN_COMPORT */ #endif /* TCPSOCKET */ #ifdef NETDLL if ( network && nettype == NET_DLL ) { extern int (*net_dll_ttpkt)(void); extern char * (*net_dll_errorstr)(int); int rc = 0; if ( net_dll_ttpkt ) { rc = net_dll_ttpkt(); debug(F111,"net_dll_ttpkt()", (net_dll_errorstr && rc<0)?net_dll_errorstr(rc):"",rc); if (rc<0) return(-1); } else return(-1); } #endif /* NETDLL */ debug(F100,"ttpkt success","",0); tt_mode = TT_MODE_PKT; return(0); } if (speed < 0) return(-1); os2setdtr(1); if (ttsetspd(speed)) return(-1); if (ttsettings(ttprty,stopbits)) return(-1); if (ttsetflow(flow)) return(-1); if (os2settimo(speed,ttmdm)) return(-1); if (os2setcarr(ttcarr == CAR_ON && flow != FLO_DIAL)) return(-1); debug(F100,"ttpkt success","",0); tt_mode = TT_MODE_PKT; return(0); } /* T T V T -- Condition communication line for use as virtual terminal */ ttvt(long speed, int flow) { extern int priority; #ifdef NT char * p = NULL; #endif /* NT */ debug(F111,"ttvt","speed",speed); debug(F111,"ttvt","flow",flow); debug(F111,"ttvt","parity",parity); #ifdef COMMENT if (tt_mode == TT_MODE_VT) return(0); #endif if ( tt_mode != TT_MODE_NORM && tt_mode != TT_MODE_NORM ) ttres(); if (ttyfd == -1 #ifdef CK_TAPI || (tttapi && ttyfd == -2) #endif /* CK_TAPI */ ) { if ( ttchk() > 0 ) return(0); /* Data waiting to be read */ else return(-1); /* Not open. */ } #ifndef NOTERM if ( tt_update_sav > -1 ) { tt_update = tt_update_sav; tt_update_sav = -1; } #endif /* NOTERM */ ResetThreadPrty(); #ifdef NT /* Support for Pragma Systems Telnet/Terminal Servers */ p = getenv("PRAGMASYS_INETD_SOCK"); if ( p && ttyfd == atoi(p)) { char PragmaSysInputMutexName[MAX_PATH]; char PragmaSysOutputMutexName[MAX_PATH]; p = getenv("PRAGMASYS_TELNETD_PID"); if ( p ) { if ( hPragmaSysOutputMutex && hPragmaSysInputMutex ) return(0); debug(F111,"ttvt","PRAGMASYS_TELNETD_PID",atoi(p)); SET_TELNETD_INPUT_MUTEX(PragmaSysInputMutexName,(DWORD)atoi(p)); SET_TELNETD_OUTPUT_MUTEX(PragmaSysOutputMutexName,(DWORD)atoi(p)); debug(F110,"ttvt",PragmaSysInputMutexName,0); debug(F110,"ttvt",PragmaSysOutputMutexName,0); hPragmaSysOutputMutex = OpenMutex( SYNCHRONIZE, FALSE, PragmaSysOutputMutexName); if ( hPragmaSysOutputMutex == NULL ) { debug(F111,"ttvt","PragmaSys unable to OpenMutex(Output)", GetLastError()); return(-1); } if (WaitForSingleObject( hPragmaSysOutputMutex, 5000 ) != WAIT_OBJECT_0) { debug(F111,"ttvt","PragmaSys unable to WaitForSingleObject(Output)", GetLastError()); CloseHandle(hPragmaSysOutputMutex); hPragmaSysOutputMutex = NULL; return(-1); } hPragmaSysInputMutex = OpenMutex( SYNCHRONIZE, FALSE, PragmaSysInputMutexName); if ( hPragmaSysInputMutex == NULL ) { debug(F111,"ttvt","PragmaSys unable to OpenMutex(Input)", GetLastError()); CloseHandle(hPragmaSysOutputMutex); hPragmaSysOutputMutex = NULL; return(-1); } if (WaitForSingleObject( hPragmaSysInputMutex, 5000 ) != WAIT_OBJECT_0) { debug(F111,"ttvt","PragmaSys unable to WaitForSingleObject(Input)", GetLastError()); CloseHandle(hPragmaSysOutputMutex); hPragmaSysOutputMutex = NULL; CloseHandle(hPragmaSysInputMutex); hPragmaSysInputMutex = NULL; return(-1); } debug(F100,"ttvt success","",0); tt_mode = TT_MODE_VT; return(0); } debug(F110,"ttvt","PragmaSys unable to getenv(PRAGMASYS_TELNETD_PID)",0); return(-1); } #endif /* NT */ if (network) { #ifdef TCPSOCKET #ifdef TCP_NODELAY if ( network && nettype == NET_TCPB ) { extern int tcp_nodelay; if ( nodelay_sav > -1 ) { no_delay(ttyfd,nodelay_sav); nodelay_sav = -1; } } #endif /* TCP_NODELAY */ #ifdef TN_COMPORT if (network && istncomport()) { int rc = -1; if ((rc = tnsetflow(flow)) < 0) return(rc); if (speed <= 0) speed = tnc_get_baud(); else if ((rc = tnc_set_baud(speed)) < 0) return(rc); tnc_set_datasize(8); if (hwparity) { switch (hwparity) { case 'e': /* Even */ debug(F100,"ttvt 8 bits + even parity","",0); tnc_set_parity(3); break; case 'o': /* Odd */ debug(F100,"ttvt 8 bits + odd parity","",0); tnc_set_parity(2); break; case 'm': /* Mark */ debug(F100,"ttvt 8 bits + invalid parity: mark","",0); tnc_set_parity(4); break; case 's': /* Space */ debug(F100,"ttvt 8 bits + invalid parity: space","",0); tnc_set_parity(5); break; } } else { tnc_set_parity(1); /* None */ } tnc_set_stopsize(stopbits); tt_mode = TT_MODE_VT; return(0); } #endif /* TN_COMPORT */ #endif /* TCPSOCKET */ #ifdef NETDLL if ( network && nettype == NET_DLL ) { extern int (*net_dll_ttvt)(void); extern char * (*net_dll_errorstr)(int); int rc = 0; if ( net_dll_ttvt ) { rc = net_dll_ttvt(); debug(F111,"net_dll_ttvt()", (net_dll_errorstr && rc<0)?net_dll_errorstr(rc):"",rc); if ( rc < 0 ) return(-1); } else return(-1); } #endif /* NETDLL */ debug(F100,"ttvt success","",0); tt_mode = TT_MODE_VT; return(0); } /* end of network */ if (speed < 0) return(-1); ttprty = parity; ttpmsk = 0xff; os2setdtr(1); if (ttsetspd(speed)) return(-1); if (ttsettings(ttprty,stopbits)) return(-1); if (ttsetflow(flow)) return (-1); if (os2settimo(speed,ttmdm)) return(-1); if (os2setcarr(ttcarr == CAR_ON || ttcarr == CAR_AUT)) return(-1); debug(F100,"ttvt success","",0); tt_mode = TT_MODE_VT; return(0); } /* T T S S P D -- Return the speed if OK, otherwise -1 */ int ttsspd(int speed) { long s; if (speed < 0) return(-1); s = (long) speed * 10L; ttsetspd(s); return(0); } /* The following functions will provide the interface for the local echo */ /* buffer to be used when 'duplex' is TRUE */ #ifdef OS2ONLY #define LOCAL_ECHO_BUFSIZE (65536/sizeof(USHORT)) #else /* OS2ONLY */ #define LOCAL_ECHO_BUFSIZE 65536 #endif /* OS2ONLY */ static USHORT LocalEchoBuf[LOCAL_ECHO_BUFSIZE] ; static int LocalEchoStart=0, LocalEchoEnd=0, LocalEchoData=0 ; void le_init( void ) { CreateLocalEchoAvailSem( FALSE ); CreateLocalEchoMutex( TRUE ) ; memset(LocalEchoBuf,0,LOCAL_ECHO_BUFSIZE*sizeof(USHORT)) ; LocalEchoStart = 0 ; LocalEchoEnd = 0 ; LocalEchoData = 0; ReleaseLocalEchoMutex() ; } void le_clean( void ) { CloseLocalEchoMutex() ; CloseLocalEchoAvailSem() ; } int le_inbuf( void ) { int rc = 0 ; RequestLocalEchoMutex( SEM_INDEFINITE_WAIT ) ; if ( LocalEchoStart != LocalEchoEnd ) { rc = (LocalEchoEnd - LocalEchoStart + LOCAL_ECHO_BUFSIZE)%LOCAL_ECHO_BUFSIZE; } ReleaseLocalEchoMutex() ; return rc ; } int le_putstr( char * s ) { int rc = 0; if ( s && s[0] ) rc = le_puts( s, strlen(s) ) ; return rc ; } int le_puts( char * s, int n ) { int rc = 0 ; int i = 0; hexdump("LocalEchoPutChars",s,n); RequestLocalEchoMutex( SEM_INDEFINITE_WAIT ) ; for ( i=0 ; i 0) ) { char ch=0; if ( le_getchar(&ch) > 0 ) { debug(F111,"ttflui le_getchar","ch",ch); } } #ifdef NETCONN if (network) { #ifdef TN_COMPORT #ifdef COMMENT if (istncomport()) tnc_send_purge_data(TNC_PURGE_RECEIVE); #endif /* TN_COMPORT */ #endif /* COMMENT */ return os2_netflui() ; } #endif /* NETCONN */ rdchbuf.index = rdchbuf.length = 0; /* Flush internal buffer */ #ifdef NT PurgeComm( (HANDLE) ttyfd, PURGE_RXCLEAR | PURGE_RXABORT ) ; #else /* NT */ DosDevIOCtl(&data,sizeof(data),&parm,sizeof(parm), DEV_FLUSHINPUT,IOCTL_GENERAL,ttyfd); /* Flush driver */ #endif /* NT */ return(0); } /* T T C H K -- Tell how many characters are waiting in tty input buffer */ ttchk() { int count=0; #ifdef NT DWORD rc, lasterror; DWORD errors ; COMSTAT comstat ; #else /* NT */ USHORT data[2]={0,0}; #endif /* NT */ if ( ttyfd == -1 #ifdef CK_TAPI || (tttapi && ttyfd == -2) #endif /* CK_TAPI */ ) { if ( ttpush >= 0 ) count++; count += le_inbuf(); return(count>0?count:-1); /* No connection */ } #ifdef NETCONN if (network) { count = os2_nettchk(); if ( count >= 0 ) { if ( ttpush >= 0 ) count++; count += le_inbuf(); #ifdef TN_COMPORT if (count == 0 && istncomport() && ttcarr != CAR_OFF) { /* Check carrier */ extern int clsondisc; int mdmsig = tngmdm(); if ( mdmsig >= 0 && (mdmsig & BM_DCD) == 0 ) { debug(F111,"ttchk","Carrier not detected",ttcarr); if (clsondisc) { /* If "close-on-disconnect" */ debug(F100,"ttchk close-on-disconnect","",0); ttclos(0); /* close device */ return(-2); } return(-1); } } #endif /* TN_COMPORT */ debug(F101,"ttchk() network istncomport returns","",count); return count; } else { int count2 = 0; if ( ttpush >= 0 ) count2++; count2 += le_inbuf(); debug(F101,"ttchk() network !istncomport returns","", count2?count2:count); return(count2?count2:count); } } #endif /* NETCONN */ #ifdef NT RequestCommMutex(SEM_INDEFINITE_WAIT); rc = ClearCommError( (HANDLE) ttyfd, &errors, &comstat ); ReleaseCommMutex(); lasterror = GetLastError(); if (!rc) { debug(F101,"ttchk() ClearCommError failed","",lasterror); count = -1; } else { if ( errors && deblog ) { if ( errors & CE_RXOVER ) debug(F110,"ttchk ClearCommError","Receive Queue overflow",0); if ( errors & CE_OVERRUN ) debug(F110,"ttchk ClearCommError","Receive Overrun error",0); if ( errors & CE_RXPARITY ) debug(F110,"ttchk ClearCommError","Receive Parity error",0); if ( errors & CE_FRAME ) debug(F110,"ttchk ClearCommError","Receive Framing error",0); if ( errors & CE_BREAK ) debug(F110,"ttchk ClearCommError","Break detected",0); if ( errors & CE_TXFULL ) debug(F110,"ttchk ClearCommError","TX Queue is full",0); if ( errors & CE_PTO ) debug(F110,"ttchk ClearCommError","LPTx Timeout",0); if ( errors & CE_IOE ) debug(F110,"ttchk ClearCommError","LPTx I/O Error",0); if ( errors & CE_DNS ) debug(F110,"ttchk ClearCommError","LPTx Device Not Selected",0); if ( errors & CE_OOP ) debug(F110,"ttchk ClearCommError","LPTx Out Of Paper",0); } count = comstat.cbInQue+(rdchbuf.length-rdchbuf.index); } #else /* NT */ if ( DosDevIOCtl(data,sizeof(USHORT),NULL,0, ASYNC_GETCOMMERROR,IOCTL_ASYNC,ttyfd)) { if ( data[0] & RX_QUE_OVERRUN ) { debug( F100,"ttchk RX_QUE_OVERRUN","",0); } if ( data[0] & RX_HARDWARE_OVERRUN ) { debug( F100,"ttchk RX_HARDWARE_OVERRUN", "", 0 ); } } if(DosDevIOCtl(data,sizeof(data),NULL,0, ASYNC_GETINQUECOUNT,IOCTL_ASYNC,ttyfd)) count = 0; else count = rdchbuf.length-rdchbuf.index+data[0]; #endif /* NT */ if ( count >= 0 ) { if ( ttpush >= 0 ) count++; count += le_inbuf(); if (count == 0 && ttcarr != CAR_OFF) { /* Check carrier */ extern int clsondisc; int mdmsig = ttgmdm(); if ( mdmsig >= 0 && (mdmsig & BM_DCD) == 0 ) { debug(F111,"ttchk","Carrier not detected",ttcarr); if (clsondisc) { /* If "close-on-disconnect" */ debug(F100,"ttchk close-on-disconnect","",0); ttclos(0); /* close device */ return(-2); } return(-1); } } #ifdef NT #ifdef NEWRDCH /* Is there anything in the overlapped I/O buffers? */ /* Network Overlapped I/O is handled in nettchk() */ count += OverlappedDataWaiting(); #endif /* NEWRDCH */ #endif /* NT */ } else { int cnt = 0; if ( ttpush >= 0 ) cnt++; cnt += le_inbuf(); if ( cnt ) count = cnt; } debug(F101,"ttchk() !network returns","",count); return(count); } /* T T X I N -- Get n characters from tty input buffer */ /* Returns number of characters actually gotten, or -1 on failure */ /* Intended for use only when it is known that n characters are actually */ /* available in the input buffer because this function blocks. */ int ttxin(int n, CHAR *buf) { int i=0, j=0, k=0; CHAR m=0 ; m = (ttprty) ? 0177 : 0377; /* Parity stripping mask. */ buf[0] = '\0'; /* make it easy to read the buffer in a debugger */ if (ttyfd == -1 #ifdef CK_TAPI || (tttapi && ttyfd == -2) #endif /* CK_TAPI */ ) return(-1); /* Not open. */ debug(F101,"ttxin n","",n); if ( n <= 0 ) return(0); if ( ttpush >= 0 ) { buf[0] = ttpush & m; /* set first char of buffer to pushed char */ ttpush = -1; /* clear the push buffer */ if ( ttchk() > 0 ) return(ttxin( n-1, &buf[1] ) + 1); /* recurse the call */ else return(1); } if ( LocalEchoData ) { while ( le_inbuf() > 0 ) { le_getchar( &buf[i] ); buf[i] &= m; i++; n--; } if (ttchk() > 0) return(ttxin( n, &buf[i] ) + i); else return(i); } #ifdef NETCONN if (network) { j = os2_netxin(n,buf); if ( ttprty ) { for ( i=0;i n","",0); memcpy(buf, &rdchbuf.buffer[rdchbuf.index], n ) ; rdchbuf.index += n ; j = n; } if ( ttprty ) { for ( i=0;i= maxow ) { if ( serial ) { /* All buffers are still outstanding */ /* Lets see if we can figure out why */ DWORD errorflags ; COMSTAT comstat ; RequestCommMutex(SEM_INDEFINITE_WAIT); ClearCommError( (HANDLE) ttyfd, &errorflags, &comstat ) ; ReleaseCommMutex(); debug(F101,"getOverlappedIndex ClearCommError", "",errorflags) ; #ifdef BETADEBUG printf("\nClearCommError: %d\n",errorflags); if ( errorflags ) { if ( errorflags & CE_RXOVER ) printf(" Receive Queue overflow\n"); if ( errorflags & CE_OVERRUN ) printf(" Receive Overrun error\n"); if ( errorflags & CE_RXPARITY ) printf(" Receive Parity error\n"); if ( errorflags & CE_FRAME ) printf(" Receive Framing error\n"); if ( errorflags & CE_BREAK ) printf(" Break detected\n"); if ( errorflags & CE_TXFULL ) printf(" TX Queue is full\n"); if ( errorflags & CE_PTO ) printf(" LPTx Timeout\n"); if ( errorflags & CE_IOE ) printf(" LPTx I/O Error\n"); if ( errorflags & CE_DNS ) printf(" LPTx Device Not Selected\n"); if ( errorflags & CE_OOP ) printf(" LPTx Out Of Paper\n"); } printf("Port Status:\n"); printf(" Cts Hold: %d\n",comstat.fCtsHold); printf(" Dsr Hold: %d\n",comstat.fDsrHold); printf(" Rlsd Hold: %d\n",comstat.fRlsdHold); printf(" Xoff Hold: %d\n",comstat.fXoffHold); printf(" Xoff Sent: %d\n",comstat.fXoffSent); printf(" Eof: %d\n",comstat.fEof); printf(" Tx Immed: %d\n",comstat.fTxim); printf(" In Que: %d\n",comstat.cbInQue); printf(" Out Que: %d\n",comstat.cbOutQue); #endif /* BETADEBUG */ if ( errorflags && deblog ) { if ( errorflags & CE_RXOVER ) debug(F110,"ClearCommError","Receive Queue overflow",0); if ( errorflags & CE_OVERRUN ) debug(F110,"ClearCommError","Receive Overrun error",0); if ( errorflags & CE_RXPARITY ) debug(F110,"ClearCommError","Receive Parity error",0); if ( errorflags & CE_FRAME ) debug(F110,"ClearCommError","Receive Framing error",0); if ( errorflags & CE_BREAK ) debug(F110,"ClearCommError","Break detected",0); if ( errorflags & CE_TXFULL ) debug(F110,"ClearCommError","TX Queue is full",0); if ( errorflags & CE_PTO ) debug(F110,"ClearCommError","LPTx Timeout",0); if ( errorflags & CE_IOE ) debug(F110,"ClearCommError","LPTx I/O Error",0); if ( errorflags & CE_DNS ) debug(F110,"ClearCommError","LPTx Device Not Selected",0); if ( errorflags & CE_OOP ) debug(F110,"ClearCommError","LPTx Out Of Paper",0); } if ( deblog ) { debug(F111,"ClearCommError","Cts Hold",comstat.fCtsHold); debug(F111,"ClearCommError","Dsr Hold",comstat.fDsrHold); debug(F111,"ClearCommError","Rlsd Hold",comstat.fRlsdHold); debug(F111,"ClearCommError","Xoff Hold",comstat.fXoffHold); debug(F111,"ClearCommError","Xoff Sent",comstat.fXoffSent); debug(F111,"ClearCommError","Eof",comstat.fEof); debug(F111,"ClearCommError","Tx Immed",comstat.fTxim); debug(F111,"ClearCommError","In Que",comstat.cbInQue); debug(F111,"ClearCommError","Out Que",comstat.cbOutQue); } } ow = -1; Sleep(100); /* take a breather */ } continue; } else if ( error == ERROR_OPERATION_ABORTED ) { debug(F100,"getOverlappedIndex OPERATION ABORTED","",0); ResetEvent( overlapped_write[ow].hEvent ) ; ow_inuse[ow] = FALSE ; break; } else { LPVOID lpMsgBuf; int freebuf = 1; if ( !FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL)) { lpMsgBuf = ""; freebuf = 0; } debug(F111,"getOverlappedIndex Overlapped I/O Error", (char *) lpMsgBuf, error) ; if ( freebuf ) LocalFree(lpMsgBuf); if ( serial ) { DWORD errorflags ; COMSTAT comstat ; ClearCommError( (HANDLE) ttyfd, &errorflags, &comstat ) ; debug(F101,"getOverlappedIndex ClearCommError", "",errorflags) ; if ( errorflags && deblog ) { if ( errorflags & CE_RXOVER ) debug(F110,"ClearCommError","Receive Queue overflow",0); if ( errorflags & CE_OVERRUN ) debug(F110,"ClearCommError","Receive Overrun error",0); if ( errorflags & CE_RXPARITY ) debug(F110,"ClearCommError","Receive Parity error",0); if ( errorflags & CE_FRAME ) debug(F110,"ClearCommError","Receive Framing error",0); if ( errorflags & CE_BREAK ) debug(F110,"ClearCommError","Break detected",0); if ( errorflags & CE_TXFULL ) debug(F110,"ClearCommError","TX Queue is full",0); if ( errorflags & CE_PTO ) debug(F110,"ClearCommError","LPTx Timeout",0); if ( errorflags & CE_IOE ) debug(F110,"ClearCommError","LPTx I/O Error",0); if ( errorflags & CE_DNS ) debug(F110,"ClearCommError","LPTx Device Not Selected",0); if ( errorflags & CE_OOP ) debug(F110,"ClearCommError","LPTx Out Of Paper",0); } if ( deblog ) { debug(F111,"ClearCommError","Cts Hold",comstat.fCtsHold); debug(F111,"ClearCommError","Dsr Hold",comstat.fDsrHold); debug(F111,"ClearCommError","Rlsd Hold",comstat.fRlsdHold); debug(F111,"ClearCommError","Xoff Hold",comstat.fXoffHold); debug(F111,"ClearCommError","Xoff Sent",comstat.fXoffSent); debug(F111,"ClearCommError","Eof",comstat.fEof); debug(F111,"ClearCommError","Tx Immed",comstat.fTxim); debug(F111,"ClearCommError","In Que",comstat.cbInQue); debug(F111,"ClearCommError","Out Que",comstat.cbOutQue); } } ResetEvent( overlapped_write[ow].hEvent ) ; ow_inuse[ow] = FALSE ; break; } } debug(F111,"getOverlappedIndex COMPLETE","ow",ow); debug(F111,"getOverlappedIndex COMPLETE",ow_ptr[ow],ow); debug(F111,"getOverlappedIndex COMPLETE","nActuallyWritten", nActuallyWritten); } debug(F111,"GetOverlappedIndex","available ow",ow); return ow ; } int freeOverlappedComplete( int serial ) { int ow, rc = -1 ; debug(F100,"freeOverlappedComplete","",0); #ifdef COMMENT if ( owwait ) /* if owwait, then we will wait for completion */ return ; /* before attempting the next write */ #endif /* COMMENT */ /* free any which are complete */ for ( ow=0 ; ow 0 ) memcpy(buf,or_ptr[NextReadPending], bufsize 0 ) return(nActuallyRead); else return (-1); /* fdc */ } else { if ( serial ) { DWORD errorflags ; COMSTAT comstat ; debug(F101,"rdch ReadFile Overlapped I/O Error", "",error); ClearCommError( (HANDLE) ttyfd, &errorflags, &comstat ); debug(F101,"rdch ClearCommError","",errorflags); if ( errorflags && deblog ) { if ( errorflags & CE_RXOVER ) debug(F110,"ClearCommError","Receive Queue overflow",0); if ( errorflags & CE_OVERRUN ) debug(F110,"ClearCommError","Receive Overrun error",0); if ( errorflags & CE_RXPARITY ) debug(F110,"ClearCommError","Receive Parity error",0); if ( errorflags & CE_FRAME ) debug(F110,"ClearCommError","Receive Framing error",0); if ( errorflags & CE_BREAK ) debug(F110,"ClearCommError","Break detected",0); if ( errorflags & CE_TXFULL ) debug(F110,"ClearCommError","TX Queue is full",0); if ( errorflags & CE_PTO ) debug(F110,"ClearCommError","LPTx Timeout",0); if ( errorflags & CE_IOE ) debug(F110,"ClearCommError","LPTx I/O Error",0); if ( errorflags & CE_DNS ) debug(F110,"ClearCommError","LPTx Device Not Selected",0); if ( errorflags & CE_OOP ) debug(F110,"ClearCommError","LPTx Out Of Paper",0); } if ( deblog ) { debug(F111,"ClearCommError","Cts Hold",comstat.fCtsHold); debug(F111,"ClearCommError","Dsr Hold",comstat.fDsrHold); debug(F111,"ClearCommError","Rlsd Hold",comstat.fRlsdHold); debug(F111,"ClearCommError","Xoff Hold",comstat.fXoffHold); debug(F111,"ClearCommError","Xoff Sent",comstat.fXoffSent); debug(F111,"ClearCommError","Eof",comstat.fEof); debug(F111,"ClearCommError","Tx Immed",comstat.fTxim); debug(F111,"ClearCommError","In Que",comstat.cbInQue); debug(F111,"ClearCommError","Out Que",comstat.cbOutQue); } } ResetEvent( overlapped_read[NextReadPending].hEvent ) ; if ( nActuallyRead > 0 ) memcpy(buf,or_ptr[NextReadPending], bufsize 0 ) { return(nActuallyRead); } return -1; } } } else { if ( serial ) { DWORD errorflags ; COMSTAT comstat ; debug(F101,"rdch ReadFile - real error occurred","",error) ; ClearCommError( (HANDLE) ttyfd, &errorflags, &comstat ); debug(F101,"rdch ClearCommError","",errorflags); if ( errorflags && deblog ) { if ( errorflags & CE_RXOVER ) debug(F110,"ClearCommError","Receive Queue overflow",0); if ( errorflags & CE_OVERRUN ) debug(F110,"ClearCommError","Receive Overrun error",0); if ( errorflags & CE_RXPARITY ) debug(F110,"ClearCommError","Receive Parity error",0); if ( errorflags & CE_FRAME ) debug(F110,"ClearCommError","Receive Framing error",0); if ( errorflags & CE_BREAK ) debug(F110,"ClearCommError","Break detected",0); if ( errorflags & CE_TXFULL ) debug(F110,"ClearCommError","TX Queue is full",0); if ( errorflags & CE_PTO ) debug(F110,"ClearCommError","LPTx Timeout",0); if ( errorflags & CE_IOE ) debug(F110,"ClearCommError","LPTx I/O Error",0); if ( errorflags & CE_DNS ) debug(F110,"ClearCommError","LPTx Device Not Selected",0); if ( errorflags & CE_OOP ) debug(F110,"ClearCommError","LPTx Out Of Paper",0); } if ( deblog ) { debug(F111,"ClearCommError","Cts Hold",comstat.fCtsHold); debug(F111,"ClearCommError","Dsr Hold",comstat.fDsrHold); debug(F111,"ClearCommError","Rlsd Hold",comstat.fRlsdHold); debug(F111,"ClearCommError","Xoff Hold",comstat.fXoffHold); debug(F111,"ClearCommError","Xoff Sent",comstat.fXoffSent); debug(F111,"ClearCommError","Eof",comstat.fEof); debug(F111,"ClearCommError","Tx Immed",comstat.fTxim); debug(F111,"ClearCommError","In Que",comstat.cbInQue); debug(F111,"ClearCommError","Out Que",comstat.cbOutQue); } } ResetEvent( overlapped_read[NextReadPending].hEvent ) ; if ( nActuallyRead > 0 ) memcpy(buf,or_ptr[NextReadPending], bufsize 0 ) { return(nActuallyRead); } return -2 ; } } ResetEvent( overlapped_read[NextReadPending].hEvent ) ; #ifndef COMMENT debug(F101,"rdch nActuallyRead","",nActuallyRead ) ; debug(F101,"rdch overlapped_read.Offset","", overlapped_read[NextReadPending].Offset) ; #endif /* COMMENT */ if ( nActuallyRead > 0 ) memcpy(buf,or_ptr[NextReadPending], bufsize 10240 ? n : 10240; xpacket = (CHAR *)malloc(x); if (!xpacket) { fprintf(stderr,"ttol malloc failure\n"); return(-1); } else nxpacket = x; } memcpy((char *)xpacket,(char *)s,n); s = xpacket; } #endif /* CK_ENCRYPTION */ chars = s; charsleft = n; while ( rc >= 0 && charsleft > 0 ) { #ifdef NETCONN if (network) { debug(F111,"ttol()","charsleft",charsleft); rc = os2_nettol(chars,charsleft); debug(F111,"ttol()","os2_nettol() returns",rc); } else { #endif /* NETCONN */ #ifdef COMMENT if (ttchk() < 0) rc = -1 ; /* Not open. */ else #endif /* COMMENT */ { #ifdef NT rc = OverlappedWrite( TRUE, chars, charsleft ); #else /* NT */ if(DosWrite(ttyfd,chars,charsleft,(PVOID)&i)) rc = -1 ; else rc = i ; #endif /* NT */ } #ifdef NETCONN } #endif /* NETCONN */ if ( rc >= 0 ) { charsleft -= rc ; chars += rc ; } } debug( F101, "ttol returns","",rc >= 0 ? (n-charsleft) : rc ) ; #ifdef CKXXCHAR if (p) free(p); #endif /* CKXXCHAR */ if ( rc < 0 ) { if ( ttchk() < 0 ) return -2; /* connection dropped */ else return -1; /* soft error - timeout ? */ } else return( n - charsleft ) ; } /* T T O C -- Output a character to the communication line */ int ttoc(char c) { int rc = 0 ; #ifdef NT DWORD i ; int ow = 0 ; #else /* NT */ UINT i; #endif /* NT */ if (ttyfd == -1 #ifdef CK_TAPI || (tttapi && ttyfd == -2) #endif /* CK_TAPI */ ) return(-1); /* Not open. */ #ifdef NETCONN if (network) return os2_nettoc(c); #endif /* NETCONN */ #ifdef NT #ifndef COMMENT rc = OverlappedWrite( TRUE, &c, 1 ); #else /* COMMENT */ ow = getOverlappedIndex() ; if ( ow_size[ow] < 1 ) { if ( ow_ptr[ow] ) { free( ow_ptr[ow] ); ow_ptr[ow] = NULL; ow_size[ow] = 0; } ow_ptr[ow] = (char *) malloc( 128 ); if ( !ow_ptr[ow] ) { return -1; } ow_size[ow] = 128 ; } ow_ptr[ow][0] = c; ow_ptr[ow][1] = NUL; debug(F111,"ttoc chars to send",ow_ptr[ow],1); if ( overlapped_write[ow].hEvent == (HANDLE) -1 ) { overlapped_write[ow].hEvent = CreateEvent( NULL, // no security TRUE, // explicit reset req FALSE, // initial event reset NULL ) ; // no name if ( overlapped_write[ow].hEvent == (HANDLE) -1 ) { debug(F101,"ttoc CreateEvent error","",GetLastError() ) ; } } overlapped_write[ow].Offset = overlapped_write[ow].OffsetHigh = 0 ; ResetEvent( overlapped_write[ow].hEvent ) ; nActuallyWritten = 0 ; if ( !WriteFile( (HANDLE) ttyfd, ow_ptr[ow], 1, &nActuallyWritten, &overlapped_write[ow]) ) { DWORD error = GetLastError() ; if ( error != ERROR_IO_PENDING ) { debug(F101,"ttoc WriteFile - real error occurred","",error) ; ResetEvent( overlapped_write[ow].hEvent ) ; ow_inuse[ow] = FALSE ; return -1 ; } else ow_inuse[ow] = TRUE ; } else { ResetEvent( overlapped_write[ow].hEvent ) ; ow_inuse[ow] = FALSE ; } #ifndef COMMENT debug(F101,"ttoc nActuallyWritten","",nActuallyWritten ) ; #endif /* COMMENT */ freeOverlappedComplete() ; rc = 1 ; #endif /* COMMENT */ #else /* NT */ if(DosWrite(ttyfd,&c,1,(PVOID)&i)) rc = -1; else rc = i; #endif /* NT */ return rc ; } #ifndef NOTTOCI #define NEWTTOCI #endif /* NOTTOCI */ /* T T O C I -- Output a character to the communication line immediately */ #ifdef NEWTTOCI int ttoci(char c) { int x; BYTE i; ULONG Data = 0L ; #ifdef NT DWORD errors ; COMSTAT comstat ; #endif /* NT */ if (ttyfd == -1 #ifdef CK_TAPI || (tttapi && ttyfd == -2) #endif /* CK_TAPI */ ) return(-1); /* Not open. */ #ifdef NETCONN if (network) return os2_nettoc(c); #endif /* NETCONN */ #ifdef NT if ( ttoc(c) ) /* write the character first */ return(0); /* if an error occurs, then try to clear it and try again */ ClearCommError( (HANDLE) ttyfd, &errors, &comstat ) ; if ( errors && deblog ) { debug( F101, "ttoci: ClearCommError errors","",errors ) ; if ( errors & CE_RXOVER ) debug(F110,"ClearCommError","Receive Queue overflow",0); if ( errors & CE_OVERRUN ) debug(F110,"ClearCommError","Receive Overrun error",0); if ( errors & CE_RXPARITY ) debug(F110,"ClearCommError","Receive Parity error",0); if ( errors & CE_FRAME ) debug(F110,"ClearCommError","Receive Framing error",0); if ( errors & CE_BREAK ) debug(F110,"ClearCommError","Break detected",0); if ( errors & CE_TXFULL ) debug(F110,"ClearCommError","TX Queue is full",0); if ( errors & CE_PTO ) debug(F110,"ClearCommError","LPTx Timeout",0); if ( errors & CE_IOE ) debug(F110,"ClearCommError","LPTx I/O Error",0); if ( errors & CE_DNS ) debug(F110,"ClearCommError","LPTx Device Not Selected",0); if ( errors & CE_OOP ) debug(F110,"ClearCommError","LPTx Out Of Paper",0); } Data = comstat.fCtsHold | comstat.fDsrHold << 1 | comstat.fRlsdHold << 2 | comstat.fXoffHold << 3 | comstat.fXoffSent << 4 | comstat.fEof << 5 | comstat.fTxim << 6 ; if ( Data ) { debug( F101,"ttoci: COM Status","",Data) ; if ( (flow == FLO_XONX && comstat.fXoffHold) || (flow == FLO_RTSC && comstat.fCtsHold) ) return(Data) ; } return ttoc(c) == 1 ? 0 : -1; #else /* NT */ x = DosDevIOCtl(&Data,sizeof(Data),0,0,ASYNC_GETCOMMSTATUS,IOCTL_ASYNC,ttyfd); if ( Data ) { debug( F101,"ttoci: Query COM Status","",Data) ; return(Data) ; } x = DosWrite(ttyfd,&c,1,(PVOID)&i) ; if (x) { debug(F101,"ttoci failure status","",x); return(x); } else return(0); #endif /* NT */ } #else /* NEWTTOCI */ int ttoci(char c) { int x; if (ttyfd == -1 #ifdef CK_TAPI || (tttapi && ttyfd == -2) #endif /* CK_TAPI */ ) return(-1); /* Not open. */ #ifdef NETCONN if (network) return os2_nettoc(c); #endif /* NETCONN */ #ifdef NT return TransmitCommChar( ttyfd, c ) ? 0 : -1 ; #else /* NT */ x = DosDevIOCtl(NULL,0,&c,sizeof(c),ASYNC_TRANSMITIMM,IOCTL_ASYNC,ttyfd); #endif /* NT */ if (x) { debug(F101,"ttoci failure status","",x); return(x); } else return(0); } #endif /* NEWTTOCI */ static int inlret ; static CHAR * inldest, inleol, inlstart ; static int inlmax, inlturn ; static int ckcgetc(int dummy) { return ttinc(1); } #ifndef NOXFER /* T T I N L -- Read a packet from the communication device. */ /* blah blah */ ttinl(CHAR *dest, int max, int timo, CHAR eol, CHAR start, int turn) { extern int xfrcan, xfrchr, xfrnum; /* Defined in ckcmai.c */ extern int priority; int x=0, c=0, ccn=0; /* register */ int i=0, j=0, m=0, n=0; /* Local variables */ int timespent = 0 ; int flag = 0; unsigned char ch; int pktlen = -1; int lplen = 0; int havelen = 0; extern int server, srvidl, rpsiz ; int srvtimer=0 ; int sopmask = 0xff; #ifdef CKXXCHAR extern short dblt[]; /* Ignore-character table */ extern int ignflag; #endif /* CKXXCHAR */ #ifdef IKS_OPTION extern int stchr; #endif /* IKS_OPTION */ #ifdef STREAMING extern int streaming; extern int sndtyp; #endif /* STREAMING */ extern int tcp_incoming, idletmo; int canread=0, haveread=0; #define INXBUF_SIZE 10240 static char inxbuf[INXBUF_SIZE]; time_t start_time = time(NULL); if (ttyfd == -1 #ifdef CK_TAPI || (tttapi && ttyfd == -2) #endif /* CK_TAPI */ ) return(-3); /* Not open. */ inlret = -1 ; /* Assume we are going to fail */ inldest = dest ; inlmax = max ; inleol = eol ; inlstart = start ; inlturn = turn ; debug(F101,"ttinl max","",max); debug(F101,"ttinl timo","",timo); debug(F101,"ttinl network","",network); debug(F101,"ttinl ttnproto","",ttnproto); *dest = '\0'; /* Clear destination buffer */ if (timo < 0) timo = 0; /* Safety */ debug(F101,"ttinl start","",inlstart); flag = 0; /* Start of packet flag */ ttpmsk = m = (ttprty) ? 0177 : 0377; /* Set parity stripping mask. */ sopmask = needpchk ? 0177 : ttpmsk; /* And SOP mask */ /* Now read into destination, stripping parity and looking for the */ /* the packet terminator, and also for two Ctrl-C's typed in a row. */ i = 0; /* Destination index */ debug(F101,"ttinl eol","",inleol); do { canread = ttchk(); if ( canread > 0 ) { int blah=pktlen-i+5; int pleaseread; if ( !havelen || blah < 0 ) { #ifdef COMMENT /* causes us to read too much data when the peer as been issued */ /* a SET SEND PACKET-SIZE which is smaller than our SET RECEIVE */ /* PACKET-SIZE value. */ blah = rpsiz < LOCAL_ECHO_BUFSIZE ? rpsiz : LOCAL_ECHO_BUFSIZE; #else /* Enough to get the size */ blah = 40; #endif } debug(F111,"ttinl","blah",blah); debug(F111,"ttinl","rpsiz",rpsiz); debug(F111,"ttinl","canread",canread); if ( blah > 0 && blah < canread && blah < INXBUF_SIZE ) pleaseread = blah; else if ( canread < INXBUF_SIZE ) pleaseread = canread; else pleaseread = INXBUF_SIZE; debug(F111,"ttinl","will attempt to read",pleaseread); haveread = ttxin( pleaseread,inxbuf); #ifdef IKS_OPTION if (haveread >= 0) { inlstart = stchr; if (TELOPT_ME(TELOPT_KERMIT) && !TELOPT_SB(TELOPT_KERMIT).kermit.me_start && server) { /* I'm not in Server mode */ debug(F100,"ttinl TELOPT_ME_KERMIT && !me_start && server","",0); if ( haveread ) { debug(F111,"ttinl putting back chars","haveread", haveread); le_puts(inxbuf, haveread); } return(-2); /* End server mode */ } #ifdef IKSD if (TELOPT_U(TELOPT_KERMIT) && TELOPT_SB(TELOPT_KERMIT).kermit.u_start && !inserver && server && !tcp_incoming) { /* Remote in Server mode */ if ( haveread ) { debug(F111,"ttinl putting back chars","haveread", haveread); le_puts(inxbuf, haveread); } return(-2); /* End server mode */ } #endif /* IKSD */ } #endif /* IKS_OPTION */ } else if ( canread == 0 ) { debug(F100,"ttinl canread == 0","",0); #ifdef STREAMING if (streaming && sndtyp == 'D') return(0); #endif /* STREAMING */ if ( #ifdef IKSD !inserver && #endif /* IKSD */ conchk() > 0 ) { debug(F100,"ttinl conchk() > 0","",0); return(-1); /* User pressed a key */ } #ifdef COMMENT #ifdef STREAMING if (streaming && sndtyp == 'D') return(-1); #endif /* STREAMING */ #endif /* COMMENT */ if ((c=ttinc((timo||srvidl)?1:0))<0) { if ( c < -1 ) { debug(F101,"ttinl ttinc() returned error","",c); ttclos(0); return(-3); } else { debug(F101,"ttinl ttinc() returned timeout","",c); timespent = time(NULL) - start_time; if ( server && srvidl ) { if ( timespent > srvidl ) { #ifdef IKSD if ( inserver ) { printf("\r\nIKS IDLE TIMEOUT: %d sec\r\n", srvidl); doexit(GOOD_EXIT,xitsta); } #endif /* IKSD */ idletmo = 1; return(-2) ; } } continue; } } else if (c == IAC && (network && IS_TELNET() #ifdef IKSD || inserver #endif /* IKSD */ )) { int tx=0; extern int duplex; debug(F100,"ttinl got IAC","",0); if ((tx = tn_doop((CHAR)(c & 0xff),duplex,ckcgetc)) == 0) { continue; } else if (tx == -1) { /* I/O error */ return(-3); } else if (tx == -2 || tx == -3) { /* Connection failed. */ ttclos(0) ; return(-3); } else if (tx == 1) { /* ECHO change */ duplex = 1; /* Get next char */ continue; } else if (tx == 2) { /* ECHO change */ duplex = 0; /* Get next char */ continue; } else if (tx == 3) { /* Quoted IAC */ c = 255; /* proceeed with it. */ } #ifdef IKS_OPTION else if (tx == 4) { if (TELOPT_SB(TELOPT_KERMIT).kermit.u_start && server /* Remote in Server mode */ #ifdef IKSD && !inserver #endif /* IKSD */ ) { debug(F100,"ttinl u_start && server && !inserver","",0); return(-2); /* End server mode */ } if (!TELOPT_SB(TELOPT_KERMIT).kermit.me_start && server) { debug(F100,"ttinl me_start && server","",0); return(-2); } } else if (tx == 5) { /* IKS State Change */ extern int stchr; inlstart = stchr; } #endif /* IKS_OPTION */ else if (tx == 6) { /* Remote Logout */ ttclos(0); #ifdef IKSD if (inserver && !local) doexit(GOOD_EXIT,0); else #endif /* IKSD */ return(-2); } else continue; /* Unknown, get next char */ } inxbuf[0] = (char) c; haveread = 1; } else /* canread < 0 == error */ { debug(F101,"ttinl ttchk() returned error","",n); ttclos(0); return (-3); /* i/o error or no connection */ } hexdump("ttinl() ttin?() returned",inxbuf,haveread); j = 0; while ( j < haveread ) { n = inxbuf[j++]; ch = n & 0xff; #ifdef CKXXCHAR if (ignflag) if (dblt[(unsigned) ch] & 1) /* Character to ignore? */ continue; #endif /* CKXXCHAR */ /* Check cancellation */ if (xfrcan && ((ch & ttpmsk) == xfrchr)) { if (++ccn >= xfrnum) { /* If xfrnum in a row, bail out. */ if (xfrchr < 32) printf("^%c...\r\n",(char)(xfrchr+64)); else printf("Canceled...\r\n"); return(-2); } } else ccn = 0; /* No cancellation, reset counter, */ if (flag == 0) { /* Find the Start of Packet */ if ((n & sopmask) == inlstart) /* Got it! */ flag = 1; else { /* Keep looking */ debug(F101,"ttinl skipping","",n); #ifndef NOLOCAL #ifdef BETATEST_X cwrite(n); #endif /* BETATEST */ #endif /* NOLOCAL */ continue; } } inldest[i++] = n & ttpmsk; if (!havelen) { /* Try to compute the packet length */ if (i == 2) { pktlen = xunchar(inldest[1] & ttpmsk); havelen = (pktlen > 1); debug(F101,"ttinl length","",pktlen); } else if (i == 5 && pktlen == 0) { lplen = xunchar(inldest[4] & ttpmsk); } else if (i == 6 && pktlen == 0) { pktlen = lplen * 95 + xunchar(inldest[5] & ttpmsk) + 5; havelen = 1; debug(F101,"ttinl extended length","",pktlen); } /* Suppose we looked at the sequence number here and found it was out of range? This would mean either (a) incoming packets had SOP unprefixed and we are out of sync, or (b) the packet is damaged. Since (a) is bad practice, let's ignore it. So what should we do here if we know the packet is damaged? 1. Nothing -- keep trying to read the packet till we find what we think is the end, or we time out, and let the upper layer decide what to do. But since either the packet is corrupt or we are out of sync, our criterion for finding the end does not apply and we are likely to time out (or swallow a piece of the next packet) if our assumed length is too long. (This was the behavior prior to version 7.0.) 2. set flag = 0 and continue? This would force us to wait for the next packet to come in, and therefore (in the nonwindowing case), would force a timeout in the other Kermit. 3. set flag = 0 and continue, but only if the window size is > 1 and the window is not blocked? Talk about cheating! 4. Return a failure code and let the upper layer decide what to do. This should be equivalent to 3, but without the cheating. So let's do it that way... */ if (i == 3) { /* Peek at sequence number */ x = xunchar(dest[2]); /* If it's not in range... */ if (x < 0 || x > 63) { debug(F111,"ttinl xunchar(dest[2])",dest,x); return(-1); /* return a nonfatal error */ } } } else if ((i > pktlen+1) && (!inlturn || (inlturn && (n & ttpmsk) == inleol)) ) { /* We have the end of the packet */ inldest[i] = '\0'; /* Terminate the string, */ if (deblog) { if ((n & ttpmsk) != inleol) { debug(F101,"ttinl EOP length","",pktlen); debug(F101,"ttinl i","",i); } else debug(F101,"ttinl got eol","",inleol); debug(F101,"ttinl needpchk","",needpchk); debug(F101,"ttinl ttprty","",ttprty); debug(F101,"ttinl ttpmsk","",ttpmsk); } /* Parity checked yet? */ if ( needpchk ) { if (ttprty == 0) { if ((ttprty = parchk(inldest,inlstart,i)) > 0) { /* No */ int j; debug(F101,"ttinl senses parity","",ttprty); debug(F110,"ttinl packet before",inldest,0); ttpmsk = 0x7f; for (j = 0; j < i; j++) inldest[j] &= ttpmsk; /* Strip parity from packet */ debug(F110,"ttinl packet after ",inldest,0); } else ttprty = 0; /* restore if parchk error */ } sopmask = ttprty; needpchk = 0; } hexdump("ttinl got",inldest,i); inlret = i ; srvtimer = 0 ; /* if there is anything left in the buffer, we better save it */ /* But first, throw out chars that are before the start char */ while (++j= 0 ) { debug(F111,"ttinc","ttpush",ttpush); ch = ttpush; ttpush = -1; return(ch & m); } if ( LocalEchoData ) { if ( le_getchar(&ch) > 0 ) { debug(F111,"ttinc le_inbuf","ch",ch); return(ch & m); } } if (ttyfd == -1 #ifdef CK_TAPI || (tttapi && ttyfd == -2) #endif /* CK_TAPI */ ) return(-2); /* Not open. */ #ifdef SESLIMIT /* Session Limits go here */ /* if time() - start_time > limit */ if ( seslimit ) { time_t t = time(NULL) - start_time; if ( t > seslimit ) { debug(F111,"ttinc","Session Limit Exceeded",seslimit); return(-3); } #ifndef IKSDONLY else if ( downloaded && IsConnectMode() ) { if ( warn[0] ) { popupdemo(VTERM,seslimit - t); warn[0] = 0; } else if ( warn[1] && t > 300 ) { popupdemo(VTERM,seslimit - t); warn[1] = 0; } else if ( warn[2] && t > 600 ) { popupdemo(VTERM,seslimit - t); warn[2] = 0; } else if ( warn[3] && t > 840 ) { popupdemo(VTERM,seslimit - t); warn[3] = 0; } } #endif /* IKSDONLY */ } #endif /* SESLIMIT */ if ( tt_inpacing ) msleep(tt_inpacing); #ifdef NETCONN if (network) { extern int duplex; if ( !duplex #ifdef IKSD || inserver #endif /* IKSD */ ) { i = os2_netinc(timo); return(i >= 0 ? i & m : i); } else { if ( timo < 0 ) { j = -timo / 100; } else if ( timo > 0 ) j = timo * 10; do { if ( LocalEchoData ) { if ( le_getchar(&ch) > 0 ) { debug(F111,"ttinc le_inbuf","ch",ch); return(ch & m); } } i = os2_netinc(-100); } while (timo ? (i==-1 && --j>0) : (i == -1)); return(i >= 0 ? i & m : i); } } #endif /* NETCONN */ if (timo == 0) { /* Untimed read. */ do { i = rdch(ck_sleepint); if ( i < 0 && #ifdef COMMENT (ttcarr != CAR_OFF) && /* Carrier dropped */ ((ttgmdm() & BM_DCD) == 0) #else /* COMMENT */ (ttchk() < 0) #endif /* COMMENT */ ) DialerSend( OPT_KERMIT_HANGUP, 0 ) ; #ifdef NTSIG ck_ih(); #endif /* NTSIG */ if ( LocalEchoData ) { if ( le_getchar(&ch) > 0 ) { debug(F111,"ttinc le_inbuf","ch",ch); return(ch & m); } } } while (i == -1); /* Wait for a character. */ return(i >= 0 ? i & m : i); } /* Timed read */ if (timo < 0) /* Convert to milliseconds */ { timo= -timo; t = 0 ; } else { t = timo ; timo = timo * 1000; } #ifdef NT tt = timo / ck_sleepint; /* Break up into chunks */ tr = timo % ck_sleepint; /* Break up into chunks */ if ( tt ) interval = ck_sleepint + tr / tt ; else { tt = 1 ; interval = tr ; } debug(F111,"ttinc","rdch interval",interval); debug(F111,"ttinc","rdch tries",tt); for (j = 0; j < tt; j++) { /* to avoid being stuck */ i = rdch(interval); /* in a system call... */ #ifdef NTSIG ck_ih(); #endif /* NTSIG */ if (i >= 0) break; else if (i < -1) break; if ( LocalEchoData ) { if ( le_getchar(&ch) > 0 ) { debug(F111,"ttinc le_inbuf","ch",ch); return(ch & m); } } } #else /* NT */ i = rdch(timo); #endif /* NT */ return( (i < 0) ? i : (i & m) ); } /* RDCH -- Read characters from the serial port, maintaining an internal buffer of characters for the sake of efficiency. Timeout is specified in milliseconds. */ /* The MustComplete section in this code is required because SIO.SYS at least versions up to 1.45 set the length to buffersize when a SIGINT occurs during the processing of this call. */ #ifdef NEWRDCH static int rdch(int timo /* ms */) { ULONG Nesting; #ifdef NT COMMTIMEOUTS timeouts ; static int OldReadPending = FALSE ; int rc=0; #endif /* NT */ if ( ttyfd == -1 #ifdef CK_TAPI || (tttapi && ttyfd == -2) #endif /* CK_TAPI */ ) return -2; /* No connection */ if (rdchbuf.index == rdchbuf.length) { rdchbuf.index = rdchbuf.length = 0; rmstimer(); debug(F111,"NEWRDCH rdch","timo",timo); if ( timo == 0 ) { #ifdef NT memset(&timeouts, 0, sizeof(COMMTIMEOUTS)) ; GetCommTimeouts( (HANDLE) ttyfd, &timeouts ) ; /* These settings will wait until at least one character is available to be read. at least in Win95 */ timeouts.ReadIntervalTimeout = MAXDWORD ; timeouts.ReadTotalTimeoutMultiplier = MAXDWORD ; timeouts.ReadTotalTimeoutConstant = 10 ; debug(F111,"NEWRDCH rdch SetCommTimeouts","WriteTotalTimeoutMultiplier", timeouts.WriteTotalTimeoutMultiplier); debug(F111,"NEWRDCH rdch SetCommTimeouts","WriteTotalTimeoutConstant", timeouts.WriteTotalTimeoutConstant); SetCommTimeouts( (HANDLE) ttyfd, &timeouts ) ; #else /* NT */ if (ttydcb.usReadTimeout != 9) { ttydcb.usReadTimeout = 9; /* Test every 0.1s per call */ if (DosDevIOCtl(NULL,0,&ttydcb,sizeof(ttydcb), ASYNC_SETDCBINFO,1,ttyfd)) return(-1); } #endif /* NT */ } else { #ifdef NT memset(&timeouts, 0, sizeof(COMMTIMEOUTS) ) ; GetCommTimeouts( (HANDLE) ttyfd, &timeouts ) ; timeouts.ReadIntervalTimeout = MAXDWORD ; timeouts.ReadTotalTimeoutMultiplier = MAXDWORD ; timeouts.ReadTotalTimeoutConstant = timo; debug(F111,"NEWRDCH rdch SetCommTimeouts","WriteTotalTimeoutMultiplier", timeouts.WriteTotalTimeoutMultiplier); debug(F111,"NEWRDCH rdch SetCommTimeouts","WriteTotalTimeoutConstant", timeouts.WriteTotalTimeoutConstant); SetCommTimeouts( (HANDLE) ttyfd, &timeouts ) ; #else /* NT */ if (ttydcb.usReadTimeout != timo) { /* Set timeout value */ ttydcb.usReadTimeout = (timo/10)-1; /* 0.01 sec units. 0 = 0.01 sec */ if (DosDevIOCtl(NULL,0,&ttydcb,sizeof(ttydcb), ASYNC_SETDCBINFO,IOCTL_ASYNC,ttyfd)) return(-1); } #endif /* NT */ } #ifdef NT #ifndef COMMENT rc = OverlappedRead( TRUE, rdchbuf.buffer, sizeof(rdchbuf.buffer), timo ); if ( rc >= 0 ) rdchbuf.length = rc; else return(rc); #else /* COMMENT */ if ( overlapped_read.hEvent == (HANDLE) -1 ) { overlapped_read.hEvent = CreateEvent( NULL, /* no security */ TRUE, /* explicit reset req */ FALSE, /* initial event set */ NULL /* no name */ ); if (overlapped_read.hEvent == (HANDLE) -1) { debug(F101,"rdch CreateEvent error","",GetLastError() ) ; } } if ( !OldReadPending ) { overlapped_read.Offset = overlapped_read.OffsetHigh = 0 ; ResetEvent( overlapped_read.hEvent ) ; } if (OldReadPending || !ReadFile((HANDLE) ttyfd, rdchbuf.buffer, sizeof(rdchbuf.buffer), &nActuallyRead, &overlapped_read) ) { DWORD error = GetLastError() ; if ( OldReadPending || error == ERROR_IO_PENDING ) { int timedout=FALSE; #ifndef COMMENT debug(F100,"rdch ReadFile ERROR_IO_PENDING","",0); #endif /* COMMENT */ while(!GetOverlappedResult( (HANDLE) ttyfd, &overlapped_read, &nActuallyRead, FALSE ) ) { DWORD error = GetLastError() ; if ( error == ERROR_IO_INCOMPLETE ) { int rc=0; debug(F100,"rdch ReadFile ERROR_IO_INCOMPLETE","",0); if ( timedout ) { debug(F110,"rdch ReadFile","timedout",0); OldReadPending = TRUE; return(-1); } rc = WaitForSingleObjectEx( overlapped_read.hEvent, timo, TRUE ) ; debug(F111,"rdch WaitForSingleObjectEx","rc",rc); if ( rc != WAIT_OBJECT_0 ) timedout = TRUE; continue; } else if ( error == ERROR_OPERATION_ABORTED ) { debug(F100,"rdch ReadFile OPERATION ABORTED","",0); ResetEvent( overlapped_read.hEvent ) ; if (nActuallyRead > 0 ) rdchbuf.length = nActuallyRead ; OldReadPending = FALSE; return (-1); /* fdc */ } else { DWORD errorflags ; COMSTAT comstat ; debug(F101,"rdch ReadFile Overlapped I/O Error", "",error); ClearCommError( (HANDLE) ttyfd, &errorflags, &comstat ); debug(F101,"rdch ClearCommError","",errorflags); if ( errorflags && deblog ) { if ( errorflags & CE_RXOVER ) debug(F110,"ClearCommError","Receive Queue overflow",0); if ( errorflags & CE_OVERRUN ) debug(F110,"ClearCommError","Receive Overrun error",0); if ( errorflags & CE_RXPARITY ) debug(F110,"ClearCommError","Receive Parity error",0); if ( errorflags & CE_FRAME ) debug(F110,"ClearCommError","Receive Framing error",0); if ( errorflags & CE_BREAK ) debug(F110,"ClearCommError","Break detected",0); if ( errorflags & CE_TXFULL ) debug(F110,"ClearCommError","TX Queue is full",0); if ( errorflags & CE_PTO ) debug(F110,"ClearCommError","LPTx Timeout",0); if ( errorflags & CE_IOE ) debug(F110,"ClearCommError","LPTx I/O Error",0); if ( errorflags & CE_DNS ) debug(F110,"ClearCommError","LPTx Device Not Selected",0); if ( errorflags & CE_OOP ) debug(F110,"ClearCommError","LPTx Out Of Paper",0); } if ( deblog ) { debug(F111,"ClearCommError","Cts Hold",comstat.fCtsHold); debug(F111,"ClearCommError","Dsr Hold",comstat.fDsrHold); debug(F111,"ClearCommError","Rlsd Hold",comstat.fRlsdHold); debug(F111,"ClearCommError","Xoff Hold",comstat.fXoffHold); debug(F111,"ClearCommError","Xoff Sent",comstat.fXoffSent); debug(F111,"ClearCommError","Eof",comstat.fEof); debug(F111,"ClearCommError","Tx Immed",comstat.fTxim); debug(F111,"ClearCommError","In Que",comstat.cbInQue); debug(F111,"ClearCommError","Out Que",comstat.cbOutQue); } ResetEvent( overlapped_read.hEvent ) ; if (nActuallyRead > 0 ) rdchbuf.length = nActuallyRead ; OldReadPending = FALSE; return -1; } } } else { DWORD errorflags ; COMSTAT comstat ; debug(F101,"rdch ReadFile - real error occurred","",error) ; ClearCommError( (HANDLE) ttyfd, &errorflags, &comstat ); debug(F101,"rdch ClearCommError","",errorflags); if ( errorflags && deblog ) { if ( errorflags & CE_RXOVER ) debug(F110,"ClearCommError","Receive Queue overflow",0); if ( errorflags & CE_OVERRUN ) debug(F110,"ClearCommError","Receive Overrun error",0); if ( errorflags & CE_RXPARITY ) debug(F110,"ClearCommError","Receive Parity error",0); if ( errorflags & CE_FRAME ) debug(F110,"ClearCommError","Receive Framing error",0); if ( errorflags & CE_BREAK ) debug(F110,"ClearCommError","Break detected",0); if ( errorflags & CE_TXFULL ) debug(F110,"ClearCommError","TX Queue is full",0); if ( errorflags & CE_PTO ) debug(F110,"ClearCommError","LPTx Timeout",0); if ( errorflags & CE_IOE ) debug(F110,"ClearCommError","LPTx I/O Error",0); if ( errorflags & CE_DNS ) debug(F110,"ClearCommError","LPTx Device Not Selected",0); if ( errorflags & CE_OOP ) debug(F110,"ClearCommError","LPTx Out Of Paper",0); } if ( deblog ) { debug(F111,"ClearCommError","Cts Hold",comstat.fCtsHold); debug(F111,"ClearCommError","Dsr Hold",comstat.fDsrHold); debug(F111,"ClearCommError","Rlsd Hold",comstat.fRlsdHold); debug(F111,"ClearCommError","Xoff Hold",comstat.fXoffHold); debug(F111,"ClearCommError","Xoff Sent",comstat.fXoffSent); debug(F111,"ClearCommError","Eof",comstat.fEof); debug(F111,"ClearCommError","Tx Immed",comstat.fTxim); debug(F111,"ClearCommError","In Que",comstat.cbInQue); debug(F111,"ClearCommError","Out Que",comstat.cbOutQue); } ResetEvent( overlapped_read.hEvent ) ; if (nActuallyRead > 0 ) rdchbuf.length = nActuallyRead ; OldReadPending = FALSE; return -2 ; } } ResetEvent( overlapped_read.hEvent ) ; #ifndef COMMENT debug(F101,"rdch nActuallyRead","",nActuallyRead ) ; debug(F101,"rdch overlapped_read.Offset","",overlapped_read.Offset) ; #endif /* COMMENT */ rdchbuf.length = nActuallyRead ; #endif /* COMMENT */ #else /* NT */ DosEnterMustComplete( &Nesting ) ; if (DosRead(ttyfd,rdchbuf.buffer,sizeof(rdchbuf.buffer), &rdchbuf.length)) { rdchbuf.length = 0; DosExitMustComplete( &Nesting ); return(-1); } DosExitMustComplete( &Nesting ); #endif /* NT */ } #ifndef COMMENT debug(F101,"rdch() index","",rdchbuf.index); debug(F101,"rdch() length","",rdchbuf.length); #endif /* COMMENT */ #ifdef NT OldReadPending = FALSE; #endif /* NT */ return((rdchbuf.index < rdchbuf.length) ? rdchbuf.buffer[rdchbuf.index++] : -1 ); } #else /* NEWRDCH */ static int rdch(int timo /* ms */) { ULONG Nesting; #ifdef NT COMMTIMEOUTS timeouts ; static int OldReadPending = FALSE ; #endif /* NT */ if ( ttyfd == -1 #ifdef CK_TAPI || (tttapi && ttyfd == -2) #endif /* CK_TAPI */ ) return -2; /* No connection */ if (rdchbuf.index == rdchbuf.length) { rdchbuf.index = rdchbuf.length = 0; debug(F111,"OLD rdch","timo",timo); if ( timo == 0 ) { #ifdef NT int change = 0; memset(&timeouts, 0, sizeof(COMMTIMEOUTS)) ; GetCommTimeouts( (HANDLE) ttyfd, &timeouts ) ; /* These settings will wait until at least one character is available to be read. at least in Win95 */ if ( timeouts.ReadIntervalTimeout != MAXDWORD ) { timeouts.ReadIntervalTimeout = MAXDWORD ; change++; } if ( timeouts.ReadTotalTimeoutMultiplier != MAXDWORD ) { timeouts.ReadTotalTimeoutMultiplier = MAXDWORD ; change++; } if ( timeouts.ReadTotalTimeoutConstant != 10 ) { timeouts.ReadTotalTimeoutConstant = 10 ; change++; } if ( change ) { debug(F111,"OLD rdch SetCommTimeouts","WriteTotalTimeoutMultiplier", timeouts.WriteTotalTimeoutMultiplier); debug(F111,"OLD rdch SetCommTimeouts","WriteTotalTimeoutConstant", timeouts.WriteTotalTimeoutConstant); SetCommTimeouts( (HANDLE) ttyfd, &timeouts ) ; } #else /* NT */ if (ttydcb.usReadTimeout != 9) { ttydcb.usReadTimeout = 9; /* Test every 0.1s per call */ if (DosDevIOCtl(NULL,0,&ttydcb,sizeof(ttydcb), ASYNC_SETDCBINFO,1,ttyfd)) return(-1); } #endif /* NT */ } else { #ifdef NT int change = 0; memset(&timeouts, 0, sizeof(COMMTIMEOUTS) ) ; GetCommTimeouts( (HANDLE) ttyfd, &timeouts ) ; if ( timeouts.ReadIntervalTimeout != MAXDWORD ) { timeouts.ReadIntervalTimeout = MAXDWORD ; change++; } if ( timeouts.ReadTotalTimeoutMultiplier != MAXDWORD ) { timeouts.ReadTotalTimeoutMultiplier = MAXDWORD ; change++; } if ( timeouts.ReadTotalTimeoutConstant != timo ) { timeouts.ReadTotalTimeoutConstant = timo ; change++; } if ( change ) { debug(F111,"OLD rdch SetCommTimeouts","WriteTotalTimeoutMultiplier", timeouts.WriteTotalTimeoutMultiplier); debug(F111,"OLD rdch SetCommTimeouts","WriteTotalTimeoutConstant", timeouts.WriteTotalTimeoutConstant); SetCommTimeouts( (HANDLE) ttyfd, &timeouts ) ; } #else /* NT */ if (ttydcb.usReadTimeout != timo) { /* Set timeout value */ ttydcb.usReadTimeout = (timo/10)-1; /* 0.01 sec units. 0 = 0.01 sec */ if (DosDevIOCtl(NULL,0,&ttydcb,sizeof(ttydcb), ASYNC_SETDCBINFO,IOCTL_ASYNC,ttyfd)) return(-1); } #endif /* NT */ } #ifdef NT if ( overlapped_read[0].hEvent == (HANDLE) -1 ) { overlapped_read[0].hEvent = CreateEvent( NULL, /* no security */ TRUE, /* explicit reset req */ FALSE, /* initial event set */ NULL /* no name */ ); if (overlapped_read[0].hEvent == (HANDLE) -1) { debug(F101,"rdch CreateEvent error","",GetLastError() ) ; } } if ( !OldReadPending ) { overlapped_read[0].Offset = overlapped_read[0].OffsetHigh = 0 ; ResetEvent( overlapped_read[0].hEvent ) ; } if (OldReadPending || !ReadFile((HANDLE) ttyfd, rdchbuf.buffer, sizeof(rdchbuf.buffer), &nActuallyRead, &overlapped_read[0]) ) { DWORD error = GetLastError() ; if ( OldReadPending || error == ERROR_IO_PENDING ) { int timedout=FALSE; #ifndef COMMENT debug(F100,"rdch ReadFile ERROR_IO_PENDING","",0); #endif /* COMMENT */ while(!GetOverlappedResult( (HANDLE) ttyfd, &overlapped_read[0], &nActuallyRead, FALSE ) ) { DWORD error = GetLastError() ; if ( error == ERROR_IO_INCOMPLETE ) { int rc=0; debug(F100,"rdch ReadFile ERROR_IO_INCOMPLETE","",0); if ( timedout ) { debug(F110,"rdch ReadFile","timedout",0); OldReadPending = TRUE; return(-1); } rc = WaitForSingleObjectEx( overlapped_read[0].hEvent, timo, TRUE ) ; debug(F111,"rdch WaitForSingleObjectEx","rc",rc); if ( rc != WAIT_OBJECT_0 ) timedout = TRUE; continue; } else if ( error == ERROR_OPERATION_ABORTED ) { debug(F100,"rdch ReadFile OPERATION ABORTED","",0); ResetEvent( overlapped_read[0].hEvent ) ; if (nActuallyRead > 0 ) rdchbuf.length = nActuallyRead ; OldReadPending = FALSE; return (-1); /* fdc */ } else { DWORD errorflags ; COMSTAT comstat ; debug(F101,"rdch ReadFile Overlapped I/O Error", "",error); ClearCommError( (HANDLE) ttyfd, &errorflags, &comstat ); debug(F101,"rdch ClearCommError","",errorflags); if ( errorflags && deblog ) { if ( errorflags & CE_RXOVER ) debug(F110,"ClearCommError","Receive Queue overflow",0); if ( errorflags & CE_OVERRUN ) debug(F110,"ClearCommError","Receive Overrun error",0); if ( errorflags & CE_RXPARITY ) debug(F110,"ClearCommError","Receive Parity error",0); if ( errorflags & CE_FRAME ) debug(F110,"ClearCommError","Receive Framing error",0); if ( errorflags & CE_BREAK ) debug(F110,"ClearCommError","Break detected",0); if ( errorflags & CE_TXFULL ) debug(F110,"ClearCommError","TX Queue is full",0); if ( errorflags & CE_PTO ) debug(F110,"ClearCommError","LPTx Timeout",0); if ( errorflags & CE_IOE ) debug(F110,"ClearCommError","LPTx I/O Error",0); if ( errorflags & CE_DNS ) debug(F110,"ClearCommError","LPTx Device Not Selected",0); if ( errorflags & CE_OOP ) debug(F110,"ClearCommError","LPTx Out Of Paper",0); } if ( deblog ) { debug(F111,"ClearCommError","Cts Hold",comstat.fCtsHold); debug(F111,"ClearCommError","Dsr Hold",comstat.fDsrHold); debug(F111,"ClearCommError","Rlsd Hold",comstat.fRlsdHold); debug(F111,"ClearCommError","Xoff Hold",comstat.fXoffHold); debug(F111,"ClearCommError","Xoff Sent",comstat.fXoffSent); debug(F111,"ClearCommError","Eof",comstat.fEof); debug(F111,"ClearCommError","Tx Immed",comstat.fTxim); debug(F111,"ClearCommError","In Que",comstat.cbInQue); debug(F111,"ClearCommError","Out Que",comstat.cbOutQue); } if ( deblog ) { debug(F111,"ClearCommError","Cts Hold",comstat.fCtsHold); debug(F111,"ClearCommError","Dsr Hold",comstat.fDsrHold); debug(F111,"ClearCommError","Rlsd Hold",comstat.fRlsdHold); debug(F111,"ClearCommError","Xoff Hold",comstat.fXoffHold); debug(F111,"ClearCommError","Xoff Sent",comstat.fXoffSent); debug(F111,"ClearCommError","Eof",comstat.fEof); debug(F111,"ClearCommError","Tx Immed",comstat.fTxim); debug(F111,"ClearCommError","In Que",comstat.cbInQue); debug(F111,"ClearCommError","Out Que",comstat.cbOutQue); } ResetEvent( overlapped_read[0].hEvent ) ; if (nActuallyRead > 0 ) rdchbuf.length = nActuallyRead ; OldReadPending = FALSE; return -1; } } } else { DWORD errorflags ; COMSTAT comstat ; debug(F101,"rdch ReadFile - real error occurred","",error) ; ClearCommError( (HANDLE) ttyfd, &errorflags, &comstat ); debug(F101,"rdch ClearCommError","",errorflags); if ( errorflags && deblog ) { if ( errorflags & CE_RXOVER ) debug(F110,"ClearCommError","Receive Queue overflow",0); if ( errorflags & CE_OVERRUN ) debug(F110,"ClearCommError","Receive Overrun error",0); if ( errorflags & CE_RXPARITY ) debug(F110,"ClearCommError","Receive Parity error",0); if ( errorflags & CE_FRAME ) debug(F110,"ClearCommError","Receive Framing error",0); if ( errorflags & CE_BREAK ) debug(F110,"ClearCommError","Break detected",0); if ( errorflags & CE_TXFULL ) debug(F110,"ClearCommError","TX Queue is full",0); if ( errorflags & CE_PTO ) debug(F110,"ClearCommError","LPTx Timeout",0); if ( errorflags & CE_IOE ) debug(F110,"ClearCommError","LPTx I/O Error",0); if ( errorflags & CE_DNS ) debug(F110,"ClearCommError","LPTx Device Not Selected",0); if ( errorflags & CE_OOP ) debug(F110,"ClearCommError","LPTx Out Of Paper",0); } if ( deblog ) { debug(F111,"ClearCommError","Cts Hold",comstat.fCtsHold); debug(F111,"ClearCommError","Dsr Hold",comstat.fDsrHold); debug(F111,"ClearCommError","Rlsd Hold",comstat.fRlsdHold); debug(F111,"ClearCommError","Xoff Hold",comstat.fXoffHold); debug(F111,"ClearCommError","Xoff Sent",comstat.fXoffSent); debug(F111,"ClearCommError","Eof",comstat.fEof); debug(F111,"ClearCommError","Tx Immed",comstat.fTxim); debug(F111,"ClearCommError","In Que",comstat.cbInQue); debug(F111,"ClearCommError","Out Que",comstat.cbOutQue); } ResetEvent( overlapped_read[0].hEvent ) ; if (nActuallyRead > 0 ) rdchbuf.length = nActuallyRead ; OldReadPending = FALSE; return -2 ; } } ResetEvent( overlapped_read[0].hEvent ) ; #ifndef COMMENT debug(F101,"rdch nActuallyRead","",nActuallyRead ) ; debug(F101,"rdch overlapped_read.Offset","",overlapped_read[0].Offset) ; #endif /* COMMENT */ rdchbuf.length = nActuallyRead ; #else /* NT */ DosEnterMustComplete( &Nesting ) ; if (DosRead(ttyfd,rdchbuf.buffer,sizeof(rdchbuf.buffer), &rdchbuf.length)) { rdchbuf.length = 0; DosExitMustComplete( &Nesting ); return(-1); } DosExitMustComplete( &Nesting ); #endif /* NT */ } #ifdef COMMENT debug(F101,"rdch() index","",rdchbuf.index); debug(F101,"rdch() length","",rdchbuf.length); #endif /* COMMENT */ #ifdef NT OldReadPending = FALSE; #endif /* NT */ return((rdchbuf.index < rdchbuf.length) ? rdchbuf.buffer[rdchbuf.index++] : -1 ); } #endif /* NEWRDCH */ /* T T S C A R R -- Set ttcarr variable, controlling carrier handling. * * 0 = Off: Always ignore carrier. E.g. you can connect without carrier. * 1 = On: Heed carrier, except during dialing. Carrier loss gives disconnect. * 2 = Auto: For "modem direct": The same as "Off". * For real modem types: Heed carrier during connect, but ignore * it anytime else. Compatible with pre-5A Kermit versions. */ int ttscarr(int carrier) { ttcarr = carrier; debug(F101, "ttscarr","",ttcarr); return(ttcarr); } /* T T G M D M -- Get modem signals */ /* Looks for the modem signals CTS, DSR, and CTS, and returns those that are on in as its return value, in a bit mask as described for ttwmdm. Returns: -3 Not implemented -2 if the line does not have modem control -1 on error. >= 0 on success, with a bit mask containing the modem signals that are on. */ int ttgmdm() { #ifdef NT DWORD ModemStat ; #else /* NT */ BYTE instat, outstat; #endif /* NT */ int modem = 0; if (ttyfd == -1 #ifdef CK_TAPI || (tttapi && ttyfd == -2) #endif /* CK_TAPI */ ) return(-1); #ifdef TN_COMPORT if (network) return(tngmdm()); #endif /* TN_COMPORT */ #ifdef NT #ifdef CK_TAPI if ( tttapi && !tapipass ) { HANDLE hModem = NULL; if (ttyfd == -2) return(-1); hModem = GetModemHandleFromLine( (HLINE) 0 ); if ( hModem == NULL ) return(-1); if (!GetCommModemStatus( hModem, &ModemStat )) { CloseHandle( hModem ); return -1 ; } CloseHandle( hModem ); } else #endif /* CK_TAPI */ if (!GetCommModemStatus( (HANDLE) ttyfd, &ModemStat )) return -1 ; if (ModemStat & MS_CTS_ON) modem |= BM_CTS ; if (ModemStat & MS_DSR_ON) modem |= BM_DSR ; if (ModemStat & MS_RING_ON) modem |= BM_RNG ; if (ModemStat & MS_RLSD_ON) modem |= BM_DCD ; #else /* NT */ if(DosDevIOCtl(&instat,sizeof(instat),NULL,0, ASYNC_GETMODEMINPUT,IOCTL_ASYNC,ttyfd)) return(-1); if(DosDevIOCtl(&outstat,sizeof(outstat),NULL,0, ASYNC_GETMODEMOUTPUT,IOCTL_ASYNC,ttyfd)) return(-1); /* Clear To Send */ if (instat & CTS_ON) modem |= BM_CTS; /* Data Set Ready */ if (instat & DSR_ON) modem |= BM_DSR; /* Carrier */ if (instat & DCD_ON) modem |= BM_DCD; /* Ring Indicate */ if (instat & RI_ON) modem |= BM_RNG; /* Data Terminal Ready */ if (outstat & DTR_ON) modem |= BM_DTR; /* Request To Send */ if (outstat & RTS_ON) modem |= BM_RTS; #endif /* NT */ return(modem); } /* T T S N D B -- Send a BREAK signal */ int ttsndb() { #ifdef OS2ONLY MODEMSTATUS ms; UINT data, i; #endif /* OS2ONLY */ #ifdef NETCONN if (network) { #ifdef TN_COMPORT if (istncomport()) { if (tnsndb(275L) >= 0) return(0); } #endif /* TN_COMPORT */ return(os2_netbreak()); } #endif /* NETCONN */ #ifdef NT SetCommBreak( (HANDLE) ttyfd ) ; msleep(275L); ClearCommBreak( (HANDLE) ttyfd ) ; #else /* NT */ ms.fbModemOn = RTS_ON; ms.fbModemOff = 255; DosDevIOCtl(&data,sizeof(data),&ms,sizeof(ms), ASYNC_SETMODEMCTRL,IOCTL_ASYNC,ttyfd); DosDevIOCtl(&i,sizeof(i),NULL,0, ASYNC_SETBREAKON,IOCTL_ASYNC,ttyfd); /* Break on */ msleep(275L); /* ZZZzzz */ DosDevIOCtl(&i,sizeof(i),NULL,0, ASYNC_SETBREAKOFF,IOCTL_ASYNC,ttyfd); /* Break off */ #endif /* NT */ return 0; } /* T T S N D L B -- Send a LONG BREAK signal */ int ttsndlb() { #ifndef NT MODEMSTATUS ms; UINT data, i; #endif /* NT */ #ifdef NETCONN if (network) { #ifdef TN_COMPORT if (istncomport()) { if (tnsndb(1800L) >= 0) return(0); } #endif /* TN_COMPORT */ return(os2_netbreak()); } #endif /* NETCONN */ #ifdef NT SetCommBreak( (HANDLE) ttyfd ) ; msleep(1800L); ClearCommBreak( (HANDLE) ttyfd ) ; #else /* NT */ ms.fbModemOn = RTS_ON; ms.fbModemOff = 255; DosDevIOCtl(&data,sizeof(data),&ms,sizeof(ms), ASYNC_SETMODEMCTRL,IOCTL_ASYNC,ttyfd); DosDevIOCtl(&i,sizeof(i),NULL,0, ASYNC_SETBREAKON,IOCTL_ASYNC,ttyfd); /* Break on */ msleep(1800L); /* ZZZzzz */ DosDevIOCtl(&i,sizeof(i),NULL,0, ASYNC_SETBREAKOFF,IOCTL_ASYNC,ttyfd); /* Break off */ #endif /* NT*/ return 0; } #ifndef __EMX__ /* S L E E P -- Emulate the Unix sleep function */ /* MustComplete section required because of a bug in OS/2 that fails to allow us to reset the SIGINT signal after it has occurred during this call. */ unsigned sleep(t) unsigned int t; { ULONG start_t, now_t, ms; int tt, tr, i; #ifndef NT unsigned long p ; #endif /* NT */ #ifdef NT start_t = GetTickCount(); /* msecs since Windows was started */ #else /* NT */ DosQuerySysInfo(QSV_MS_COUNT,QSV_MS_COUNT,&start_t,4); #endif /* NT */ tt = (t * 1000L) / ck_sleepint; tr = (t * 1000L) % ck_sleepint; for (i = 0; i < tt; i++) { #ifdef NT Sleep((long) ck_sleepint); #else /* NT */ DosEnterMustComplete(&p); DosSleep((long)ck_sleepint); DosExitMustComplete(&p); #endif /* NT */ #ifdef NTSIG ck_ih(); #endif /* NTSIG */ #ifdef NT now_t = GetTickCount(); #else /* NT */ DosQuerySysInfo(QSV_MS_COUNT,QSV_MS_COUNT,&now_t,4); #endif /* NT */ if ( now_t < start_t ) { /* we wrapped */ #ifdef NT ms = (MAXDWORD - start_t + now_t); #else /* NT */ ms = (ULONG_MAX - start_t + now_t); #endif /* NT */ } else { ms = (now_t - start_t); } if ( ms >= (t * 1000L) ) return(0); } if ( tr ) { #ifdef NT Sleep((long) tr); #else /* NT */ DosEnterMustComplete(&p); DosSleep((long)tr); DosExitMustComplete(&p); #endif /* NT */ #ifdef NTSIG ck_ih(); #endif /* NTSIG */ } return(0); } #endif /* __EMX__ */ /* M S L E E P -- Millisecond version of sleep(). */ /* Intended only for small intervals. For big ones, just use sleep(). */ /* MustComplete section required because of a bug in OS/2 that fails to allow us to reset the SIGINT signal after it has occurred during this call. */ int msleep(int m) { ULONG start_t, now_t, ms; int tt, tr, ti, i; #ifndef NT unsigned long p ; #endif #ifdef NT start_t = GetTickCount(); /* msecs since Windows was started */ #else /* NT */ DosQuerySysInfo(QSV_MS_COUNT,QSV_MS_COUNT,&start_t,4); #endif /* NT */ if ( m <= 500 ) { #ifdef NT Sleep((long) m); #else /* NT */ DosEnterMustComplete(&p); DosSleep((long)m); DosExitMustComplete(&p); #endif /* NT */ #ifdef NTSIG ck_ih(); #endif /* NTSIG */ return(0); } tt = m / ck_sleepint; tr = m % ck_sleepint; ti = ck_sleepint; for (i = 0; i < tt; i++) { #ifdef NT Sleep((long) ti); #else /* NT */ DosEnterMustComplete(&p); DosSleep((long)ti); DosExitMustComplete(&p); #endif /* NT */ #ifdef NTSIG ck_ih(); #endif /* NTSIG */ #ifdef NT now_t = GetTickCount(); #else /* NT */ DosQuerySysInfo(QSV_MS_COUNT,QSV_MS_COUNT,&now_t,4); #endif /* NT */ if ( now_t < start_t ) { /* we wrapped */ #ifdef NT ms = (MAXDWORD - start_t + now_t); #else /* NT */ ms = (ULONG_MAX - start_t + now_t); #endif /* NT */ } else { ms = (now_t - start_t); } if ( ms >= m ) return(0); } if ( tr ) { #ifdef NT Sleep((long) tr); #else /* NT */ DosEnterMustComplete(&p); DosSleep((long)tr); DosExitMustComplete(&p); #endif /* NT */ #ifdef NTSIG ck_ih(); #endif /* NTSIG */ } return (0); } /* R T I M E R -- Reset elapsed time counter */ void rtimer() { #ifdef NT tcount = GetTickCount(); /* msecs since Windows was started */ #else /* NT */ DosQuerySysInfo(QSV_MS_COUNT,QSV_MS_COUNT,&tcount,4); #endif /* NT */ debug(F101,"rtimer tick_count","",tcount); } /* G T I M E R -- Get current value of elapsed time counter in seconds */ int gtimer(void) { #ifdef NT DWORD tick_now=0L; #else /* NT */ ULONG tick_now=0L; #endif /* NT */ int s=0; #ifdef NT tick_now = GetTickCount(); #else /* NT */ DosQuerySysInfo(QSV_MS_COUNT,QSV_MS_COUNT,&tick_now,4); #endif /* NT */ if ( tick_now < tcount ) { /* we wrapped */ #ifdef NT s = (MAXDWORD - tcount + tick_now) / 1000; #else /* NT */ s = (ULONG_MAX - tcount + tick_now) / 1000; #endif /* NT */ } else { s = (tick_now - tcount) / 1000; } if (s < 0) s=0; return(s); } #ifdef GFTIMER #ifdef NT DWORD tick_count=0L; DWORD tick_count2=0L; #else /* NT */ ULONG tick_count=0L; ULONG tick_count2=0L; #endif /* NT */ VOID rftimer() { #ifdef NT tick_count = GetTickCount(); /* msecs since Windows was started */ /* wraps at 49.7 days */ #else /* NT */ DosQuerySysInfo(QSV_MS_COUNT,QSV_MS_COUNT,&tick_count,4); #endif /* NT */ debug(F101,"rftimer tick_count","",tick_count); } CKFLOAT gftimer() { #ifdef NT DWORD tick_now=0L; #else /* NT */ ULONG tick_now=0L; #endif /* NT */ double s=0.0; #ifdef DEBUG char fpbuf[64]; #endif /* DEBUG */ #ifdef NT tick_now = GetTickCount(); #else /* NT */ DosQuerySysInfo(QSV_MS_COUNT,QSV_MS_COUNT,&tick_now,4); #endif /* NT */ if ( tick_now < tick_count ) { /* we wrapped */ #ifdef NT s = (double) (MAXDWORD - tick_count + tick_now) / 1000; #else /* NT */ s = (double) (ULONG_MAX - tick_count + tick_now) / 1000; #endif /* NT */ } else { s = (double) (tick_now - tick_count) / 1000; } if (s == 0.0) s = 0.000001; #ifdef DEBUG if (deblog) { sprintf(fpbuf,"%f",s); debug(F111,"gftimer",fpbuf,tick_now); } #endif /* DEBUG */ return((CKFLOAT)s); } VOID rmstimer() { #ifdef NT tick_count2 = GetTickCount(); /* msecs since Windows was started */ /* wraps at 49.7 days */ #else /* NT */ DosQuerySysInfo(QSV_MS_COUNT,QSV_MS_COUNT,&tick_count2,4); #endif /* NT */ debug(F101,"rmstimer tick_count2","",tick_count2); } ULONG gmstimer() { #ifdef NT DWORD tick_now=0L; #else /* NT */ ULONG tick_now=0L; #endif /* NT */ ULONG s; #ifdef DEBUG char fpbuf[64]; #endif /* DEBUG */ #ifdef NT tick_now = GetTickCount(); #else /* NT */ DosQuerySysInfo(QSV_MS_COUNT,QSV_MS_COUNT,&tick_now,4); #endif /* NT */ if ( tick_now < tick_count2 ) { /* we wrapped */ #ifdef NT s = (MAXDWORD - tick_count2 + tick_now); #else /* NT */ s = (ULONG_MAX - tick_count2 + tick_now); #endif /* NT */ } else { s = (tick_now - tick_count2); } #ifdef DEBUG if (deblog) { sprintf(fpbuf,"%d",s); debug(F111,"gmstimer",fpbuf,tick_now); } #endif /* DEBUG */ return(s); } #endif /* GFTIMER */ /* Z T I M E -- Return date/time string */ void ztime(char **s) { time_t clock_storage; clock_storage = time( (long *) 0 ); *s = ctime( &clock_storage ); } void loadtod( int hh, int mm ) { #ifdef NT SYSTEMTIME systime ; GetLocalTime( &systime ) ; systime.wHour = hh ; systime.wMinute = mm ; systime.wSecond = 0 ; systime.wMilliseconds = 0 ; SetLocalTime( &systime ) ; #else /* NT */ DATETIME DateTime = {0}; /* Structure to hold date/time info. */ APIRET rc = NO_ERROR; /* Return code */ /* Retrieve the current date and time */ if ( DosGetDateTime(&DateTime) == NO_ERROR ) { DateTime.hours = (UCHAR) hh; DateTime.minutes = (UCHAR) mm; DateTime.seconds = 0 ; DateTime.hundredths = 0 ; rc = DosSetDateTime(&DateTime); /* Update the date and time */ } #endif /* NT */ } /* C O N O C -- Output a character to the console terminal */ int conoc(char c) { extern unsigned char colorcmd; extern int wherex[]; /* Screen column, 1-based */ extern int wherey[]; /* Screen row, 1-based */ #ifdef IKSD if ( inserver ) { debug(F100,"conoc inserver","",0); ttoc(c); } #endif /* IKSD */ #ifndef NOLOCAL if ( k95stdout ) fwrite(&c,1,1,stdout); else { VscrnWrtCharStrAtt( VCMD, &c, 1, wherey[VCMD], wherex[VCMD], &colorcmd ) ; } #endif /* NOLOCAL */ return 1; } /* C O N X O -- Write x characters to the console terminal */ int conxo(int x, char *s) { int i, rc; if ( s == NULL ) return(-1); #ifdef IKSD if ( inserver ) { debug(F100,"conxo inserver","",0); return(ttol(s,x)); } #endif /* IKSD */ for ( i=0 ; iy+1, VscrnGetCurPos(VCMD)->x+1, &colorcmd ) ; #endif /* NOLOCAL */ return 0; } /* C O N O L A -- Write an array of lines to the console terminal */ int conola(s) char *s[]; { int i; if ( s == NULL ) return(-1); for (i=0 ; *s[i] ; i++) conol(s[i]); return 0 ; } /* C O N O L L -- Output a string followed by CRLF */ int conoll(s) char *s; { if ( s == NULL ) return(-1); conol(s); conol("\r\n"); return 0 ; } /* C O N C H K -- Return how many characters available at console */ int conchk() { #ifdef IKSD if ( inserver ) { return(ttchk()); } else #endif /* IKSD */ return charinbuf(VCMD) ; } /* C O N I N C -- Get a character from the console */ /* Call with timo > 0 to do a timed read, timo == 0 to do an untimed blocking read. Upon success, returns the character. Upon failure, returns -1. A timed read that does not complete within the timeout period returns -2. */ int coninc(timo) int timo; { int c, rc = -1, cm; extern int what; #ifndef NOTERM extern enum markmodes markmodeflag[VNUM]; #endif /* NOTERM */ time_t t; debug(F111,"coninc","timo",timo); #ifdef IKSD if ( inserver ) { debug(F100,"coninc inserver","",0); c = ttinc(timo); if ( c == -1 ) return(-2); else if ( c < 0 ) return(-1); else return(c & 0xFF); } #endif /* IKSD */ t = time(NULL) ; do { c = congks(timo) ; switch ( c ) { case KEY_SCAN | BS: /* The Backspace Key */ case DEL: case XEM: #ifndef NOKVERBS case F_KVERB | K_WYBS: case F_KVERB | K_WYSBS: case F_KVERB | K_TVIBS: case F_KVERB | K_TVISBS: case F_KVERB | K_DGBS: #endif /* NOKVERBS */ debug(F111,"coninc","BS conversion",c); c = BS ; break; case KEY_SCAN | HT: #ifndef NOKVERBS case F_KVERB | K_WYTAB: case F_KVERB | K_TVITAB: case F_KVERB | K_SNI_TAB: case F_KVERB | K_SNI_S_TAB: case F_KVERB | K_SNI_C_TAB: #endif /* NOKVERBS */ debug(F111,"coninc","TAB conversion",c); c = HT; break; case KEY_SCAN | ESC: #ifndef NOKVERBS case F_KVERB | K_WYESC: case F_KVERB | K_TVIESC: #endif /* NOKVERBS */ debug(F111,"coninc","ESC conversion",c); c = ESC ; break; case KEY_SCAN | CR: #ifndef NOKVERBS case F_KVERB | K_KPENTER: case F_KVERB | K_WYENTER: case F_KVERB | K_WYRETURN: case F_KVERB | K_TVIENTER: case F_KVERB | K_TVIRETURN: case F_KVERB | K_HPENTER: case F_KVERB | K_HPRETURN: #endif /* NOKVERBS */ debug(F111,"coninc","ENTER conversion",c); c = CR ; break; #ifndef NOKVERBS case F_KVERB | K_KPMINUS: debug(F111,"coninc","MINUS conversion",c); c = '-'; break; case F_KVERB | K_KPCOMA: debug(F111,"coninc","COMA conversion",c); c = ','; break; case F_KVERB | K_KPDOT: debug(F111,"coninc","PERIOD conversion",c); c = '.'; break; case F_KVERB | K_KP0: debug(F111,"coninc","0 conversion",c); c = '0' ; break; case F_KVERB | K_KP1: debug(F111,"coninc","1 conversion",c); c = '1' ; break; case F_KVERB | K_KP2: debug(F111,"coninc","2 conversion",c); c = '2' ; break; case F_KVERB | K_KP3: debug(F111,"coninc","3 conversion",c); c = '3' ; break; case F_KVERB | K_KP4: debug(F111,"coninc","4 conversion",c); c = '4' ; break; case F_KVERB | K_KP5: debug(F111,"coninc","5 conversion",c); c = '5' ; break; case F_KVERB | K_KP6: debug(F111,"coninc","6 conversion",c); c = '6' ; break; case F_KVERB | K_KP7: debug(F111,"coninc","7 conversion",c); c = '7' ; break; case F_KVERB | K_KP8: debug(F111,"coninc","8 conversion",c); c = '8' ; break; case F_KVERB | K_KP9: debug(F111,"coninc","9 conversion",c); c = '9' ; break; #endif /* NOKVERBS */ case KEY_SCAN | KEY_CTRL | 66: /* Ctrl-B */ case KEY_SCAN | 38: case KEY_SCAN | KEY_ENHANCED | 38: #ifndef NOKVERBS case F_KVERB | K_UPARR: case F_KVERB | K_ANSIF50: #endif /* NOKVERBS */ #ifndef NOTERM if ( markmodeflag[VCMD] != notmarking ) break; if (!IsConnectMode()) { /* Up arrow = Ctrl-B */ debug(F111,"coninc","Ctrl-B conversion",c); c = 2; } #endif /* NOTERM */ break; case KEY_SCAN | KEY_CTRL | 78: case KEY_SCAN | 40: case KEY_SCAN | KEY_ENHANCED | 40: #ifndef NOKVERBS case F_KVERB | K_DNARR: case F_KVERB | K_ANSIF58: #endif /* NOKVERBS */ #ifndef NOTERM if ( markmodeflag[VCMD] != notmarking ) break; if (!IsConnectMode()) { /* Down arrow = Ctrl-N */ debug(F111,"coninc","Ctrl-N conversion",c); c = 14; } #endif /* NOTERM */ break; default: ; } if ( c == CR ) c = NL; #ifndef NOKVERBS if (c >= 0) { debug(F111,"coninc","c >= 0",c); if ( IS_KVERB(c) ) { dokverb(VCMD,c); } /* Here we could handle F_CSI, F_ESC, ... */ } #endif /* NOKVERBS */ if ( timo && (time( NULL ) - t >= timo) ) { c = -1 ; /* timeout */ break; } } while ( c >= 0x100 ) ; if ( c == -1 ) return(-2); else if ( c == -2 ) return(-3); else if ( c < 0 ) return(-1); else return(c & 0xFF); } con_event congev( int vmode, int timo ) { APIRET rc ; ULONG timeout = 0; con_event evt ; int tt,tr,interval,i ; #ifdef IKSD if ( inserver ) { int ch; debug(F100,"congev inserver","",0); ch = ttinc(timo); if (ch >= 0) { evt.type = key; evt.key.scancode = ch; } else { evt.type = error; } return evt; } #endif /* IKSD */ #ifdef NT if ( timo == 0 ) { interval = ck_sleepint ; tt = 1 ; timeout = 0; } else if ( timo == -1 ) { interval = -1 ; tt = 1 ; timeout = 0; } else { if ( timo < -1 ) timeout = -timo ; else /* ( timo > 0 ) */ timeout = timo * 1000 ; tt = timeout / ck_sleepint ; tr = timeout % ck_sleepint ; if ( tt ) interval = ck_sleepint + tr / tt ; else { tt = 1 ; interval = tr ; } } for ( i = 0 ; (timeout && (i < tt)) || !timeout ; i++ ) { rc = WaitEventAvailSem( vmode, interval ) ; #ifdef NTSIG ck_ih() ; #endif /* NTSIG */ switch ( rc ) { case NO_ERROR: if ( getevent( vmode, &evt ) ) return(evt); break; default: if ( interval == -1 ) { evt.type = error; return(evt); } } } #else /* NT */ if ( timo < -1 ) timeout = -timo ; if ( timo == -1 || timo == 0 ) timeout = SEM_INDEFINITE_WAIT ; if ( timo > 0 ) timeout = timo * 1000 ; rc = WaitEventAvailSem( vmode, timeout ) ; if ( rc == NO_ERROR ) if ( getevent( vmode, &evt ) ) return evt ; #endif /* NT */ evt.type=error; return evt ; } int congks(int timo) { APIRET rc ; ULONG timeout = 0 ; con_event evt ; int tt, i, ch ; static char * macrostr = NULL, * s = NULL; debug(F111,"congks","timo",timo); if ( macrostr && s ) { debug(F100,"congks macrostr","",0); if ( *s == NUL ) { free(macrostr); macrostr = NULL ; s = NULL; ch = CR; } else { ch = *s++; } return(ch); } #ifdef IKSD if ( inserver ) { debug(F100,"congks inserver","",0); return(ttinc(timo)); } #endif /* IKSD */ if ( timo < -1 ) timeout = -timo ; else if ( timo == -1 || timo == 0 ) timeout = SEM_INDEFINITE_WAIT ; else /* ( timo > 0 ) */ timeout = timo * 1000; debug(F111,"congks","timeout",timeout); #ifdef NT tt = timeout / ck_sleepint ; for ( i = 0 ; i <= tt ; ) { rc = WaitEventAvailSem( VCMD, ck_sleepint ) ; debug(F111,"congks","WaitEventAvailSem()",rc); #ifdef NTSIG ck_ih() ; #endif /* NTSIG */ switch ( rc ) { case NO_ERROR: if ( getevent( (BYTE)VCMD, &evt ) ) { switch ( evt.type ) { case key: debug(F111,"congks","evt.key.scancode",evt.key.scancode); return evt.key.scancode; case macro: macrostr = evt.macro.string ; s = macrostr ; ch = *s++; if ( !*s ) { free(macrostr); macrostr = NULL ; s = NULL; } debug(F111,"congks","evt.macro.string ch",ch); return(ch); case literal: macrostr = evt.literal.string ; s = macrostr ; ch = *s++; if ( !*s ) { free(macrostr); macrostr = NULL ; s = NULL; } debug(F111,"congks","evt.literal.string ch",ch); return(ch); #ifndef NOKVERBS case kverb: debug(F111,"congks","evt.kverb.id",evt.kverb.id); return F_KVERB | evt.kverb.id; #endif /* NOKVERBS */ case csi: debug(F111,"congks","evt.csi.key",evt.csi.key); return F_CSI | evt.csi.key; case esc: debug(F111,"congks","evt.esc.key",evt.esc.key); return F_ESC | evt.esc.key ; case error: return(-2); default: debug(F110,"congks","default",0); break; } } else break ; default: break ; } if (timeout != (ULONG) SEM_INDEFINITE_WAIT ) i++ ; } #else /* NT */ while ( 1 ) { rc = WaitEventAvailSem( VCMD, timeout ) ; if ( rc == NO_ERROR ) if ( getevent( VCMD, &evt ) ) { switch ( evt.type ) { case key: return evt.key.scancode; case macro: macrostr = evt.macro.string ; s = macrostr ; ch = *s++; if ( !*s ) { free(macrostr); macrostr = NULL ; s = NULL; } return(ch); case literal: macrostr = evt.literal.string ; s = macrostr ; ch = *s++; if ( !*s ) { free(macrostr); macrostr = NULL ; s = NULL; } return(ch); #ifndef NOKVERBS case kverb: return F_KVERB | evt.kverb.id; #endif /* NOKVERBS */ case csi: return F_CSI | evt.csi.key; case esc: return F_ESC | evt.esc.key ; case error: return(-2); default: break; } } else break ; } #endif /* NT */ return -1; } int conraw() { #ifdef NT DWORD mode ; extern int mouseon ; #ifndef KUI #ifdef COMMENT /* Don't call this directly - It's fatal in Windows 95 */ SetConsoleCtrlHandler( NULL, TRUE ) ; #endif /* COMMENT */ GetConsoleMode( KbdHandle, &mode ) ; mode &= ~(ENABLE_LINE_INPUT | ENABLE_WINDOW_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT | 0x40 ); #ifdef OS2MOUSE if ( mouseon ) mode |= ENABLE_MOUSE_INPUT; #endif /* OS2MOUSE */ SetConsoleMode( KbdHandle, mode ) ; #endif /* KUI */ ckconraw = 1 ; #else /* NT */ KBDINFO k; memset( &k, 0, sizeof(k) ) ; if (!islocal) return(0); conmode = 1; k.cb = sizeof(k); KbdGetStatus(&k,KbdHandle); k.fsMask &= ~(KEYBOARD_ECHO_ON | KEYBOARD_ASCII_MODE); k.fsMask |= (KEYBOARD_ECHO_OFF | KEYBOARD_BINARY_MODE | KEYBOARD_SHIFT_REPORT); /* Generates excessive key reports */ return(KbdSetStatus(&k,KbdHandle)); /* But lets us see ScrollLock, Ctrl, Alt */ #endif /* NT */ return(0); } int concooked() { #ifdef NT #ifndef KUI DWORD mode ; extern int mouseon ; #ifdef COMMENT /* Don't call this directly - It's fatal in Windows 95 */ SetConsoleCtrlHandler( NULL, FALSE ) ; #endif /* COMMENT */ GetConsoleMode( KbdHandle, &mode ) ; mode &= ~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT | 0x40); mode |= ENABLE_PROCESSED_INPUT ; #ifdef OS2MOUSE if ( mouseon ) mode |= ENABLE_MOUSE_INPUT; #endif /* OS2MOUSE */ SetConsoleMode( KbdHandle, mode ) ; #endif /* KUI */ ckconraw = 0 ; return(0); #else /* NT */ KBDINFO k; memset( &k, 0, sizeof(k) ) ; if (!islocal) return(0); conmode = 0; k.cb = sizeof(k); KbdGetStatus(&k,KbdHandle); k.fsMask &= ~(KEYBOARD_ECHO_OFF | KEYBOARD_BINARY_MODE | KEYBOARD_SHIFT_REPORT); k.fsMask |= (KEYBOARD_ECHO_ON | KEYBOARD_ASCII_MODE); return(KbdSetStatus(&k,KbdHandle)); #endif /* NT */ } /* C O N B I N -- Put console in binary mode */ /* Returns 0 if ok, -1 if not */ conbin(char esc) { if (!islocal) return(0); /* only for real ttys */ #ifndef NOLOCAL if ( IsConnectMode() ) #endif /* NOLOCAL */ conraw(); return 0; } /* C O N C B -- Put console into single char mode with no echo. */ concb(char esc) { if (!islocal) return(0); /* only for real ttys */ #ifndef NOLOCAL if (!IsConnectMode()) #endif /* NOLOCAL */ concooked(); return 0 ; } /* C O N G M -- Get console terminal mode. */ congm() { return 0 ; } /* C O N R E S -- Restore console to congm mode. */ conres() { return 0 ; } /* C O N I N T -- Enable console terminal interrupts. */ void conint(f, s) SIGTYP (*f)(int), (*s)(int); { if ( signal(SIGINT, f) == SIG_ERR ) debug(F101,"conint() could not set SIGINT","",f); if ( !quitonbreak ) if ( signal(SIGBREAK, f) == SIG_ERR ) debug(F101,"conint() could not set SIGBREAK","",f); } /* C O N N O I -- No console interrupts. */ void connoi() { signal(SIGINT, SIG_IGN); if ( !quitonbreak ) signal(SIGBREAK, SIG_IGN); } /* privilege dummy */ int priv_chk() {return 0;} #ifndef __EMX__ /* alarm() implementation for all others, emx/gcc already has it built-in */ #define STACK static BOOL alrm, running, isalarm; static UINT delay; #ifdef WIN95_IN_AN_EMERGENCY /* we are not using this code and should never need to */ alarm_thread(VOID *args) { #ifdef NT setint(); #endif /* NT */ SetThreadPrty(XYP_REG,15); while (1) { sleep(1) ; RequestAlarmMutex( SEM_INDEFINITE_WAIT ) ; if ( alrm ) if ( --delay == 0 ) { debug( F100, "alarm() triggered", "", 0 ) ; alrm = FALSE; isalarm = TRUE; isinterrupted = 1 ; PostAlarmSigSem() ; } else { debug( F101, "alarm() delay","",delay ) ; } ReleaseAlarmMutex() ; } running = FALSE; ckThreadEnd(args); } unsigned alarm(unsigned sec) { unsigned old; APIRET rc = 0 ; ULONG TimeInterval = sec * 1000 ; RequestAlarmMutex( SEM_INDEFINITE_WAIT ) ; if ( delay ) { debug(F101,"alarm(0) StopAlarmTimer","",rc) ; } old = delay; delay = sec; if ( alrm = (delay > 0) ) { debug(F101,"alarm(t) StartAlarmTimer: t","",TimeInterval) ; } else debug(F100,"alarm() reset","",0); ReleaseAlarmMutex() ; if ( !running ) { running = TRUE; tidAlarm = (TID) ckThreadBegin( &alarm_thread,THRDSTKSIZ,0,FALSE,0); } return old; } #else /* not WIN95_IN_AN_EMERGENCY */ static VOID alarm_thread(VOID *args) { #ifdef NT setint(); #endif /* NT */ SetThreadPrty(XYP_REG,15); while (1) { WaitAlarmSem( SEM_INDEFINITE_WAIT ) ; RequestAlarmMutex( SEM_INDEFINITE_WAIT ) ; ResetAlarmSem() ; if ( alrm ) { debug( F100, "alarm() triggered", "", 0 ) ; alrm = FALSE; isalarm = TRUE; #ifdef NT #ifdef NTSIG isinterrupted = 1 ; PostAlarmSigSem() ; #else /* NTSIG */ raise(SIGALRM) ; #endif /* NTSIG */ #else /* NT */ KillProcess(pid) ; #endif /* NT */ } ReleaseAlarmMutex() ; } /* this will never execute */ running = FALSE; ckThreadEnd(args); } static void alarm_signal(int sig) { debug(F101,"alarm_signal handler","",sig) ; signal(SIGTERM, term_signal); if (isalarm) { isalarm = FALSE; raise(SIGALRM); } else { KillProcess(pid); } } unsigned alarm(unsigned sec) { unsigned old; APIRET rc = 0 ; ULONG TimeInterval = sec * 1000 ; RequestAlarmMutex( SEM_INDEFINITE_WAIT ) ; if ( delay ) { rc = StopAlarmTimer() ; debug(F111,"alarm(0) StopAlarmTimer","rc",rc) ; } old = delay; delay = sec; if ( alrm = (delay > 0) ) { #ifndef NTSIG signal(SIGTERM, alarm_signal); #endif /* NTSIG */ rc = StartAlarmTimer( TimeInterval ) ; debug(F111,"alarm() StartAlarmTimer","TimeInterval",TimeInterval) ; debug(F111,"alarm() StartAlarmTimer","rc",rc) ; } else debug(F100,"alarm() reset","",0); ReleaseAlarmMutex() ; if ( !running ) { running = TRUE; tidAlarm = (TID) ckThreadBegin( &alarm_thread,THRDSTKSIZ,0,FALSE,0); } return old; } #endif /* WIN95_IN_AN_EMERGENCY */ /* * A public domain implementation of BSD directory routines for * MS-DOS. Written by Michael Rendell ({uunet,utai}michael@garfield), * August 1897 * Ported to OS/2 by Kai Uwe Rommel * December 1989, February 1990 * Change for HPFS support, October 1990 */ int attributes = A_DIR | A_HIDDEN | A_RONLY | A_SYSTEM | A_ARCHIVE ; static char *getdirent(char *); static void free_dircontents(struct _dircontents *); static HDIR hdir; static U_INT count; #ifdef NT static WIN32_FIND_DATA find; #else /* NT */ static FILEFINDBUF find; #endif /* NT */ int IsFileSystemFAT(char *dir) { USHORT nResult; #ifdef NT char rootpath[4] ; char filesys[20]; DWORD namemax = 0; if ( isalpha(dir[0]) && (dir[1] == ':') ) { rootpath[0] = dir[0] ; rootpath[1] = dir[1] ; rootpath[2] = '\\' ; rootpath[3] = '\0' ; GetVolumeInformation( rootpath, NULL, 0, &namemax, NULL, NULL, filesys, 20 ) ; } else { GetVolumeInformation( NULL, NULL, 0, &namemax, NULL, NULL, filesys, 20 ) ; } debug(F111,"File system max name length",filesys,namemax) ; #ifdef COMMENT nResult = !strcmp(filesys, "FAT"); #else nResult = ( namemax == 11 ) ; #endif #else /* NT */ static USHORT nLastDrive = -1; ULONG lMap; BYTE bData[64], bName[3]; U_INT nDrive, cbData; FSQBUFFER *pData = (FSQBUFFER *) bData; /* We separate FAT and HPFS file systems here. */ if ( isalpha(dir[0]) && (dir[1] == ':') ) nDrive = toupper(dir[0]) - '@'; else DosQueryCurrentDisk(&nDrive, &lMap); if ( nDrive == nLastDrive ) return nResult; bName[0] = (char) (nDrive + '@'); bName[1] = ':'; bName[2] = 0; nLastDrive = nDrive; cbData = sizeof(bData); if ( !DosQueryFSAttach(bName, 0, FSAIL_QUERYNAME, (PVOID) pData, &cbData) ) nResult = !strcmp(pData -> szFSDName + pData -> cbName, "FAT"); else nResult = FALSE; #endif /* NT */ return nResult; } DIR * opendir(char *name) { #ifdef NT struct _stat statb; #else /* NT */ struct stat statb; #endif /* NT */ DIR *dirp; char c; char *s; struct _dircontents *dp; char nbuf[MAXPATHLEN + 1]; int len; ckstrncpy(nbuf, name, MAXPATHLEN+1); if ((len = strlen(nbuf)) == 0) return NULL; if ( ((c = nbuf[len - 1]) == '\\' || c == '/') && (len > 1) ) { nbuf[len - 1] = 0; --len; if ( nbuf[len - 1] == ':' ) { ckstrncpy(nbuf + len, "\\.",MAXPATHLEN+1-len); len += 2; } } else if ( nbuf[len - 1] == ':' ) { ckstrncpy(nbuf+len, ".",MAXPATHLEN+1-len); ++len; } #ifdef NT if (_stat(nbuf, &statb) < 0 || (statb.st_mode & _S_IFMT) != _S_IFDIR) #else /* NT */ if (stat(nbuf, &statb) < 0 || (statb.st_mode & _S_IFMT) != _S_IFDIR) #endif /* NT */ return NULL; if ( (dirp = malloc(sizeof(DIR))) == NULL ) return NULL; if ( nbuf[len - 1] == '.' && (len == 1 || nbuf[len - 2] != '.') ) ckstrncpy(nbuf + len - 1, "*",MAXPATHLEN+1-len); else if ( ((c = nbuf[len - 1]) == '\\' || c == '/') && (len == 1) ) ckstrncpy(nbuf + len, "*",MAXPATHLEN+1-len); else ckstrncpy(nbuf + len, "/*",MAXPATHLEN+1-len); dirp -> dd_loc = 0; dirp -> dd_contents = dirp -> dd_cp = NULL; if ((s = getdirent(nbuf)) == NULL) return dirp; do { if (((dp = malloc(sizeof(struct _dircontents))) == NULL) || ((dp -> _d_entry = malloc(strlen(s) + 1)) == NULL) ) { if (dp) free(dp); free_dircontents(dirp -> dd_contents); return NULL; } if (dirp -> dd_contents) { dirp -> dd_cp -> _d_next = dp; dirp -> dd_cp = dirp -> dd_cp -> _d_next; } else dirp -> dd_contents = dirp -> dd_cp = dp; strcpy(dp -> _d_entry, s); dp -> _d_next = NULL; #ifdef NT /* I am not going to worry about this data because it is never used anywhere within Kermit */ dp->_d_size = 0 ; dp->_d_mode = 0 ; dp->_d_time = 0 ; dp->_d_date = 0 ; #else /* NT */ dp -> _d_size = find.cbFile; dp -> _d_mode = find.attrFile; dp -> _d_time = *(unsigned *) &(find.ftimeLastWrite); dp -> _d_date = *(unsigned *) &(find.fdateLastWrite); #endif /* NT */ } while ((s = getdirent(NULL)) != NULL); dirp -> dd_cp = dirp -> dd_contents; return dirp; } void closedir(DIR * dirp) { free_dircontents(dirp -> dd_contents); free(dirp); } struct dirent * readdir(DIR * dirp) { static struct dirent dp; if (dirp -> dd_cp == NULL) return NULL; dp.d_namlen = dp.d_reclen = strlen(strcpy(dp.d_name, dirp -> dd_cp -> _d_entry)); dp.d_ino = 1; dp.d_size = dirp -> dd_cp -> _d_size; dp.d_mode = dirp -> dd_cp -> _d_mode; dp.d_time = dirp -> dd_cp -> _d_time; dp.d_date = dirp -> dd_cp -> _d_date; dirp -> dd_cp = dirp -> dd_cp -> _d_next; dirp -> dd_loc++; return &dp; } void seekdir(DIR * dirp, long off) { long i = off; struct _dircontents *dp; if (off >= 0) { for (dp = dirp -> dd_contents; --i >= 0 && dp; dp = dp -> _d_next); dirp -> dd_loc = off - (i + 1); dirp -> dd_cp = dp; } } long telldir(DIR * dirp) { return dirp -> dd_loc; } static void free_dircontents(struct _dircontents * dp) { struct _dircontents *odp; while (dp) { if (dp -> _d_entry) free(dp -> _d_entry); dp = (odp = dp) -> _d_next; free(odp); } } char * getdirent(char *dir) { int done; static int lower = TRUE; if (dir != NULL) { /* get first entry */ lower = IsFileSystemFAT(dir); count = 1; #ifdef NT hdir = FindFirstFile( dir, &find ) ; done = (hdir == INVALID_HANDLE_VALUE) ; #else /* NT */ hdir = HDIR_CREATE; done = DosFindFirst(dir, &hdir, attributes, &find, sizeof(find), &count); #endif /* NT */ } else /* get next entry */ #ifdef NT done = !FindNextFile( hdir, &find ) ; count++ ; #else /* NT */ done = DosFindNext(hdir, &find, sizeof(find), &count); #endif /* NT */ if (done == 0) { if ( lower ) #ifdef NT _strlwr(find.cFileName) ; return find.cFileName; #else /* NT */ strlwr(find.achName); return find.achName; #endif /* NT */ } else { #ifdef NT FindClose(hdir) ; #else /* NT */ DosFindClose(hdir); #endif /* NT */ return NULL; } } #endif /* __EMX__ */ #ifdef COMMENT #ifdef NT /* This code was used to allow external commands to be executed on Win95 */ /* by redirecting output to a file and then reading from the file */ #define POPENMAX 4 static struct { char filename[MAX_PATH+1]; int read ; char *cmd ; FILE *file; } win95p[POPENMAX] = { "",0,NULL,NULL, "",0,NULL,NULL, "",0,NULL,NULL, "",0,NULL,NULL }; FILE * win95popen(char *cmd, char *mode) { /* Another Windows 95 bug ... */ char popenpathname[MAX_PATH+1]; char fullcmd[MAX_PATH*2]; HFILE end1, end2, std, old1, old2, temp; char fail[256], cmd_line[256], *cmd_exe, *args, *p; int rc,i,n; extern char * tempdir ; for ( i=0; i %s", cmd, win95p[i].filename); /* Command */ system(fullcmd); return (win95p[i].file = fopen(win95p[i].filename,"r")); case 'w': win95p[i].read = 0 ; win95p[i].cmd = strdup(cmd); return (win95p[i].file = fopen(win95p[i].filename,"w")); default: return ((FILE *) NULL); } } int win95pclose(FILE *pipe) { int i; for ( i=0; i>= 8 ; else pexitstat = -4; return 1; } else { pexitstat = -4; return 0; } } else #endif /* COMMENT */ { HANDLE hSaveStdIn, hSaveStdOut, hSaveStdErr; HANDLE hChildStdinRd, hChildStdinWr, hChildStdinWrDup, hChildStdoutRd, hChildStdoutWr, hChildStdoutRdDup, hInputFile, hSaveStdin, hSaveStdout; SECURITY_ATTRIBUTES saAttr; BOOL fSuccess; PROCESS_INFORMATION procinfo ; STARTUPINFO startinfo ; char cmd_line[256], *cmd_exe, *args, *p; pexitstat = -4; if (ttyfd == -1 #ifdef CK_TAPI || (tttapi && ttyfd == -2) #endif /* CK_TAPI */ ) { printf("?Sorry, device is not open\n"); return 0; } hSaveStdOut = GetStdHandle( STD_OUTPUT_HANDLE ) ; hSaveStdIn = GetStdHandle( STD_INPUT_HANDLE ) ; hSaveStdErr = GetStdHandle( STD_ERROR_HANDLE ) ; /* Set the bInheritHandle flag so pipe handles are inherited. */ saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); saAttr.bInheritHandle = TRUE; saAttr.lpSecurityDescriptor = NULL; /* * The steps for redirecting child's STDOUT: * 1. Save current STDOUT, to be restored later. * 2. Create anonymous pipe to be STDOUT for child. * 3. Set STDOUT of parent to be write handle of pipe, so * it is inherited by child. */ /* Create a pipe for the child's STDOUT. */ if (! CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0)) debug(F100,"Stdout pipe creation failed\n","",0); /* Set a write handle to the pipe to be STDOUT. */ if (! SetStdHandle(STD_OUTPUT_HANDLE, hChildStdoutWr) || ! SetStdHandle(STD_ERROR_HANDLE, hChildStdoutWr) ) debug(F100,"Redirecting STDOUT/STDERR failed","",0); /* * The steps for redirecting child's STDIN: * 1. Save current STDIN, to be restored later. * 2. Create anonymous pipe to be STDIN for child. * 3. Set STDIN of parent to be read handle of pipe, so * it is inherited by child. * 4. Create a noninheritable duplicate of write handle, * and close the inheritable write handle. */ /* Create a pipe for the child's STDIN. */ if (! CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0)) debug(F100,"Stdin pipe creation failed\n","",0); /* Set a read handle to the pipe to be STDIN. */ if (! SetStdHandle(STD_INPUT_HANDLE, hChildStdinRd)) debug(F100,"Redirecting Stdin failed","",0); /* Duplicate the write handle to the pipe so it is not inherited. */ fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdinWr, GetCurrentProcess(), &hChildStdinWrDup, 0, FALSE, /* not inherited */ DUPLICATE_SAME_ACCESS); if (! fSuccess) { debug(F100,"DuplicateHandle failed","",0); SetStdHandle( STD_OUTPUT_HANDLE, hSaveStdOut ); SetStdHandle( STD_INPUT_HANDLE, hSaveStdIn ); SetStdHandle( STD_ERROR_HANDLE, hSaveStdErr ); CloseHandle(hChildStdoutRd); hChildStdoutRd = NULL; CloseHandle(hChildStdoutWr); hChildStdoutWr = NULL; CloseHandle(hChildStdinRd); hChildStdinRd = NULL; CloseHandle(hChildStdinWr); hChildStdinWr = NULL; return(0); } fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdoutRd, GetCurrentProcess(), &hChildStdoutRdDup, 0, FALSE, /* not inherited */ DUPLICATE_SAME_ACCESS); if (! fSuccess) { debug(F100,"DuplicateHandle failed","",0); SetStdHandle( STD_OUTPUT_HANDLE, hSaveStdOut ); SetStdHandle( STD_INPUT_HANDLE, hSaveStdIn ); SetStdHandle( STD_ERROR_HANDLE, hSaveStdErr ); CloseHandle(hChildStdoutRd); hChildStdoutRd = NULL; CloseHandle(hChildStdoutWr); hChildStdoutWr = NULL; CloseHandle(hChildStdinRd); hChildStdinRd = NULL; CloseHandle(hChildStdinWr); hChildStdinWr = NULL; return(0); } CloseHandle(hChildStdinWr); hChildStdinWr = NULL; cmd_line[0] = '\0' ; /* Now create the child process. */ cmd_exe = getenv("SHELL"); if ( !cmd_exe ) cmd_exe = getenv("COMSPEC"); if ( !cmd_exe ) cmd_exe = "cmd.exe"; n = ckstrncpy(cmd_line, cmd_exe, 256); args = cmd_line + n; /* don't skip zero */ /* Look for MKS Shell, if found use -c instead of /c */ _strlwr(cmd_exe); p = strstr(cmd_exe,"sh.exe"); if ( !p ) p = strstr(cmd_exe,"bash.exe"); if ( !p ) p = strstr(cmd_exe,"ash.exe"); if ( p && (p == cmd_exe || *(p-1) == '\\' || *(p-1) == '/')) { sprintf(args, " -c \"%s\"",cmd); } else { int m; m = ckstrncpy(args, " /c ", 256 - n); ckstrncpy(&args[m], cmd, 256 - n - m); } memset( &startinfo, 0, sizeof(STARTUPINFO) ) ; startinfo.cb = sizeof(STARTUPINFO) ; fSuccess = CreateProcess( NULL, /* application name */ cmd_line, /* command line */ NULL, /* process security attributes */ NULL, /* primary thread security attrs */ TRUE, /* inherit handles */ NORMAL_PRIORITY_CLASS, /* creation flags */ NULL, /* use parent's environment */ NULL, /* use parent's current directory */ &startinfo, /* startup info */ &procinfo ) ; /* proc info returned */ if ( !SetStdHandle( STD_OUTPUT_HANDLE, hSaveStdOut ) || !SetStdHandle( STD_INPUT_HANDLE, hSaveStdIn ) || !SetStdHandle( STD_ERROR_HANDLE, hSaveStdErr ) ) { debug( F101,"ttruncmd Unable to restore standard handles","",GetLastError() ) ; CloseHandle(hChildStdoutRd); hChildStdoutRd = NULL; CloseHandle(hChildStdoutWr); hChildStdoutWr = NULL; CloseHandle(hChildStdinRd); hChildStdinRd = NULL; CloseHandle(hChildStdinWrDup); hChildStdinWrDup = NULL; } if ( !fSuccess ) { CloseHandle(hChildStdoutRd); hChildStdoutRd = NULL; CloseHandle(hChildStdoutWr); hChildStdoutWr = NULL; CloseHandle(hChildStdinRd); hChildStdinRd = NULL; CloseHandle(hChildStdinWrDup); hChildStdinWrDup = NULL; return(0); } CloseHandle(procinfo.hProcess); CloseHandle(procinfo.hThread); exitcode = STILL_ACTIVE; _beginthread( ttruncmd2, 65536, hChildStdoutRd ); do { DWORD io ; int inc ; unsigned char outc ; inc = ttinc( 1 ) ; if ( inc < -1 ) break ; else if ( inc >= 0 ) { if ( !WriteFile( hChildStdinWrDup, &inc, 1, &io, NULL ) ) { debug(F101,"ttruncmd unable to write to child","",GetLastError()); break; } continue; } // Give the process time to execute and finish if (WaitForSingleObject(procinfo.hProcess, 0L) == WAIT_OBJECT_0) { GetExitCodeProcess(procinfo.hProcess, &exitcode); } } while ( exitcode == STILL_ACTIVE ); debug(F111, "ttruncmd","exitcode",exitcode); if ( exitcode == STILL_ACTIVE ) exitcode = 128; /* Close the pipe handle so the child stops reading. */ CloseHandle(hChildStdoutRd); hChildStdoutRd = NULL; CloseHandle(hChildStdoutWr); hChildStdoutWr = NULL; CloseHandle(hChildStdinRd); hChildStdinRd = NULL; CloseHandle(hChildStdinWrDup); hChildStdinWrDup = NULL; CloseHandle( procinfo.hProcess ) ; CloseHandle( procinfo.hThread ) ; pexitstat = exitcode; return (exitcode>=0 ? 1 : 0); } return 0; /* Should never be reached */ } #else /* not NT */ #define STILL_ACTIVE -1L static ULONG exitcode = 0; void ttruncmd2( HFILE pipe ) { int success = 1; CHAR outc; ULONG io; while ( success && exitcode == STILL_ACTIVE ) { if ( success = !DosRead( pipe, &outc, 1, &io ) ) { ttoc(outc) ; } } exitcode = 0; } int ttruncmd(cmd) char *cmd; { /* Return: 0 = failure, 1 = success */ extern int pexitstat; HFILE hSaveStdOut=-1, hSaveStdIn=-1, hSaveStdErr=-1; HFILE hChildStdoutRd, hChildStdoutWr, hChildStdinRd, hChildStdinWr; HFILE temp; FILE *file; char fail[256], cmd_line[256], *cmd_exe, *args, *p; RESULTCODES res; PID pid, pid2; int n, rc; debug(F110,"ttruncmd",cmd,0); /* Save existing handles */ DosDupHandle(0,&hSaveStdIn); DosSetFHState(hSaveStdIn, OPEN_FLAGS_NOINHERIT); DosDupHandle(1,&hSaveStdOut); DosSetFHState(hSaveStdOut, OPEN_FLAGS_NOINHERIT); DosDupHandle(2,&hSaveStdErr); DosSetFHState(hSaveStdErr, OPEN_FLAGS_NOINHERIT); /* Create a pipe for the child's STDOUT */ if (DosCreatePipe(&hChildStdoutRd, &hChildStdoutWr, 4096)) debug(F100,"Stdout pipe creation failed\n","",0); /* Set a write handle to the pipe to be STDOUT */ temp = 1; /* stdout */ DosDupHandle(hChildStdoutWr, &temp); temp = 2; /* stderr */ DosDupHandle(hChildStdoutWr, &temp); /* Create a pipe for the child's STDOUT */ if (DosCreatePipe(&hChildStdinRd, &hChildStdinWr, 4096)) debug(F100,"Stdout pipe creation failed\n","",0); /* Set a write handle to the pipe to be STDOUT */ temp = 0; /* stdin */ DosDupHandle(hChildStdinRd, &temp); DosSetFHState(hChildStdoutRd, OPEN_FLAGS_NOINHERIT); DosSetFHState(hChildStdinWr, OPEN_FLAGS_NOINHERIT); cmd_exe = getenv("SHELL"); if ( !cmd_exe ) cmd_exe = getenv("COMSPEC"); if ( !cmd_exe ) cmd_exe = "cmd.exe"; n = ckstrncpy(cmd_line, cmd_exe, 256); args = cmd_line + n + 1; /* skip zero */ /* Look for MKS Shell, if found use -c instead of /c */ strlwr(cmd_exe); p = strstr(cmd_exe,"sh.exe"); if ( !p ) p = strstr(cmd_exe,"bash.exe"); if ( !p ) p = strstr(cmd_exe,"ash.exe"); if ( p && (p == cmd_exe || *(p-1) == '\\' || *(p-1) == '/')) { sprintf(args, "-c%c%s%c",0,cmd,0); } else { sprintf(args, "/c%c%s%c",0,cmd,0); } rc = DosExecPgm(fail, sizeof(fail), EXEC_ASYNCRESULT, args, 0, &res, cmd_exe); /* Restore Standard Handles for this process */ temp = 0; DosDupHandle(hSaveStdIn,&temp); temp = 1; DosDupHandle(hSaveStdOut,&temp); temp = 2; DosDupHandle(hSaveStdErr,&temp); if (rc) { debug(F111,"ttruncmd failed",fail,rc); DosClose(hChildStdinRd); DosClose(hChildStdinWr); DosClose(hChildStdoutRd); DosClose(hChildStdoutWr); return 1; } pid = res.codeTerminate; debug(F111,"ttruncmd","PID",pid); exitcode = STILL_ACTIVE; _beginthread( ttruncmd2, 0, 65536, hChildStdoutRd ); do { ULONG io ; int inc ; CHAR outc ; inc = ttinc( 1 ) ; if ( inc < -1 ) break ; else if ( inc >= 0 ) { if ( rc = DosWrite( hChildStdinWr, &inc, 1, &io ) ) { debug(F101,"ttruncmd unable to write to child","",rc); break; } continue; } res.codeTerminate = 99; rc = DosWaitChild(DCWA_PROCESSTREE, DCWW_NOWAIT, &res, &pid2, pid); if ( (rc==0) && (res.codeTerminate != 99) ) { exitcode = res.codeResult; } } while ( exitcode == STILL_ACTIVE ); if ( exitcode == STILL_ACTIVE && pid ) { exitcode = 128; if (!DosWaitChild(DCWA_PROCESSTREE, DCWW_WAIT, &res, &pid2, pid)) exitcode = res.codeResult; debug(F111,"ttruncmd","res.codeResult",res.codeResult); } DosClose(hChildStdinRd); DosClose(hChildStdinWr); DosClose(hChildStdoutRd); DosClose(hChildStdoutWr); pexitstat = exitcode; return (exitcode>=0 ? 1 : 0); } #endif /* NT */ #endif /* CK_REDIR */ /* Keyboard Hardware ID PC AT* Standard Keyboard 0001H 101 Key Enhanced Keyboard and AB41H 102 Key Enhanced Keyboard 88 Key Enhanced Keyboard and AB54H 89 Key Enhanced Keyboard 122 Key Mainframe Interactive AB86H (MFI) Keyboard */ static char os2kbt[20]; char * conkbg(void) { int x=0; char * p=os2kbt; #ifdef NT os2kbt[0] = '\0' ; switch (GetKeyboardType(0)) /* Get Keyboard subtype */ { case 1: x=83; break; case 2: case 4: x=102; break; case 3: x = 84 ; break; case 5: x=1050; break; case 6: x=9140; break; default: x=0 ; } if (x) /* If it's known model */ sprintf(p,"%d",x); /* use its "name" */ else /* otherwise */ sprintf(p,"unknown"); /* unknown */ #else /* NT */ KBDHWID kbID ; int rc=0; *p = '\0'; memset( &kbID, 0, sizeof(kbID) ) ; kbID.cb = sizeof(kbID); KbdGetHWID(&kbID, KbdHandle); debug(F101,"conkbg","",kbID.idKbd); switch (kbID.idKbd) { case 0x0001: /* PC/AT keyboard */ case 0xab54: /* PC or PC/XT 88 or 89 key */ x = 88; break; case 0xab41: /* 101 or 102 enhanced keyboard */ case 0xab83: x = 101; break; case 0xab86: /* 122-key "mainframe interactive" */ x = 122; break; default: x = 0; break; /* Something else... */ } if (x) /* If it's known model */ sprintf(p,"%d",x); /* use its "name" */ else /* otherwise */ sprintf(p,"%04X",(int) kbID.idKbd); /* use the hex code */ #endif /* NT */ return(p); /* Return string pointer */ }; #ifdef CK_LABELED static CHAR os2version[50] ; char * get_os2_vers() { APIRET rc ; #ifdef NT OSVERSIONINFO verinfo ; verinfo.dwOSVersionInfoSize=sizeof(OSVERSIONINFO); rc = !GetVersionEx( &verinfo ) ; if ( rc ) { os2version[0] = '\0'; } else { sprintf(os2version,"%s %02d.%02d.%02d", verinfo.dwPlatformId == VER_PLATFORM_WIN32_NT ? "WinNT" : verinfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS ? (verinfo.dwMinorVersion == 0 ? "Win95" : "Win98") : verinfo.dwPlatformId == VER_PLATFORM_WIN32_WIN32S ? "Win32s" : "unknown", verinfo.dwMajorVersion, verinfo.dwMinorVersion, verinfo.dwBuildNumber ); } #else /* NT */ ULONG StartIndex = QSV_VERSION_MAJOR ; /* Major Version Number */ ULONG EndIndex = QSV_VERSION_REVISION ; /* Revision Letter */ ULONG DataBuf[3] ; ULONG DataBufLen = 3 * sizeof(ULONG) ; rc = DosQuerySysInfo( StartIndex, EndIndex, DataBuf, DataBufLen ); if (rc) os2version[0] = '\0' ; else sprintf(os2version,"%02d.%02d%c",DataBuf[0],DataBuf[1],DataBuf[2]) ; #endif /* NT */ return os2version ; } #endif /* CK_LABELED */ #ifdef CK_REXX extern char * mrval[] ; extern int maclvl ; /* This is the CkCommand/CKermit function handler. It is an undocumented */ /* Kermit feature. Do not remove this code. */ ULONG APIENTRY os2rexxckcmd( PUCHAR Name, ULONG Argc, PRXSTRING Argv, PSZ Queuename, PRXSTRING Retstr) { int rc = 0 ; int i ; for ( i = 0 ; i < Argc ; i++ ) { rc = domac("_rexx_commands",RXSTRPTR(Argv[i]),CF_REXX); debug(F111,"os2rexxckcmd",RXSTRPTR(Argv[i]),rc); delmac("_rexx_commands",0); if (rc < 0) break ; } if ( mrval[maclvl+1] ) { MAKERXSTRING(*Retstr, strdup(mrval[maclvl+1]), strlen(mrval[maclvl+1]) ) ; } else MAKERXSTRING( *Retstr, strdup(""), 0 ) ; return (rc < 0 ? rc : 0 ) ; } ULONG APIENTRY os2rexxsubcom( PRXSTRING Command, PUSHORT pFlags, PRXSTRING Retstr) { int rc = 0 ; rc = domac("_rexx_commands",RXSTRPTR(Command[0]),CF_REXX); debug(F111,"os2rexxsubcom",RXSTRPTR(Command[0]),rc); delmac("_rexx_commands",0); *pFlags = rc < 0 ? RXSUBCOM_ERROR : RXSUBCOM_OK; if ( mrval[maclvl+1] ) { MAKERXSTRING(*Retstr, strdup(mrval[maclvl+1]), strlen(mrval[maclvl+1])) ; } else MAKERXSTRING( *Retstr, strdup(""), 0 ) ; return 0; } int os2rexx( char * rexxcmd, char * rexxbuf, int rexxbuflen ) { long return_code ; /* rexx interpreter return code */ short rc ; /* converted return code */ char return_buffer[256] ; /*returned buffer*/ RXSTRING Instore[2] ; /* Instorage rexx procedure */ RXSTRING retstr ; /* program return value */ int retval ; /* os2rexx return value */ MAKERXSTRING( Instore[0], rexxcmd, strlen(rexxcmd) ) ; MAKERXSTRING( Instore[1], 0, 0 ) ; MAKERXSTRING( retstr, return_buffer, sizeof(return_buffer) ) ; debug(F110,"os2rexx: procedure",rexxcmd,0); return_code = RexxStart( 0, /* no program arguments */ 0, /* null argument list */ "Kermit for OS/2 REXX Command", /* default program name */ Instore, /* rexx procedure to interpret */ "CKermit", /* default address name */ RXFUNCTION, /* calling as a function */ 0, /* no exits used */ &rc, /* converted return code */ &retstr); /* returned result */ debug(F111,"os2rexx: returns",RXSTRPTR(retstr),return_code); if ( !return_code && RXSTRLEN( retstr ) < rexxbuflen ) { ckstrncpy( rexxbuf, RXSTRPTR(retstr), RXSTRLEN( retstr ) ); retval = 0 ; /* Success */ } else { rexxbuf[0] = '\0' ; retval = 1 ; /* Failure */ } if (RXSTRPTR(retstr) != return_buffer) DosFreeMem(RXSTRPTR(retstr)); return retval ; } int os2rexxinit() { /* this next line installs the CkCommand statement into the Rexx */ /* interpretter environment. We have replaced it with a subcommand */ /* handler instead. Both mechanisms can co-exist, so we leave in */ /* the CkCommand/CKermit as an undocumented function. */ RexxRegisterFunctionExe("CKermit",(PFN)os2rexxckcmd) ; RexxRegisterFunctionExe("CKCommand",(PFN)os2rexxckcmd) ; RexxRegisterSubcomExe("CKermit",(PFN)os2rexxsubcom, NULL); return 0 ; } #endif /* CK_REXX */ int os2settitle(char *newtitle, int newpriv ) { #ifndef NOLOCAL extern int StartedFromDialer ; extern LONG KermitDialerID ; #ifndef NT HSWITCH hSwitch; SWCNTRL swctl; #endif /* NT */ static char title[80]="not yet set"; static int private = 1; char titlebuf[128] ; extern enum markmodes markmodeflag[]; extern bool scrollflag[] ; extern int vmode; extern int inserver; char * videomode = ""; switch ( markmodeflag[vmode] ) { case notmarking: if ( scrollflag[vmode] ) videomode = " [Scrollback]"; break; case inmarkmode: videomode = " [Mark Mode]"; break; case marking: videomode = " [Marking]"; break; } if ( newtitle ) { ckstrncpy(title,newtitle,80); private = newpriv; } if ( usertitle[0] ) { if ( StartedFromDialer ) { sprintf( titlebuf, "%d::%s%s%s",KermitDialerID,usertitle, private ? (inserver ? " - IKS" : " - K-95") : "", videomode ); } else { sprintf( titlebuf, "%s%s%s",usertitle, private ? (inserver ? " - IKS" : " - K-95") : "", videomode ); } } else if ( StartedFromDialer ) { sprintf( titlebuf, "%d::%s%s%s%s",KermitDialerID,title,(*title&&private)?" - ":"", private ? (inserver ? "IKS" : "K-95") : "", videomode ); } else { sprintf( titlebuf, "%s%s%s%s",title,(*title&&private)?" - ":"", private ? (inserver ? "IKS" : "K-95") : "" , videomode ); } #ifdef NT #ifdef KUI KuiSetProperty(KUI_TITLE,(long)titlebuf,(long)0) ; return 1; #else /* KUI */ return !SetConsoleTitle(titlebuf); #endif /* KUI */ #else /* NT */ /* This changes the text in the task list. */ /* That the window handle (first parameter) in the WinQuerySwitchHandle */ /* call can be NULL is fully documented in the API description. */ hSwitch = WinQuerySwitchHandle((HWND) NULL, pid); WinQuerySwitchEntry(hSwitch, &swctl); strcpy(swctl.szSwtitle, titlebuf); WinChangeSwitchEntry(hSwitch, &swctl); #ifdef CK_SETTITLE { /* and this undocumented call changes the session title */ extern APIRET16 APIENTRY16 Win16SetTitle(HWND hwnd, PSZ szTitle); extern APIRET16 APIENTRY16 Win16SetTitleAndIcon(HWND hwnd, PSZ szTitle, PSZ szIconFile ); Win16SetTitle( 0, titlebuf ) ; /* Win16SetTitleAndIcon( 0, title, "ckermit.ico" ) ; */ } #else /* CK_SETTITLE */ zsyscmd( "exit" ) ; #endif /* CK_SETTITLE */ return 0; #endif /* NT */ #else /* NOLOCAL */ return(0); #endif /* NOLOCAL */ } int os2gettitle(char *buffer, int size) { #ifndef NOLOCAL extern enum markmodes markmodeflag[]; extern bool scrollflag[] ; extern int vmode; int len; #ifdef OS2ONLY HSWITCH hSwitch; SWCNTRL swctl; #endif /* OS2ONLY */ if ( buffer == NULL ) return(-1); buffer[0] = '\0'; #ifdef NT if ( GetConsoleTitle(buffer, size) ) { len = strlen(buffer); switch ( markmodeflag[vmode] ) { case notmarking: if ( scrollflag[vmode] && len >= 13) buffer[len-13] = '\0'; break; case inmarkmode: if ( len >= 12 ) buffer[len-12] = '\0'; break; case marking: if ( len >= 10 ) buffer[len-10] = '\0'; break; } return(0); } else return GetLastError(); #else /* NT */ /* Query the text in the task list */ hSwitch = WinQuerySwitchHandle( (HWND) NULL, pid); WinQuerySwitchEntry(hSwitch, &swctl); ckstrncpy(buffer, swctl.szSwtitle, size); #ifdef OS2PM /* Only documented for PM applications */ WinQuerySessionTitle(hab, 0, buffer, size); #endif /* OS2PM */ len = strlen(buffer); switch ( markmodeflag[vmode] ) { case notmarking: if ( scrollflag[vmode] && len >= 13) buffer[len-13] = '\0'; break; case inmarkmode: if ( len >= 12 ) buffer[len-12] = '\0'; break; case marking: if ( len >= 10 ) buffer[len-10] = '\0'; break; } return 0; #endif /* NT */ #else /* NOLOCAL */ return(-1); #endif /* NOLOCAL */ } #ifndef NT HFILE ReadPipe = (HFILE) 0; APIRET ConnectToPM( void ) { APIRET rc = 0 ; UCHAR PipeName[256] = {""}; ULONG ulOpenMode = NP_ACCESS_INBOUND | NP_NOINHERIT, ulPipeMode = NP_WMESG | NP_RMESG | NP_NOWAIT | 0x01, ulOutBufSize = 1024, ulInpBufSize = 1024, ulTimeout = 2000L, ulBytesDone = 0 ; if ( StartedFromDialer ) { sprintf( PipeName, "\\PIPE\\K2DIAL\\%d",KermitDialerID ); rc = DosCreateNPipe(PipeName, &ReadPipe, ulOpenMode, ulPipeMode, ulOutBufSize, ulInpBufSize, ulTimeout); debug(F111,"DosCreateNPipe",PipeName,rc); if ( !rc ) { rc = DosConnectNPipe( ReadPipe ); debug(F111,"DosConnectNPipe",PipeName,rc); DialerSend( OPT_KERMIT_HWND, (ULONG) 0 ) ; } } return rc; } APIRET ReadFromPM( char * Buf, ULONG len, ULONG * BytesRead ) { APIRET rc ; AVAILDATA availdata = {0,0}; ULONG State = 0; static query = 0 ; if ( !StartedFromDialer || !ReadPipe || !Buf || !len || !BytesRead ) return -1 ; query = (query + 1)%20 ; /* Only check once per second or there abouts */ if ( query ) return -1; rc = DosPeekNPipe( ReadPipe, Buf, 1, BytesRead, &availdata, &State ) ; switch ( rc ) { case ERROR_BAD_PIPE: StartedFromDialer = 0 ; DisconnectFromPM() ; return -1; case NO_ERROR: if ( State == NP_STATE_CONNECTED && availdata.cbmessage ) break; default: return -1; } *Buf = '\0' ; *BytesRead = 0 ; rc = DosRead ( ReadPipe, Buf, len, BytesRead ) ; debug(F111,"ReadFromPM",Buf,rc); return rc; } APIRET DisconnectFromPM( void ) { APIRET rc = 0 ; if ( StartedFromDialer ) { rc = DosDisConnectNPipe( ReadPipe ) ; rc = DosClose( ReadPipe ); ReadPipe = 0L ; } return rc; } #endif /* OS2PM */ void demoscrn(int vmode) { #ifndef NOLOCAL #ifdef SESLIMIT extern int seslimit; if ( !(downloaded && expired) ) return; popupdemo(vmode, seslimit - (time(NULL) - start_time)); #endif /* NOLOCAL */ #endif /* SESLIMIT */ } int chkexp( void ) { #ifndef NOLOCAL extern unsigned char colorcmd ; extern int expmon, expday, expyear ; time_t ltime, etime ; struct tm expires; int i; int dsn ; /* decoded serial number */ #ifdef SESLIMIT extern int seslimit; /* Session Time Limit */ #endif /* SESLIMIT */ memset( &expires, 0, sizeof(struct tm) ) ; expires.tm_mday = expday ; expires.tm_mon = expmon ; expires.tm_year = expyear ; etime = mktime( &expires ) + 24 * 60 * 60; ltime = time(NULL); colorcmd ^= 0x8 ; dsn = isregistered(NULL) ; #ifdef BETATEST bleep( BP_WARN ) ; if ( !quiet ) { printf("\n NOTICE:\n"); printf( " This software is pre-release and is to be used for testing\n"); printf( " purposes only. Pre-release versions of Kermit-95 are updated\n"); printf( " on a very frequent basis (several times a week.) If you find\n"); printf( " a bug and more than a week has transpired since the date listed\n"); printf( " above, please look for an updated version before reporting it.\n\n"); printf( " UNDER NO CIRCUMSTANCES IS THIS PRE-RELEASE SOFTWARE TO BE\n"); printf( " UPLOADED FOR DISTRIBUTION TO ANY SITE OTHER THAN:\n"); printf( " ftp://ftp.kermit-project.org/\n\n"); } #endif /* BETATEST */ downloaded = (dsn == 98); if ( !dsn || dsn < 100 ) { unsigned long now_t = time(NULL); #ifdef COMMENT if ( downloaded ) { etime = regtime(NULL) + 60*60*24*21; memcpy(&expires,localtime(&etime),sizeof(struct tm)); expday = expires.tm_mday; expmon = expires.tm_mon; expyear = expires.tm_year; expired = (now_t < regtime(NULL) || now_t > etime); } #endif /* COMMENT */ if (!quiet) printf( " This copy will expire on %d/%d/%d.\n\n",expmon+1,expday,1900+expyear); if ( !downloaded && ltime > etime ) { #ifdef BETADEBUG if ( !quiet ) { printf( " This Beta Test release copy has expired.\n"); printf( " Please retrieve a newer release from ftp://kermit.columbia.edu.\n\n"); } #else /* BETADEBUG */ if ( dsn ) { if ( !quiet ) { printf( " This DEMO copy of Kermit has expired.\n"); printf( " Please contact Kermit Orders at kermit-orders@columbia.edu or read the\n"); printf( " Kermit 95 Web Page at http://www.columbia.edu/kermit/k95.html\n"); printf( " to continue use of program.\n"); } } else { if ( !quiet ) printf( " This copy of Kermit 95 must be registered to continue use.\n\n"); } #endif /* BETADEBUG */ for ( i=0;i<3;i++ ) { bleep(BP_FAIL); sleep(2); } doexit(BAD_EXIT,-1); } else if ( downloaded ) { if ( !quiet ) { printf( " This is a DEMO of version of Kermit 95 designed to allow you to\n"); printf( " experience the full feature set of the program. This DEMO has a per\n"); printf( " session time limit of 15 minutes. This provides enough time to test\n"); printf( " the capabilities of the program and ensure compatibility with your\n"); printf( " existing systems. To purchase a full release of Kermit 95 please\n"); printf( " contact Kermit Orders at kermit-orders@columbia.edu or read the\n"); printf( " Kermit 95 Web Page at http://www.columbia.edu/kermit/k95.html\n"); printf("\n\n"); } #ifdef SESLIMIT seslimit = 60 * 15; #endif /* SESLIMIT */ } } colorcmd ^= 0x8 ; #endif /* NOLOCAL */ return(1); } int shoreg( void ) { #ifndef NOLOCAL int dsn ; /* decoded serial number */ extern unsigned char colorcmd ; colorcmd ^= 0x8 ; dsn = isregistered(NULL) ; /* add K95-00001123108-1.1 to the list below. */ if ( dsn == 91340 || dsn == 23567 || dsn == 12496 ) { if ( !quiet ) printf(" THIS COPY OF KERMIT SOFTWARE HAS BEEN PIRATED.\n"); for ( ;; ) { bleep( BP_WARN ) ; sleep(1); } } else if ( dsn == 99 || dsn == 98 /* Demo */ || dsn >= 100 && dsn < 10000 /* Academic Site License */ || dsn >= 10000 && dsn < 10000000 /* Retail Package */ || dsn >= 10000000 /* Commercial Site License */ ) { char * p; if ( !quiet ) { printf("Registered to:\n\n"); p = get_reg_name(); if ( *p ) printf(" %s\n",p); p = get_reg_corp(); if ( *p ) printf(" %s\n",p); p = get_reg_sn(); printf("\n Serial number: %s\n",p); if ( dsn == 99 ) { /* Demo copy */ printf("\n For evaluation purposes only.\n"); printf("\n DO NOT DISTRIBUTE.\n"); } else if ( dsn >= 100 && dsn < 10000 ) { /* Academic Site License */ printf("\n For use only by current students, faculty, and staff\n") ; printf(" of %s.\n", get_reg_name() ) ; } else if ( dsn >= 10000000 ) { /* Commercial Site License */ if ( get_reg_count() ) printf(" licensed for %d users\n", get_reg_count() ) ; } printf("\n"); } } else { bleep( BP_WARN ) ; if ( !quiet ) { printf(" THIS COPY OF KERMIT SOFTWARE IS NOT REGISTERED.\n"); printf( " This software must be installed from the original diskettes using the SETUP\n"); printf( " procedure provided. It may not be downloaded or redistributed without a\n"); printf( " license from Columbia University. For further information send e-mail to\n"); printf( " kermit-orders@columbia.edu or call +1 (212) 854-3703.\n\n"); } #ifdef COMMENT doexit( BAD_EXIT, 0 ) ; #else /* COMMENT */ sleep(5) ; bleep( BP_WARN ) ; #endif /* COMMENT */ } colorcmd ^= 0x8 ; #endif /* NOLOCAL */ return 0; } long getmsec( void ) { #ifdef NT SYSTEMTIME LocalTime ; GetLocalTime(&LocalTime); return (LocalTime.wMilliseconds + 1000 * (LocalTime.wSecond + (60 * LocalTime.wMinute + (60 * LocalTime.wHour + (24 * LocalTime.wDay))))); #else return 0; #endif } #ifdef NT void DisplayCommProperties(HANDLE h) { COMMPROP * lpCommProp = NULL; LPMODEMDEVCAPS lpModemDevCaps = NULL; int rc=0; /* leave enough room for provider specific information */ lpCommProp = (COMMPROP *) malloc( 1024 ); if ( lpCommProp == NULL ) return; memset( lpCommProp, 0, 1024 ); lpCommProp->wPacketLength = 1024; lpCommProp->dwProvSpec1 = COMMPROP_INITIALIZED; rc = GetCommProperties( h, lpCommProp ); if ( !rc ) { debug(F111,"GetCommProperties","GetLastError",GetLastError()); free(lpCommProp); return ; } printf("GetCommProperties:\n"); printf(" PacketLength = %d (bytes)\n",lpCommProp->wPacketLength); printf(" PacketVersion = %x\n",lpCommProp->wPacketVersion); printf(" Services Implemented:\n"); if ( lpCommProp->dwServiceMask & SP_SERIALCOMM ) printf(" Serial Communication\n"); if ( lpCommProp->dwServiceMask & SP_PARITY ) printf(" Parity\n"); if ( lpCommProp->dwServiceMask & SP_BAUD ) printf(" Baud\n"); if ( lpCommProp->dwServiceMask & SP_DATABITS ) printf(" DataBits\n"); if ( lpCommProp->dwServiceMask & SP_STOPBITS ) printf(" StopBits\n"); if ( lpCommProp->dwServiceMask & SP_HANDSHAKING ) printf(" Handshaking\n"); if ( lpCommProp->dwServiceMask & SP_PARITY_CHECK ) printf(" Parity Check\n"); if ( lpCommProp->dwServiceMask & SP_RLSD ) printf(" Carrier Detect\n"); printf(" Max Tx Queue = %d (bytes) [0 - unlimited]\n",lpCommProp->dwMaxTxQueue); printf(" Max Rx Queue = %d (bytes) [0 - unlimited]\n",lpCommProp->dwMaxRxQueue); printf(" Max Baud Rate = "); switch ( lpCommProp->dwMaxBaud ) { case BAUD_075: printf("75 bps \n"); break; case BAUD_110: printf("110 bps \n"); break; case BAUD_134_5: printf("134.5 bps \n"); break; case BAUD_150: printf("150 bps \n"); break; case BAUD_300: printf("300 bps \n"); break; case BAUD_600: printf("600 bps \n"); break; case BAUD_1200: printf("1200 bps \n"); break; case BAUD_1800: printf("1800 bps \n"); break; case BAUD_2400: printf("2400 bps \n"); break; case BAUD_4800: printf("4800 bps \n"); break; case BAUD_7200: printf("7200 bps \n"); break; case BAUD_9600: printf("9600 bps \n"); break; case BAUD_14400: printf("14400 bps \n"); break; case BAUD_19200: printf("19200 bps \n"); break; case BAUD_38400: printf("38400 bps \n"); break; case BAUD_56K: printf("56K bps \n"); break; case BAUD_57600: printf("57600 bps \n"); break; case BAUD_115200:printf("115200 bps\n"); break; case BAUD_128K: printf("128K bps \n"); break; case BAUD_USER: printf("Programmable baud rates available\n"); break; default: printf("(unknown)\n"); break; } printf(" Provider Sub Type = "); switch ( lpCommProp->dwProvSubType ) { case PST_UNSPECIFIED : printf("Unspecified"); break; case PST_RS232 : printf("RS232"); break; case PST_PARALLELPORT : printf("Parallel Port"); break; case PST_RS422 : printf("RS422"); break; case PST_RS423 : printf("RS423"); break; case PST_RS449 : printf("RS449"); break; case PST_MODEM : printf("Modem"); break; case PST_FAX : printf("Fax"); break; case PST_SCANNER : printf("Scanner"); case PST_NETWORK_BRIDGE : printf("Network Bridge"); break; case PST_LAT : printf("LAT"); break; case PST_TCPIP_TELNET : printf("TCP/IP Telnet"); break; case PST_X25 : printf("X.25"); break; default: printf("Unknown"); } printf("\n"); printf(" Provider Capabilities:\n"); if ( lpCommProp->dwProvCapabilities & PCF_16BITMODE ) printf(" Special 16 Bit Mode supported\n"); if ( lpCommProp->dwProvCapabilities & PCF_DTRDSR ) printf(" DTR (data-terminal-ready)/DSR (data-set-ready) supported\n"); if ( lpCommProp->dwProvCapabilities & PCF_INTTIMEOUTS ) printf(" Interval time-outs supported\n"); if ( lpCommProp->dwProvCapabilities & PCF_PARITY_CHECK ) printf(" Parity checking supported\n"); if ( lpCommProp->dwProvCapabilities & PCF_RLSD ) printf(" RLSD (receive-line-signal-detect) supported\n"); if ( lpCommProp->dwProvCapabilities & PCF_RTSCTS ) printf(" RTS (request-to-send)/CTS (clear-to-send) supported\n"); if ( lpCommProp->dwProvCapabilities & PCF_SETXCHAR ) printf(" Settable XON/XOFF supported\n"); if ( lpCommProp->dwProvCapabilities & PCF_SPECIALCHARS ) printf(" Special character support provided\n"); if ( lpCommProp->dwProvCapabilities & PCF_TOTALTIMEOUTS ) printf(" Total (elapsed) time-outs supported\n"); if ( lpCommProp->dwProvCapabilities & PCF_XONXOFF ) printf(" XON/XOFF flow control supported\n"); printf(" Settable Parameters:\n"); if ( lpCommProp->dwSettableParams & SP_BAUD ) printf(" Baud Rate\n"); if ( lpCommProp->dwSettableParams & SP_DATABITS ) printf(" DataBits\n"); if ( lpCommProp->dwSettableParams & SP_HANDSHAKING ) printf(" Handshaking (flow control)\n"); if ( lpCommProp->dwSettableParams & SP_PARITY ) printf(" Parity\n"); if ( lpCommProp->dwSettableParams & SP_PARITY_CHECK ) printf(" Parity checking\n"); if ( lpCommProp->dwSettableParams & SP_RLSD ) printf(" RLSD (receive-line-signal-detect)\n"); if ( lpCommProp->dwSettableParams & SP_STOPBITS ) printf(" StopBits\n"); #ifdef COMMENT DWORD dwSettableBaud; // allowable baud rates WORD wSettableData; // allowable byte sizes WORD wSettableStopParity; // stop bits/parity allowed #endif printf(" Current Tx Queue = %d (bytes)\n",lpCommProp->dwCurrentTxQueue); printf(" Current Rx Queue = %d (bytes)\n",lpCommProp->dwCurrentRxQueue); if ( lpCommProp->dwProvSubType == PST_MODEM && lpCommProp->wcProvChar[0]) { lpModemDevCaps = (LPMODEMDEVCAPS) lpCommProp->wcProvChar; printf("Modem Device Capabilities:\n"); printf(" Modem Provider Version = %x\n",lpModemDevCaps->dwModemProviderVersion); if ( isWin95() ) { printf(" Modem Manufacturer = %s\n", lpModemDevCaps->dwModemManufacturerOffset ? (LPCSTR) lpModemDevCaps + lpModemDevCaps->dwModemManufacturerOffset : "(not specified)"); printf(" Modem Model = %s\n", lpModemDevCaps->dwModemModelOffset ? (LPCSTR) lpModemDevCaps + lpModemDevCaps->dwModemModelOffset : "(not specified)"); printf(" Modem Version = %s\n", lpModemDevCaps->dwModemVersionOffset ? (LPCSTR) lpModemDevCaps + lpModemDevCaps->dwModemVersionOffset : "(not specified)"); } else { char strbuf[256]; WORD * word; int i,len; if ( lpModemDevCaps->dwModemManufacturerOffset ) { len = lpModemDevCaps->dwModemManufacturerSize; word = (WORD *)((LPCSTR) lpModemDevCaps + lpModemDevCaps->dwModemManufacturerOffset); for ( i=0 ; i < len ; i++ ) strbuf[i] = (char) word[i]; strbuf[i] = '\0'; printf(" Modem Manufacturer = %s\n",strbuf); } else printf(" Modem Manufacturer = (not specified)\n"); if ( lpModemDevCaps->dwModemModelOffset ) { len = lpModemDevCaps->dwModemModelSize; word = (WORD *)((LPCSTR) lpModemDevCaps + lpModemDevCaps->dwModemModelOffset); for ( i=0 ; i < len ; i++ ) strbuf[i] = (char) word[i]; strbuf[i] = '\0'; printf(" Modem Model = %s\n",strbuf); } else printf(" Modem Model = (not specified)\n"); if ( lpModemDevCaps->dwModemVersionOffset ) { len = lpModemDevCaps->dwModemVersionSize; word = (WORD *)((LPCSTR) lpModemDevCaps + lpModemDevCaps->dwModemVersionOffset); for ( i=0 ; i < len ; i++ ) strbuf[i] = (char) word[i]; strbuf[i] = '\0'; printf(" Modem Version = %s\n",strbuf); } else printf(" Modem Version = (not specified)\n"); } printf(" Dial Options:\n"); if ( lpModemDevCaps->dwDialOptions & DIALOPTION_BILLING ) printf(" Specifies that the modem supports waiting for billing tone (bong).\n"); if ( lpModemDevCaps->dwDialOptions & DIALOPTION_QUIET ) printf(" Specifies that the modem supports waiting for quiet.\n"); if ( lpModemDevCaps->dwDialOptions & DIALOPTION_DIALTONE ) printf(" Specifies that the modem supports waiting for a dial tone.\n"); printf(" Max CallSetupFailTimer = %d (seconds)\n", lpModemDevCaps->dwCallSetupFailTimer); printf(" Max Inactivity Timeout = %d (1/10 seconds)\n", lpModemDevCaps->dwInactivityTimeout); printf(" Speaker Volumes:\n"); if ( lpModemDevCaps->dwSpeakerVolume & MDMVOLFLAG_LOW ) printf(" Low\n"); if ( lpModemDevCaps->dwSpeakerVolume & MDMVOLFLAG_MEDIUM ) printf(" Medium\n"); if ( lpModemDevCaps->dwSpeakerVolume & MDMVOLFLAG_HIGH ) printf(" High\n"); printf(" Speaker Modes:\n"); if ( lpModemDevCaps->dwSpeakerVolume & MDMSPKRFLAG_OFF ) printf(" Off\n"); if ( lpModemDevCaps->dwSpeakerVolume & MDMSPKRFLAG_DIAL ) printf(" Dial\n"); if ( lpModemDevCaps->dwSpeakerVolume & MDMSPKRFLAG_ON ) printf(" On\n"); if ( lpModemDevCaps->dwSpeakerVolume & MDMSPKRFLAG_CALLSETUP ) printf(" Call Setup\n"); printf(" Modem Options:\n"); if ( lpModemDevCaps->dwModemOptions & MDM_BLIND_DIAL ) printf(" Blind Dial\n"); if ( lpModemDevCaps->dwModemOptions & MDM_FLOWCONTROL_SOFT ) printf(" Software Flow Control\n"); if ( lpModemDevCaps->dwModemOptions & MDM_CCITT_OVERRIDE ) printf(" CCITT modulation override\n"); if ( lpModemDevCaps->dwModemOptions & MDM_FORCED_EC ) printf(" Forced Error Correction\n"); if ( lpModemDevCaps->dwModemOptions & MDM_CELLULAR ) printf(" Cellular\n"); if ( lpModemDevCaps->dwModemOptions & MDM_SPEED_ADJUST ) printf(" Speed Adjustment\n"); if ( lpModemDevCaps->dwModemOptions & MDM_COMPRESSION ) printf(" Compression\n"); if ( lpModemDevCaps->dwModemOptions & MDM_TONE_DIAL ) printf(" Tone Dial\n"); if ( lpModemDevCaps->dwModemOptions & MDM_ERROR_CONTROL ) printf(" Error Control\n"); if ( lpModemDevCaps->dwModemOptions & MDM_V23_OVERRIDE ) printf(" V.23 override\n"); if ( lpModemDevCaps->dwModemOptions & MDM_FLOWCONTROL_HARD ) printf(" Hardware flow control\n"); printf(" Max DTE Rate = %d (bits/second)\n", lpModemDevCaps->dwMaxDTERate); printf(" Max DCE Rate = %d (bits/second)\n", lpModemDevCaps->dwMaxDCERate); } printf("\n"); free(lpCommProp); return; } #endif /* NT */ #ifdef BPRINT extern int printbidi; /* SET BPRINTER (bidirectional) */ extern long pportspeed; /* Bidirection printer port speed, */ extern int pportparity; /* parity, */ extern int pportflow; /* and flow control */ extern char *printername; #ifdef NT TID tidBPrint=NULL; #else TID tidBPrint=0; #endif /* NT */ #ifdef NT HANDLE hBPrinter = NULL; #else /* NT */ HFILE hBPrinter = 0; #endif /* NT */ #ifdef NT int prtcfg(HANDLE hPrt) { DCB dcbBPrint; COMMTIMEOUTS timeouts ; if ( pportflow == FLO_KEEP && !pportspeed && !pportparity ) return(TRUE); SetCommMask( (HANDLE) hPrt, EV_RXCHAR ) ; SetupComm( (HANDLE) hPrt, 20000, 20000 ) ; PurgeComm( (HANDLE) hPrt, PURGE_RXABORT | PURGE_TXABORT | PURGE_RXCLEAR | PURGE_TXCLEAR ) ; dcbBPrint.DCBlength = sizeof(DCB); if (!GetCommState( (HANDLE) hPrt, &dcbBPrint )) { return FALSE ; } if (!GetCommTimeouts(hPrt, &timeouts)) { return FALSE ; } if ( deblog ) debugComm( "prtcfg initial values", &dcbBPrint, &timeouts ); dcbBPrint.fBinary = TRUE ; dcbBPrint.fErrorChar = FALSE ; dcbBPrint.fAbortOnError = FALSE ; dcbBPrint.ErrorChar = '?' ; dcbBPrint.fParity = TRUE ; dcbBPrint.StopBits = ONESTOPBIT ; dcbBPrint.BaudRate = pportspeed; dcbBPrint.fDsrSensitivity = FALSE ; dcbBPrint.fDtrControl = DTR_CONTROL_ENABLE ; switch (pportparity) { case 'o': dcbBPrint.ByteSize = 7; /* Data bits */ dcbBPrint.Parity = 1; break; case 'e': dcbBPrint.ByteSize = 7; /* Data bits */ dcbBPrint.Parity = 2; break; case 'm': dcbBPrint.ByteSize = 7; /* Data bits */ dcbBPrint.Parity = 3; break; case 's': dcbBPrint.ByteSize = 7; /* Data bits */ dcbBPrint.Parity = 4; break; default : dcbBPrint.ByteSize = 8; /* Data bits */ dcbBPrint.Parity = 0; /* No parity */ } switch(pportflow) { case FLO_XONX: dcbBPrint.fOutX = TRUE ; dcbBPrint.fInX = TRUE ; dcbBPrint.fRtsControl = RTS_CONTROL_ENABLE ; dcbBPrint.fOutxCtsFlow = FALSE ; dcbBPrint.fTXContinueOnXoff = /* TRUE */ FALSE ; break; case FLO_RTSC: dcbBPrint.fOutX = FALSE ; dcbBPrint.fInX = FALSE ; dcbBPrint.fRtsControl = RTS_CONTROL_HANDSHAKE ; dcbBPrint.fOutxCtsFlow = TRUE ; dcbBPrint.fTXContinueOnXoff = TRUE ; break; case FLO_KEEP: /* leave things exactly as they are */ break; case FLO_NONE: /* turn off all flow control completely */ dcbBPrint.fOutX = FALSE ; dcbBPrint.fInX = FALSE ; dcbBPrint.fRtsControl = RTS_CONTROL_ENABLE ; dcbBPrint.fOutxCtsFlow = FALSE ; dcbBPrint.fTXContinueOnXoff = TRUE ; break; } dcbBPrint.XonChar = 0x11 ; dcbBPrint.XoffChar = 0x13; dcbBPrint.XonLim = 10 ; dcbBPrint.XoffLim = 10 ; if (!SetCommState( hPrt, &dcbBPrint )) { return FALSE ; } /* Timeouts for Overlapped I/O from MS TTY.C example */ timeouts.ReadIntervalTimeout = MAXDWORD ; timeouts.ReadTotalTimeoutMultiplier = MAXDWORD ; timeouts.ReadTotalTimeoutConstant = 10 ; timeouts.WriteTotalTimeoutMultiplier = 1000 ; timeouts.WriteTotalTimeoutConstant = 1000 ; if (!SetCommTimeouts( hPrt, &timeouts )) { return FALSE ; } return(TRUE); } #endif /* NT */ int bprtstart( void ) { #ifdef NT SECURITY_ATTRIBUTES security ; if ( hBPrinter ) return TRUE; memset(&security, 0, sizeof(SECURITY_ATTRIBUTES)); security.nLength = sizeof(SECURITY_ATTRIBUTES); security.lpSecurityDescriptor = NULL ; security.bInheritHandle = FALSE ; if ((hBPrinter = CreateFile( printername ? printername : "PRN", GENERIC_READ | GENERIC_WRITE, FALSE, /* TRUE, /* do not share */ &security, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) { hBPrinter = NULL; return FALSE; } if ( !prtcfg(hBPrinter) ) { CloseHandle( hBPrinter ); hBPrinter = NULL; return FALSE; } /* The Port should now be configured, so lets start the thread */ tidBPrint = (TID) ckThreadBegin( &bprtthread,THRDSTKSIZ,0,FALSE,0); if ( !tidBPrint ) { CloseHandle( hBPrinter ); hBPrinter = NULL; return FALSE ; } return TRUE; #else /* NT */ DCBINFO dcbBPrint; LINECONTROL lc; UINT parm = 0, data = 0; ULONG action = 0; struct { long rate; char fract; } speed; ULONG error; if (error = DosOpen(printername ? printername : "PRN", (PHFILE)&hBPrinter,&action,0L,0,FILE_OPEN, OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYREADWRITE | OPEN_FLAGS_FAIL_ON_ERROR, 0L)) { hBPrinter = 0; return FALSE; } DosDevIOCtl(&data,sizeof(data),&parm,sizeof(parm), DEV_FLUSHINPUT,IOCTL_GENERAL,hBPrinter); /* Flush driver */ /* Get the current settings */ if (DosDevIOCtl(&dcbBPrint,sizeof(dcbBPrint),NULL,0, ASYNC_GETDCBINFO,IOCTL_ASYNC,hBPrinter)) { DosClose(hBPrinter); hBPrinter = 0; return FALSE; } dcbBPrint.fbCtlHndShake = MODE_DTR_CONTROL; dcbBPrint.fbFlowReplace &= ~(MODE_AUTO_RECEIVE | MODE_AUTO_TRANSMIT | /* clear only a few */ MODE_RTS_CONTROL | MODE_RTS_HANDSHAKE); if (pportflow == FLO_XONX) { dcbBPrint.fbFlowReplace |= (MODE_AUTO_RECEIVE | MODE_AUTO_TRANSMIT | MODE_RTS_CONTROL); } else if (pportflow == FLO_RTSC) { dcbBPrint.fbCtlHndShake |= MODE_CTS_HANDSHAKE; dcbBPrint.fbFlowReplace |= MODE_RTS_HANDSHAKE; } else if ( pportflow != FLO_KEEP ) { dcbBPrint.fbFlowReplace |= MODE_RTS_CONTROL; } /* set write timeout */ dcbBPrint.fbTimeout &= ~MODE_NO_WRITE_TIMEOUT; dcbBPrint.usWriteTimeout = 15 * 100; /* 15-second timeout */ /* Read "some" data from line mode */ dcbBPrint.fbTimeout &= ~MODE_NOWAIT_READ_TIMEOUT; dcbBPrint.fbTimeout |= MODE_WAIT_READ_TIMEOUT; /* Timeouts */ dcbBPrint.usReadTimeout = 9; /* Test every 0.1s per call */ /* Set DCB */ if (DosDevIOCtl(NULL,0,&dcbBPrint,sizeof(dcbBPrint), ASYNC_SETDCBINFO,IOCTL_ASYNC,hBPrinter)) { DosClose(hBPrinter); hBPrinter = 0; return FALSE; } if (pportflow != FLO_RTSC && pportflow != FLO_KEEP) {/* keep RTS permanently on */ MODEMSTATUS ms; UINT data; ms.fbModemOn = RTS_ON; ms.fbModemOff = 255; DosDevIOCtl(&data,sizeof(data),&ms,sizeof(ms), ASYNC_SETMODEMCTRL,IOCTL_ASYNC,hBPrinter); } if (DosDevIOCtl(&lc,sizeof(lc),NULL,0, ASYNC_GETLINECTRL,IOCTL_ASYNC,hBPrinter)) { DosClose(hBPrinter); hBPrinter = 0; return FALSE; } switch (pportparity) { case 'o': lc.bDataBits = 7; /* Data bits */ lc.bParity = 1; break; case 'e': lc.bDataBits = 7; /* Data bits */ lc.bParity = 2; break; case 'm': lc.bDataBits = 7; /* Data bits */ lc.bParity = 3; break; case 's': lc.bDataBits = 7; /* Data bits */ lc.bParity = 4; break; default : lc.bDataBits = 8; /* Data bits */ lc.bParity = 0; /* No parity */ } switch (1) { case 2: lc.bStopBits = 2; /* Two stop bits */ break; case 1: lc.bStopBits = 0; /* One stop bit */ break; default: /* No change */ break; } if (DosDevIOCtl(NULL,0,&lc,sizeof(lc), ASYNC_SETLINECTRL,IOCTL_ASYNC,hBPrinter)) { DosClose(hBPrinter); hBPrinter = 0; return FALSE; } if (pportspeed > 65535L) { speed.rate = pportspeed; speed.fract = 0; if (DosDevIOCtl(NULL,0,&speed,sizeof(speed),0x0043,IOCTL_ASYNC,hBPrinter)) { DosClose(hBPrinter); hBPrinter = 0; return FALSE; } } else if (DosDevIOCtl(NULL,0,&pportspeed,sizeof(pportspeed), ASYNC_SETBAUDRATE,IOCTL_ASYNC,hBPrinter)) { DosClose(hBPrinter); hBPrinter = 0; return FALSE; } /* Still must start the thread */ tidBPrint = (TID) ckThreadBegin( &bprtthread,THRDSTKSIZ,0,FALSE,0); if ( !tidBPrint ) { DosClose( hBPrinter ); hBPrinter = 0; return FALSE ; } return TRUE; #endif /* NT */ } int bprtstop( void ) { #ifdef NT if ( hBPrinter == NULL ) return TRUE; CloseHandle( hBPrinter ); hBPrinter = NULL; msleep( 500 ); CloseHandle( tidBPrint ); tidBPrint = NULL; return TRUE; #else /* NT */ if ( !hBPrinter ) return TRUE; DosClose(hBPrinter); hBPrinter = 0; DosClose(tidBPrint); tidBPrint = 0; msleep(500); return TRUE; #endif /* NT */ } void bprtthread( void * dummy ) { CHAR buf[64]; #ifdef NT DWORD read; #else ULONG read; ULONG Nesting; #endif #ifdef NT while ( hBPrinter ) { #ifdef COMMENT if ( WaitForSingleObject( hBPrinter, -1L ) != WAIT_OBJECT_0 ) { debug(F111,"BPrinter WaitForSingleObject", "GetLastError",GetLastError()); continue; } #endif if ( ReadFile( hBPrinter, buf, 64, &read, NULL ) ) { if ( read ) { buf[read] = '\0'; debug(F111,"BPrinter Read",buf,read); ttxout( buf, read ); } else msleep(100); } else { DWORD error = GetLastError(); debug(F111,"BPrinter ReadFile","GetLastError",error); switch ( error ) { default: break; } msleep(100); } } #else /* NT */ while ( hBPrinter ) { ULONG error; DosEnterMustComplete( &Nesting ) ; if ( !(error =DosRead(hBPrinter,buf,64,&read)) ) { DosExitMustComplete( &Nesting ); if ( read ) { buf[read] = '\0'; debug(F111,"BPrinter Read",buf,read); sendchars( buf, read ); } else msleep(100); } else { DosExitMustComplete( &Nesting ); debug(F111,"BPrinter DosRead","Error",error); switch ( error ) { default: break; } msleep(100); } } #endif /* NT */ } int bprtwrite( char * s, int len ) { #ifdef NT DWORD written=0; debug(F111,"BPrinter Write", s,len); if (!WriteFile( hBPrinter, s, len, &written, NULL )) { debug(F111,"BPrinter WriteFile", "GetLastError",GetLastError()); return -1; } else { return written; } #else /* NT */ UINT written; if(DosWrite(hBPrinter,s,len,(PVOID)&written)) return -1 ; else return written ; #endif /* NT */ } #endif /* BPRINT */ struct tm * #ifdef CK_ANSIC cmdate2tm(char * date, int gmt) /* date as "yyyymmdd hh:mm:ss" */ #else cmdate2tm(date,gmt) char * date; int gmt; #endif { /* date as "yyyymmdd hh:mm:ss" */ static struct tm _tm; time_t now; if ( strlen(date) != 17 || date[8] != ' ' || date[11] != ':' || date[14] != ':') return(NULL); time(&now); if ( gmt ) _tm = *gmtime(&now); else _tm = *localtime(&now); _tm.tm_year = (date[0]-'0')*1000 + (date[1]-'0')*100 + (date[2]-'0')*10 + (date[3]-'0')-1900; _tm.tm_mon = (date[4]-'0')*10 + (date[5]-'0')-1; _tm.tm_mday = (date[6]-'0')*10 + (date[7]-'0'); _tm.tm_hour = (date[9]-'0')*10 + (date[10]-'0'); _tm.tm_min = (date[12]-'0')*10 + (date[13]-'0'); _tm.tm_sec = (date[15]-'0')*10 + (date[16]-'0'); _tm.tm_wday = 0; _tm.tm_yday = 0; return(&_tm); } /*---------------------------------------------------------------------------*/ /* IsWARPed() */ /* In OS/2 terms, this means we have support for flexible column widths */ /*---------------------------------------------------------------------------*/ bool IsWARPed( void ) { #ifdef NT return TRUE ; #else ULONG StartIndex = QSV_VERSION_MAJOR ; /* Major Version Number */ ULONG EndIndex = QSV_VERSION_REVISION ; /* Revision Letter */ ULONG DataBuf[3] ; ULONG DataBufLen = 3 * sizeof(ULONG) ; APIRET rc ; DataBuf[0] = DataBuf[1] = DataBuf[2] = 0 ; rc = DosQuerySysInfo( StartIndex, EndIndex, DataBuf, DataBufLen ); return ( DataBuf[0] > 20 || DataBuf[0] == 20 && DataBuf[1] >= 30 ) ; #endif /* NT */ } #ifdef COMMENT WINBASEAPI DWORD WINAPI SetConsoleDisplayMode(HANDLE, DWORD, LPDWORD); WINBASEAPI BOOL WINAPI GetConsoleDisplayMode(LPDWORD); are not declared in any header, they are in KERNEL32.LIB. So, after declaring them (as above, for example) you can link with them. Use: SetConsoleDisplayMode(GetStdHandle(STD_OUTPUT_HANDLE), 1, &Result); or SetConsoleDisplayMode(GetStdHandle(STD_OUTPUT_HANDLE), 0, &Result); to go to fullscreen or windowed (respectively). I don't recall what "Result" holds when you're done, the curent status (post-execution) I think; a DejaNews search for the function name ought to turn up that info. - Vince #endif /* Undocumented Windows functions */ .