home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / k95source / ckotio.c < prev    next >
C/C++ Source or Header  |  2020-01-01  |  315KB  |  10,458 lines

  1. #ifdef NT
  2. char *ckxv = "Win32 Communications I/O, 8.0.229, 29 Dec 2005";
  3. #else
  4. char *ckxv = "OS/2 Communications I/O, 8.0.229, 29 Dec 2005";
  5. #endif /* NT */
  6.  
  7. /* Expiration Information */
  8. #ifdef BETATEST
  9. int expyear = 137,       /* years from 1900 */
  10.     expmon  = 0,         /* 0 = Jan */
  11.     expday  = 1;        /* 1 - 31 */
  12. #else
  13. int expyear = 137,      /* years from 1900 */
  14.     expmon  = 0,        /* 0 = Jan */
  15.     expday  = 1;       /* 1 - 31 */
  16. #endif /* BETATEST */
  17.  
  18. int  downloaded=0;               /* Is this a downloaded demo? */
  19. int  expired=0;                  /* Has demo expired? */
  20.  
  21. /* Define the following symbol to allow setting the title bar... */
  22. /* Not recommended in OS/2 because the call to do this is undocumented. */
  23. #define CK_SETTITLE
  24.  
  25. /* C K O T I O  --  Kermit communications I/O support for OS/2 systems */
  26.  
  27. /*
  28.   Also contains code to emulate the UNIX alarm() function under OS/2
  29.   and a set of opendir/readdir/closedir, etc, functions.
  30. */
  31.  
  32. /*
  33.   Authors: Jeffrey E Altman (jaltman@secure-endpoints.com), 
  34.              Secure Endpoints Inc., New York City
  35.            Frank da Cruz (fdc@columbia.edu),
  36.              Columbia University Academic Information Systems, New York City.
  37.  
  38.   Copyright (C) 1985, 2004, Trustees of Columbia University in the City of New
  39.   York.  All rights reserved.
  40.  
  41.   Originally adapted to OS/2 by Chris Adie <C.Adie@uk.ac.edinburgh>,
  42.   Edinburgh University Computing Service, 1988.
  43.  
  44.   Adapted to Kermit 5A by Kai Uwe Rommel <rommel@informatik.tu-muenchen.de>,
  45.   1992-93.
  46. */
  47.  
  48. /* Includes */
  49.  
  50. #include "ckcdeb.h"                     /* Typedefs, debug formats, etc */
  51. #include "ckcasc.h"                     /* ASCII character names */
  52. #include "ckcker.h"                     /* Kermit definitions */
  53. #include "ckcnet.h"                     /* Kermit definitions */
  54. #include "ckcxla.h"
  55. #include "ckuxla.h"                     /* Translation tables */
  56. #include "ckuusr.h"         /* Command definitions - needed for ckokey.h */
  57.  
  58. #include <ctype.h>                      /* Character types */
  59. #include <stdio.h>                      /* Standard i/o */
  60. #include <io.h>                         /* File io function declarations */
  61. #include <fcntl.h>
  62. #include <process.h>            /* Process-control functions */
  63. #include <string.h>                     /* String manipulation declarations */
  64. #include <sys/types.h>
  65. #include <sys/stat.h>
  66. #include <time.h>                       /* Time functions */
  67. #include <signal.h>
  68. #ifdef NT
  69. #include <locale.h>
  70. #endif /* NT */
  71. #ifdef OS2ONLY
  72. #include <limits.h>
  73. #endif /* OS2ONLY */
  74.  
  75. #include <assert.h>
  76. #ifdef NT
  77. #include <setjmpex.h>
  78. #else /* NT */
  79. #include <setjmp.h>
  80. #endif /* NT */
  81. #include "ckodir.h"
  82.  
  83. /* macros we might need */
  84. #ifndef _O_APPEND
  85. #define _O_APPEND  O_APPEND
  86. #endif
  87. #ifndef _O_WRONLY
  88. #define _O_WRONLY  O_WRONLY
  89. #endif
  90. #ifndef _O_CREAT
  91. #define _O_CREAT   O_CREAT
  92. #endif
  93. #ifndef _O_TEXT
  94. #define _O_TEXT    O_TEXT
  95. #endif
  96. #ifndef _SH_DENYNO
  97. #define _SH_DENYNO SH_DENYNO
  98. #endif
  99. #ifndef _O_BINARY
  100. #define _O_BINARY  O_BINARY
  101. #endif
  102. #ifndef _S_IFMT
  103. #define _S_IFMT S_IFMT
  104. #endif
  105. #ifndef _S_IFDIR
  106. #define _S_IFDIR S_IFDIR
  107. #endif
  108.  
  109. #ifdef NT
  110. #include <windows.h>
  111. #include <commctrl.h>
  112. #include <tapi.h>
  113. #include <mcx.h>
  114. #include "cknwin.h"
  115. #include "ckntap.h"
  116. #ifdef CK_TAPI
  117. int TAPIAvail = 0 ;   /* is TAPI Installed */
  118. extern int tttapi ;   /* is Line TAPI? */
  119. extern int tapipass;  /* TAPI Passthrough */
  120. #endif /* CK_TAPI */
  121. #ifdef KUI
  122. #include "ikui.h"
  123. struct _kui_init kui_init = {0,0,0,0,NULL,0,0,0,0,0,0,1};
  124. #endif /* KUI */
  125. _PROTOTYP( void DisplayCommProperties, (HANDLE));
  126. #define popen _popen
  127. #define pclose _pclose
  128. #endif /* NT */
  129.  
  130. /* Version herald(s) */
  131.  
  132. #include "ckuver.h"
  133. #ifdef CK_AUTHENTICATION
  134. #include "ckuath.h"
  135. #endif /* CK_AUTHENTICATION */
  136.  
  137. char ckxsystem[256] = HERALD;
  138. char *ckxsys = HERALD;
  139. #ifdef CK_UTSNAME
  140. char unm_nam[80]="";
  141. char unm_rel[80]="";
  142. char unm_mch[80]="";
  143. char unm_ver[80]="";
  144. char unm_mod[80]="";
  145. #endif /* CK_UTSNAME */
  146. static char *ckxrev = "32-bit";
  147.  
  148. /* OS/2 system header files & related stuff */
  149.  
  150. #ifndef NT
  151. #define INCL_WIN
  152. #define INCL_WINSWITCHLIST
  153. #define INCL_ERRORS
  154. #define INCL_KBD
  155. #ifdef OS2MOUSE
  156. #define INCL_MOU
  157. #endif /* OS2MOUSE */
  158. #define INCL_VIO
  159. #define INCL_DOSMISC
  160. #define INCL_DOSPROCESS
  161. #define INCL_DOSSEMAPHORES
  162. #define INCL_DOSQUEUES
  163. #define INCL_DOSEXCEPTIONS
  164. #define INCL_DOSSIGNALS
  165. #define INCL_DOSDEVICES
  166. #define INCL_DOSDEVIOCTL
  167. #define INCL_DOSNLS
  168. #define INCL_DOSASYNCTIMER
  169. #define INCL_DOSDATETIME
  170. #define INCL_DOSNMPIPES
  171. #include <os2.h>        /* This pulls in a whole load of stuff */
  172. #ifdef CK_REXX
  173. #define  INCL_REXXSAA
  174. #include <rexxsaa.h>
  175. #endif /* CK_REXX */
  176. #undef COMMENT
  177. #endif /* NT */
  178.  
  179. #include "ckowin.h"
  180. #include "ckcuni.h"
  181. #include "ckocon.h"
  182. #include "ckcsig.h"
  183. #include "ckokey.h"
  184. #include "ckoslp.h"
  185.  
  186. #ifdef CK_XYZ
  187. #include "p.h"
  188. #include "ckop.h"
  189. #ifdef XYZ_DLL
  190. int p_avail = 0 ;      /* Must load the DLL */
  191. #else
  192. int p_avail = 1 ;      /* No DLL to load - built-in */
  193. #endif /* XYZ_DLL */
  194. #endif /* CK_XYZ */
  195.  
  196. HKBD KbdHandle = 0 ;
  197. TID tidKbdHandler = (TID) 0,
  198.     tidRdComWrtScr   = (TID) 0,
  199.     tidConKbdHandler = (TID) 0,
  200.     tidTermScrnUpd   = (TID) 0;
  201. #ifdef NT
  202. TID  tidCommand = (TID) 0 ;
  203. DWORD CommandID = 0 ;
  204. int ckconraw = 0 ;
  205. HINSTANCE hInstance = NULL ;
  206. extern HWND hwndConsole;
  207. #endif /* NT */
  208. BOOL KbdActive = 0 ;
  209. int Shutdown = FALSE;
  210. extern int tt_status[VNUM] ;
  211. int k95stdin=0,k95stdout=0;
  212. extern int inserver, local;
  213.  
  214. #ifdef CHAR
  215. #undef CHAR
  216. #endif /* CHAR */
  217.  
  218. /*
  219.  Variables available to outside world:
  220.  
  221.    dftty  -- Pointer to default tty name string, like "/dev/tty".
  222.    dfloc  -- 0 if dftty is console, 1 if external line.
  223.    dfprty -- Default parity
  224.    dfflow -- Default flow control
  225.    ckxech -- Flag for who echoes console typein:
  226.      1 - The program (system echo is turned off)
  227.      0 - The system (or front end, or terminal).
  228.    functions that want to do their own echoing should check this flag
  229.    before doing so.
  230.  
  231.  Functions for assigned communication line (either external or console tty):
  232.  
  233.    sysinit()               -- System dependent program initialization
  234.    syscleanup()            -- System dependent program Shutdown
  235.    ttopen(ttname,local,mdmtyp) -- Open the named tty for exclusive access.
  236.    ttclos()                -- Close & reset the tty, releasing any access lock.
  237.    ttpkt(speed,flow,parity)-- Put the tty in packet mode
  238.                                 or in DIALING or CONNECT modem control state.
  239.    ttvt(speed,flow)        -- Put the tty in virtual terminal mode.
  240.    ttinl(dest,max,timo,...) -- Timed read packet from the tty.
  241.    ttinc(timo)             -- Timed read character from tty.
  242.    ttchk()                 -- See how many characters in tty input buffer.
  243.    ttxin(n,buf)            -- Read n characters from tty (untimed).
  244.    ttol(string,length)     -- Write a string to the tty.
  245.    ttxout(string,length)   -- Write a string to the tty (with conversions).
  246.    ttoc(c)                 -- Write a character to the tty.
  247.    ttflui()                -- Flush tty input buffer.
  248.    ttgspd()                -- Speed of tty line.
  249.  
  250. Functions for console terminal:
  251.  
  252.    conraw()  -- Set console into Raw mode
  253.    concooked() -- Set console into Cooked mode
  254.    conoc(c)  -- Unbuffered output, one character to console.
  255.    conol(s)  -- Unbuffered output, null-terminated string to the console.
  256.    conola(s) -- Unbuffered output, array of strings to the console.
  257.    conxo(n,s) -- Unbuffered output, n characters to the console.
  258.    conchk()  -- Check if characters available at console (bsd 4.2).
  259.                 Check if escape char (^\) typed at console (System III/V).
  260.    coninc(timo)  -- Timed get a character from the console.
  261.  Following routines are dummies:
  262.    congm()   -- Get console terminal mode.
  263.    concb()   -- Put console into single char mode with no echo.
  264.    conres()  -- Restore console to congm mode.
  265.    conint()  -- Enable console terminal interrupts.
  266.    connoi()  -- No console interrupts.
  267.  
  268. Time functions
  269.  
  270.    sleep(t)  -- Like UNIX sleep
  271.    msleep(m) -- Millisecond sleep
  272.    ztime(&s) -- Return pointer to date/time string
  273.    rtimer() --  Reset timer
  274.    gtimer()  -- Get elapsed time since last call to rtimer()
  275. */
  276.  
  277.  
  278. /* Defines */
  279.  
  280. #define HUPTIME 1000                    /* Milliseconds for hangup */
  281.  
  282. #ifndef DEVNAMLEN
  283. #ifdef NETCONN          /* Allow for long network hostnames */
  284. #define DEVNAMLEN 128
  285. #else                   /* No networks, applies to OS/2 device names only. */
  286. #define DEVNAMLEN 14
  287. #endif /* NETCONN */
  288. #endif /* DEVNAMLEN */
  289.  
  290. /* definitions hiding 32-bit / 16-bit differences */
  291.  
  292. #ifdef __32BIT__
  293.  
  294. #ifndef NT
  295. USHORT DosDevIOCtl32(PVOID pData, USHORT cbData, PVOID pParms, USHORT cbParms,
  296.                      USHORT usFunction, USHORT usCategory, HFILE hDevice)
  297. {
  298.   ULONG ulParmLengthInOut = cbParms, ulDataLengthInOut = cbData;
  299.   return (USHORT) DosDevIOCtl(hDevice, usCategory, usFunction,
  300.                               pParms, cbParms, &ulParmLengthInOut,
  301.                               pData, cbData, &ulDataLengthInOut);
  302. }
  303. #endif /* NT */
  304.  
  305. typedef ULONG U_INT;
  306. #define FILEFINDBUF FILEFINDBUF3
  307. #define FSQBUFFER FSQBUFFER2
  308.  
  309. #define DosFindFirst(p1, p2, p3, p4, p5, p6) \
  310.         DosFindFirst(p1, p2, p3, p4, p5, p6, 1)
  311.  
  312. #define DosDevIOCtl DosDevIOCtl32
  313. #endif
  314.  
  315. /* Declarations */
  316.  
  317. /* dftty is the device name of the default device for file transfer */
  318. /* dfloc is 0 if dftty is the user's console terminal, 1 if an external line */
  319.  
  320. extern long speed;
  321. extern int parity, fcharset, flow, ttcarr, isinterrupted;
  322. extern MACRO *macrotab;
  323. #ifdef OS2PM
  324. extern int os2pm;
  325. #endif /* OS2PM */
  326. #ifndef K95G
  327. /* This is to allow remote operation */
  328. char *dftty = "0"; /* stdin */
  329. int dfloc = 0;
  330. #else
  331. char *dftty = "com1"; /* COM1 */
  332. int dfloc = 1;
  333. #endif /* K95G */
  334.  
  335. int OSVer = 0;
  336. int nt351 = 0;
  337.  
  338. #ifdef NTSIG
  339. int TlsIndex = 0;
  340. #endif /* NTSIG */
  341.  
  342. #ifdef OS2ONLY
  343. bool ttslip = 0 ;  /* Equals 1 if being used as a replacement for SLIPTERM */
  344. bool ttppp  = 0 ;  /* Equals 1 if being used as a replacement for SLATTACH */
  345. #endif /* OS2ONLY */
  346. bool ttshare = 0;                /* do not open devices in shared mode */
  347. int ttyfd = -1;         /* TTY file descriptor (not open yet) */
  348. int dfprty = 0;                 /* Default parity (0 = none) */
  349. int ttprty = 0;                 /* Parity in use. */
  350. int ttmdm = 0;                  /* Modem in use. */
  351. int dfflow = FLO_AUTO;          /* Default flow is AUTO-DETECT */
  352. int backgrd = 0;                /* Assume in foreground */
  353. int ttcarr = CAR_AUT;           /* Carrier handling mode. */
  354. int ckxech = 1; /* 0 if system normally echoes console characters, else 1 */
  355. extern int tcsl ;               /* Local character set */
  356. extern int tt_inpacing ;        /* Input pacing */
  357. extern int exithangup;
  358.  
  359. #ifdef NETCONN
  360. extern int network, nettype, ttnproto, tn_exit, xitsta ;
  361. #endif
  362. extern int wasclosed;
  363. extern int exitonclose;
  364. extern int quiet;
  365.  
  366. int ck_sleepint = CK_SLEEPINT ;
  367.  
  368. char startupdir[CKMAXPATH] = "./";
  369. char exedir[CKMAXPATH] = "./";
  370. char usertitle[64] = "";
  371.  
  372. /* Declarations of variables global within this module */
  373.  
  374. static struct rdchbuf_rec {             /* Buffer for serial characters */
  375.         unsigned char buffer[32768];
  376.         U_INT length, index;
  377. } rdchbuf;
  378.  
  379. int ttpush=-1;                          /* So we can perform a peek */
  380.  
  381. static ULONG tcount;                    /* Elapsed time counter */
  382. static int conmode, consaved;
  383. static int ttpmsk = 0377;               /* Parity stripping mask. */
  384. static char ttnmsv[DEVNAMLEN+1];
  385. int islocal;
  386. int ishandle=0;
  387. int pid = 0;
  388. #ifdef NT
  389. static DCB ttydcb ;
  390. static LPCOMMCONFIG ttycfg=NULL;
  391. static DWORD cfgsize=0;
  392. #else /* NT */
  393. static DCBINFO ttydcb;
  394. #endif /* NT */
  395.  
  396. int quitonbreak = FALSE ;               /* Should SIGBREAK result in Quit */
  397. static int nOldCP;
  398. static char szOldTitle[80];
  399.  
  400. #ifdef NT
  401. HANDLE
  402. #else
  403. HVIO
  404. #endif /* NT */
  405. VioHandle = 0;
  406.  
  407. #ifndef NOLOCAL
  408. #ifndef KUI
  409. static CK_VIDEOMODEINFO StartupConsoleModeInfo ;
  410. #endif /* KUI */
  411. #endif /* NOLOCAL */
  412. #ifndef NT
  413. HAB hab = 0 ;         /* Handle to an Anchor Block */
  414. #endif /* NT */
  415.  
  416. TID tidAlarm = (TID) 0 ;
  417.  
  418. #define THRDSTKSIZ      (2*131072)
  419.  
  420.  
  421. #ifdef NT
  422. /* Overlapped I/O structures */
  423. #define MAXOW 7
  424. int maxow_usr = MAXOW;
  425. int maxow = MAXOW; /* only use 1; otherwise, serial ports are overdriven */
  426. /* This was caused because the default TX buffer size is guess what?  */
  427. /* ZERO.  Set the TX Buffer Size to be the largest packet size or     */
  428. /* larger with SetupComm() and things work great!                     */
  429. static OVERLAPPED overlapped_write[30] = {
  430.     {0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},
  431.     {0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},
  432.     {0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},
  433.     {0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},
  434.     {0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},
  435.     {0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},
  436.     {0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},
  437.     {0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},
  438.     {0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},
  439.     {0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1}
  440. };
  441. static char * ow_ptr[30] = {
  442.     NULL, NULL, NULL, NULL, NULL,NULL, NULL, NULL, NULL, NULL,
  443.     NULL, NULL, NULL, NULL, NULL,NULL, NULL, NULL, NULL, NULL,
  444.     NULL, NULL, NULL, NULL, NULL,NULL, NULL, NULL, NULL, NULL
  445. };
  446. static int    ow_size[30] = {
  447.     0,0,0,0,0,0,0,0,0,0,
  448.     0,0,0,0,0,0,0,0,0,0,
  449.     0,0,0,0,0,0,0,0,0,0
  450. };
  451. static int    ow_inuse[30] = {
  452.     0,0,0,0,0,0,0,0,0,0,
  453.     0,0,0,0,0,0,0,0,0,0,
  454.     0,0,0,0,0,0,0,0,0,0
  455. };
  456. int nActuallyWritten ;
  457.  
  458. /* Even though we allocate all of these read structs only the first one is */
  459. /* ever used unless NEWRDCH is defined.                                    */
  460. static OVERLAPPED overlapped_read[30] = {
  461.     {0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},
  462.     {0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},
  463.     {0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},
  464.     {0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},
  465.     {0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},
  466.     {0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},
  467.     {0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},
  468.     {0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},
  469.     {0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},
  470.     {0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1},{0L,0L,0L,0L,(HANDLE)-1}
  471. };
  472. static char * or_ptr[30] = {
  473.     NULL, NULL, NULL, NULL, NULL,NULL, NULL, NULL, NULL, NULL,
  474.     NULL, NULL, NULL, NULL, NULL,NULL, NULL, NULL, NULL, NULL,
  475.     NULL, NULL, NULL, NULL, NULL,NULL, NULL, NULL, NULL, NULL
  476. };
  477. static int    or_size[30] = {
  478.     0,0,0,0,0,0,0,0,0,0,
  479.     0,0,0,0,0,0,0,0,0,0,
  480.     0,0,0,0,0,0,0,0,0,0
  481. };
  482. static int    or_inuse[30] = {
  483.     0,0,0,0,0,0,0,0,0,0,
  484.     0,0,0,0,0,0,0,0,0,0,
  485.     0,0,0,0,0,0,0,0,0,0
  486. };
  487. static int    or_read[30] = {
  488.     0,0,0,0,0,0,0,0,0,0,
  489.     0,0,0,0,0,0,0,0,0,0,
  490.     0,0,0,0,0,0,0,0,0,0
  491. };
  492. int nActuallyRead ;
  493.  
  494. /* Lets try owwait = FALSE and see if anybody notices */
  495. int owwait = FALSE ;
  496. #endif /* NT */
  497.  
  498. char OS2CmdFile[256] = "";              /* a copy of cmdfile if specified */
  499.  
  500. #ifdef SESLIMIT
  501. static time_t start_time = 0;
  502. static char   warn[4];
  503. #endif /* SESLIMIT */
  504.  
  505. #define TT_MODE_NONE 0
  506. #define TT_MODE_VT   1
  507. #define TT_MODE_PKT  2
  508. #define TT_MODE_NORM 3
  509. static int tt_mode = TT_MODE_NONE;
  510.  
  511.  
  512. /* Forward declarations */
  513.  
  514. _PROTOTYP( static int os2setdtr,  (int) );
  515. _PROTOTYP( static int os2setcarr, (int) );
  516. _PROTOTYP( static int ttsettings, (int, int) );
  517. _PROTOTYP( int ttsetspd, (long) );
  518. _PROTOTYP( int concooked, (void) );
  519. _PROTOTYP( int os2rexxinit, (void) );
  520. _PROTOTYP( int os2setcp, (int) );
  521. _PROTOTYP( int os2getcplist, (int *, int) );
  522. _PROTOTYP( int os2getcp, (void) );
  523. _PROTOTYP( int os2settitle, (char *, int) );
  524. _PROTOTYP( int os2gettitle, (char *, int) );
  525. #ifndef NOLOCAL
  526. _PROTOTYP( int StartConnectThreads, ( void ) );
  527. _PROTOTYP( int StopConnectThreads, (int) );
  528. #endif /* NOLOCAL */
  529.  
  530. #ifndef NT
  531. _PROTOTYP( APIRET ConnectToPM, (void) );
  532. _PROTOTYP( APIRET ReadFromPM, (char *, ULONG, ULONG *) );
  533. _PROTOTYP( APIRET DisconnectFromPM, (void) );
  534. #endif /* OS2PM */
  535.  
  536. #ifdef HWPARITY
  537. /*
  538.   Unfortunately we must do this with global variables rather than through the
  539.   tt...() APIs to avoid changing the APIs and the many modules that use them.
  540.   If hwparity != 0, this indicates 8 data bits + parity, rather than 7 data
  541.   bits + parity or 8 data bits and no parity, and overrides the regular parity
  542.   variable, which is communicated to this module thru ttpkt(), and represented
  543.   locally by the ttprty variable.
  544. */
  545.     extern int hwparity;                /* Hardware parity */
  546.     extern int stopbits;                /* Stop bits */
  547. #endif /* HWPARITY */
  548.  
  549. #ifdef CKNTSIG
  550. /*
  551.   Our own SIGNAL routine, to avoid calling C runtime library.
  552. */
  553. static SIGTYP (*siginthandler)(int) = NULL; /* Pointer to SIGINT handler */
  554.  
  555. static BOOL
  556. cknthandler(DWORD dummy) {
  557.     debug(F100,"cknthandler","",0);
  558.     (*siginthandler)(SIGINT);
  559.     return(TRUE);
  560. }
  561.  
  562. SIGTYP (*
  563. ckntsignal(int sig, SIGTYP (*f)(int)))(int) {
  564.     debug(F101,"ckntsignal sig","",sig);
  565.     if (f == SIG_DFL) {
  566.         siginthandler = NULL;
  567. #ifndef KUI
  568.         SetConsoleCtrlHandler(NULL, FALSE);
  569. #endif /* KUI */
  570.     } else if (f == SIG_IGN) {
  571.         siginthandler = NULL;
  572. #ifndef KUI
  573.         SetConsoleCtrlHandler(NULL, FALSE);
  574. #endif /* KUI */
  575.     } else {
  576.         siginthandler = f;
  577. #ifndef KUI
  578.         SetConsoleCtrlHandler((PHANDLER_ROUTINE) cknthandler, TRUE);
  579. #endif /* KUI */
  580.     }
  581. }
  582. #endif /* CKNTSIG */
  583.  
  584. /* Saving/restoring of hot handles */
  585.  
  586. static int savedtty = 0;
  587. #ifdef NT
  588. static DCB saveddcb ;
  589. static LPCOMMCONFIG savedcfg=NULL;
  590. static DWORD savedcfgsize=0;
  591. #else /* NT */
  592. static long savedspeed;
  593. static LINECONTROL savedlc;
  594. static DCBINFO saveddcb;
  595. static BYTE savedstat;
  596. #endif /* NT */
  597.  
  598.  
  599. #ifdef NT
  600. /* d e b u g C o m m -- generate a debug log entry for the */
  601. /* current state of the DCB and TIMEOUT structures         */
  602.  
  603. void
  604. debugComm( char * msg, DCB * lpDCB, COMMTIMEOUTS * timeouts )
  605. {
  606.     if ( !deblog )
  607.         return;
  608.  
  609.     debug(F110,"debugComm",msg,0);
  610.     if ( lpDCB ) {
  611.     debug(F101,"  BaudRate                    ","",lpDCB->BaudRate);
  612.     debug(F101,"  Binary Mode (no EOF check)  ","",lpDCB->fBinary);
  613.     debug(F101,"  Enable Parity Checking      ","",lpDCB->fParity);
  614.     debug(F101,"  CTS Handshaking on output   ","",lpDCB->fOutxCtsFlow);
  615.     debug(F101,"  DSR Handshaking on output   ","",lpDCB->fOutxDsrFlow);
  616.     debug(F101,"  DTR Flow Control            ","",lpDCB->fDtrControl);
  617.     debug(F101,"  DSR Sensitivity             ","",lpDCB->fDsrSensitivity);
  618.     debug(F101,"  Continue TX when Xoff sent  ","",lpDCB->fTXContinueOnXoff);
  619.     debug(F101,"  Enable output X-ON/X-OFF    ","",lpDCB->fOutX);
  620.     debug(F101,"  Enable input X-ON/X-OFF     ","",lpDCB->fInX);
  621.     debug(F101,"  Enable Err Replacement      ","",lpDCB->fErrorChar);
  622.     debug(F101,"  Enable Null stripping       ","",lpDCB->fNull);
  623.     debug(F101,"  RTS flow control            ","",lpDCB->fRtsControl);
  624.     debug(F101,"  Abort all I/O on Error      ","",lpDCB->fAbortOnError);
  625.     debug(F101,"  Transmit X-ON threshold     ","",lpDCB->XonLim);
  626.     debug(F101,"  Transmit X-OFF threshold    ","",lpDCB->XoffLim);
  627.     debug(F101,"  Num of bits/byte, 4-8       ","",lpDCB->ByteSize);
  628.     debug(F101,"  Parity (0-4=N,O,E,M,S)      ","",lpDCB->Parity);
  629.     debug(F101,"  StopBits (0,1,2 = 1, 1.5, 2)","",lpDCB->StopBits);
  630.     debug(F101,"  Tx and Rx X-ON character    ","",lpDCB->XonChar);
  631.     debug(F101,"  Tx and Rx X-OFF character   ","",lpDCB->XoffChar);
  632.     debug(F101,"  Error replacement char      ","",lpDCB->ErrorChar);
  633.     debug(F101,"  End of Input character      ","",lpDCB->EofChar);
  634.     debug(F101,"  Received Event character    ","",lpDCB->EvtChar);
  635.     }
  636.     if ( timeouts ) {
  637.     debug(F101,"  ReadIntervalTimeout        ","",timeouts->ReadIntervalTimeout);
  638.     debug(F101,"  ReadTotalTimeoutMultiplier ","",timeouts->ReadTotalTimeoutMultiplier);
  639.     debug(F101,"  ReadTotalTimeoutConstant   ","",timeouts->ReadTotalTimeoutConstant);
  640.     debug(F101,"  WriteTotalTimeoutMultiplier","",timeouts->WriteTotalTimeoutMultiplier);
  641.     debug(F101,"  WriteTotalTimeoutConstant  ","",timeouts->WriteTotalTimeoutConstant);
  642.     }
  643. }
  644. #endif /* NT */
  645.  
  646.  
  647. int
  648. savetty() {
  649.     if (ttyfd != -1) {
  650. #ifdef NT
  651.         saveddcb.DCBlength = sizeof(DCB);
  652.         GetCommState( (HANDLE) ttyfd, &saveddcb ) ;
  653.  
  654.         if ( deblog )
  655.             debugComm( "savetty initial values", &ttydcb, NULL );
  656.  
  657.         savedcfg->dwSize = 1024;
  658.         savedcfgsize = 1024;
  659.         GetCommConfig( (HANDLE) ttyfd, savedcfg, &savedcfgsize );
  660. #else /* NT */
  661.         savedspeed = ttgspd();
  662.         DosDevIOCtl(&savedlc,sizeof(savedlc),NULL,0,
  663.                 ASYNC_GETLINECTRL,IOCTL_ASYNC,ttyfd);
  664.         DosDevIOCtl(&saveddcb,sizeof(saveddcb),NULL,0,
  665.                 ASYNC_GETDCBINFO,IOCTL_ASYNC,ttyfd);
  666.         DosDevIOCtl(&savedstat,sizeof(savedstat),NULL,0,
  667.                 ASYNC_GETMODEMOUTPUT,IOCTL_ASYNC,ttyfd);
  668. #endif /* NT */
  669.         savedtty = 1;
  670.     }
  671.     return 0;
  672. }
  673.  
  674. int
  675. restoretty() {
  676. #ifndef NT
  677.     MODEMSTATUS ms;
  678.     UINT cmd = 0, data = 0 ;
  679. #endif /* NT */
  680.  
  681.   if (savedtty) {
  682. #ifdef NT
  683. #ifdef COMMENT
  684.       SetCommState( (HANDLE) ttyfd, &saveddcb ) ;
  685. #else
  686.       SetCommConfig( (HANDLE) ttyfd, savedcfg, savedcfgsize );
  687. #endif
  688. #else /* NT */
  689.     ttsetspd(savedspeed);
  690.     DosDevIOCtl(&data,sizeof(data),&cmd,sizeof(cmd),
  691.                 DEV_FLUSHOUTPUT,IOCTL_GENERAL,ttyfd);
  692.     DosDevIOCtl(NULL,0,&savedlc,sizeof(savedlc),
  693.                 ASYNC_SETLINECTRL,IOCTL_ASYNC,ttyfd);
  694.     ms.fbModemOn = 0;
  695.     ms.fbModemOff = 255;
  696.     if (savedstat & DTR_ON) ms.fbModemOn |= DTR_ON;
  697.     else ms.fbModemOff &= DTR_OFF;
  698.     if (savedstat & RTS_ON) ms.fbModemOn |= RTS_ON;
  699.     else ms.fbModemOff &= RTS_OFF;
  700.     DosDevIOCtl(&data,sizeof(data),&ms,sizeof(ms),
  701.                 ASYNC_SETMODEMCTRL,IOCTL_ASYNC,ttyfd);
  702.     DosDevIOCtl(NULL,0,&saveddcb,sizeof(saveddcb),
  703.                 ASYNC_SETDCBINFO,IOCTL_ASYNC,ttyfd);
  704. #endif /* NT */
  705.   }
  706.   return 0;
  707. }
  708.  
  709. /* Code Page functions */
  710.  
  711. int
  712. os2getcp() {
  713. #ifdef NT
  714. #ifdef KUI
  715.     return GetACP();
  716. #else /* KUI */
  717.     return GetConsoleCP() ;
  718. #endif /* KUI */
  719. #else /* NT */
  720.     U_INT cbData, nCodePage[8];
  721.     return (DosQueryCp(sizeof(nCodePage), nCodePage, &cbData) == 0)
  722.            ? nCodePage[0] : 0;
  723. #endif /* NT */
  724. }
  725.  
  726.  
  727. #ifdef COMMENT
  728. int
  729. os2checkcp(cp) int cp; {
  730. #ifdef NT
  731.     return FALSE ;
  732. #else /* NT */
  733.     U_INT cbData, nCodePage[8], nCnt;
  734.     if (DosQueryCp(sizeof(nCodePage), nCodePage, &cbData))
  735.       return FALSE;
  736.     for (nCnt = 1; nCnt < cbData / sizeof(nCodePage[0]); nCnt++)
  737.       if (nCodePage[nCnt] == cp)
  738.         return TRUE;
  739.     return FALSE;
  740. #endif /* NT */
  741. }
  742. #endif /* COMMENT */
  743.  
  744. #ifdef NT
  745. static int * CPList ;
  746. static int CPListSize ;
  747. static int CPListIndex ;
  748.  
  749. BOOL CALLBACK
  750. enumproc( LPSTR cpstr )
  751. {
  752.    CPList[CPListIndex] = atoi(cpstr) ;
  753.    if ( ++CPListIndex < CPListSize )
  754.       return TRUE ;
  755.    else return FALSE ;
  756. }
  757. #endif /* NT */
  758.  
  759. int
  760. os2getcplist(cplist, size) int *cplist; int size; {
  761. #ifdef NT
  762.    int i ;
  763.  
  764.     CPList = cplist ;
  765.     CPListSize = size / sizeof(int) ;
  766.     CPListIndex = 1 ;
  767.  
  768.     for ( i=0 ; i<CPListSize ; i++ )
  769.         CPList[i] = 0 ;
  770.  
  771.     CPList[0] = GetConsoleCP() ;
  772.  
  773.    if (size > 1)
  774.        EnumSystemCodePages( enumproc, CP_INSTALLED ) ;
  775.  
  776.     return CPListIndex ;
  777. #else /* NT */
  778.     U_INT cbData;
  779.     if (DosQueryCp(size, (U_INT *) cplist, &cbData))
  780.       return 0;
  781.     return cbData / sizeof(int);
  782. #endif /* NT */
  783. }
  784.  
  785. int                                     /* Change code page */
  786. os2setcp(cp) int cp; {
  787. #ifdef NT
  788. #ifdef KUI
  789.     return 1;                           /* Code Pages do not apply */
  790. #else /* KUI */
  791.     return SetConsoleOutputCP( cp )
  792.         && SetConsoleCP( cp ) ;
  793. #endif /* KUI */
  794. #else /* NT */
  795.     if ( k95stdout )                    /* Can't set Code Page for stdio    */
  796.         return 0;                       /* This has the affect of blocking  */
  797.                                         /* and never returning if we have a */
  798.                                         /* getchar() in progress.           */
  799.  
  800.     return((VioSetCp(0, cp, VioHandle) == 0) &&
  801.            (KbdSetCp(0, cp, KbdHandle) == 0) &&
  802.            (DosSetProcessCp(cp) == 0));
  803. #endif /* NT */
  804. }
  805.  
  806. void
  807. DisableHardErrors( void )
  808. {
  809. #ifdef NT
  810.    SetErrorMode( SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS ) ;
  811. #else /* NT */
  812.     DosError(FERR_DISABLEHARDERR | FERR_DISABLEEXCEPTION);
  813. #endif /* NT */
  814. }
  815.  
  816. APIRET
  817. os2getpid(void)
  818. {
  819. #ifdef NT
  820.     return GetCurrentProcessId();
  821. #else
  822.     PTIB pptib;
  823.     PPIB pppib;
  824.     DosGetInfoBlocks(&pptib, &pppib);
  825.     return pppib -> pib_ulpid;
  826. #endif
  827. }
  828.  
  829. #ifdef NT
  830. int
  831. setOSVer( void )
  832. {
  833.     OSVERSIONINFO osverinfo ;
  834.     osverinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO) ;
  835.     GetVersionEx( &osverinfo ) ;
  836.     OSVer = osverinfo.dwPlatformId ;
  837.     if ( osverinfo.dwMajorVersion < 4 )
  838.         nt351 = 1;
  839.     return(OSVer);
  840. }
  841. #endif /* NT */
  842.  
  843. char *
  844. getcpu( void )
  845. {
  846.    static char buffer[64] = "unknown" ;
  847. #ifdef NT
  848.    SYSTEM_INFO si ;
  849.    char numstr[32] ;
  850.    memset( &si, 0, sizeof(si) ) ;
  851.    GetSystemInfo( &si ) ;
  852.    if ( isWin95() && !si.wProcessorLevel )
  853.    {
  854.       switch ( si.dwProcessorType ) {
  855.       case 386:
  856.          strcpy( buffer, "intel-386" ) ;
  857.          break;
  858.       case 486:
  859.          strcpy( buffer, "intel-486" ) ;
  860.          break;
  861.       case 586:
  862.          strcpy( buffer, "intel-pentium" ) ;
  863.          break;
  864.       default:
  865.          strcpy( buffer, "intel-" ) ;
  866.          _itoa( si.dwProcessorType, numstr, 10 ) ;
  867.          ckstrncat( buffer, numstr, 64 ) ;
  868.       }
  869.    }
  870.    else
  871.    {
  872.       switch ( si.wProcessorArchitecture ) {
  873.       case PROCESSOR_ARCHITECTURE_INTEL:
  874.          ckstrncpy( buffer, "intel-", 64 ) ;
  875.          switch ( si.wProcessorLevel ) {
  876.          case 3:
  877.             ckstrncat( buffer, "386", 64 ) ;
  878.             break;
  879.          case 4:
  880.             ckstrncat( buffer, "486", 64 ) ;
  881.             break;
  882.          case 5:
  883.             ckstrncat( buffer, "pentium", 64 ) ;
  884.             break;
  885.          default:
  886.             _itoa( si.wProcessorLevel, numstr, 10 ) ;
  887.             ckstrncat( buffer, numstr, 64 );
  888.          }
  889.          break;
  890.       case PROCESSOR_ARCHITECTURE_PPC:
  891.          ckstrncpy( buffer, "ppc-", 64 ) ;
  892.          switch ( si.wProcessorLevel ) {
  893.          case 1:
  894.             ckstrncat( buffer, "601", 64 ) ;
  895.             break;
  896.          case 3:
  897.             ckstrncat( buffer, "603", 64 ) ;
  898.             break;
  899.          case 4:
  900.             ckstrncat( buffer, "604", 64 ) ;
  901.             break;
  902.          case 6:
  903.             ckstrncat( buffer, "603+", 64 ) ;
  904.             break;
  905.          case 9:
  906.             ckstrncat( buffer, "604+", 64 ) ;
  907.             break;
  908.          case 20:
  909.             ckstrncat( buffer, "620", 64 ) ;
  910.             break;
  911.          default:
  912.             _itoa( si.wProcessorLevel, numstr, 10 ) ;
  913.             ckstrncat( buffer, numstr, 64 );
  914.          }
  915.          break;
  916.       case PROCESSOR_ARCHITECTURE_MIPS:
  917.          ckstrncpy( buffer, "mips-", 64 ) ;
  918.          switch ( si.wProcessorLevel ) {
  919.          case 4:
  920.             ckstrncat( buffer, "r4000", 64 ) ;
  921.             break;
  922.          default:
  923.             _itoa( si.wProcessorLevel, numstr, 10 ) ;
  924.             ckstrncat( buffer, numstr, 64 );
  925.          }
  926.          break;
  927.       case PROCESSOR_ARCHITECTURE_ALPHA:
  928.          ckstrncpy( buffer, "alpha-", 64 ) ;
  929.          switch ( si.wProcessorLevel ) {
  930.          default:
  931.             _itoa( si.wProcessorLevel, numstr, 10 ) ;
  932.             ckstrncat( buffer, numstr, 64 );
  933.          }
  934.          break;
  935.       case PROCESSOR_ARCHITECTURE_UNKNOWN:
  936.          ckstrncpy( buffer, "unknown", 64 ) ;
  937.          break;
  938.       }
  939.    }
  940. #else /* NT */
  941.    ckstrncpy( buffer, CKCPU, 64 ) ;
  942. #endif
  943.    return buffer ;
  944. }
  945.  
  946. static void
  947. term_signal(int sig) {
  948.     debug(F101,"term_signal handler","",sig);
  949. #ifndef NOLOCAL
  950.     SetConnectMode(0,CSX_KILL_SIG);
  951. #endif /* NOLOCAL */
  952.     printf("\n!!! Received KILL signal !!!\n");
  953.     bleep(BP_FAIL);
  954. #ifndef NODIAL
  955.     if (mdmhup() < 1)
  956. #endif /* NODIAL */
  957.         tthang();
  958.     doexit(BAD_EXIT,-1);
  959.     signal(SIGTERM, SIG_DFL);
  960. }
  961.  
  962. #ifdef NT
  963. BOOL
  964. CloseHandler( DWORD dwCtrlType ) {      //  control signal type
  965.     extern unsigned long startflags;
  966.  
  967.     debug(F111,"Win32 Close Handler","dwCtrlType",dwCtrlType);
  968.     switch ( dwCtrlType ) {
  969.     case CTRL_LOGOFF_EVENT:
  970.         if ( startflags & 128 )
  971.             return TRUE;
  972.         doexit(BAD_EXIT,0);
  973.         return TRUE;
  974.     case CTRL_CLOSE_EVENT:
  975.     case CTRL_SHUTDOWN_EVENT:
  976.         doexit(BAD_EXIT,0);
  977.         return TRUE;
  978.     default:
  979.         return FALSE;
  980.     }
  981. }
  982.  
  983. #ifdef COMMENT
  984. /*
  985.     If we were MS-DOS Kermit we could use these functions.
  986.     But we are a Win32 app, so we can't.
  987. */
  988. BOOL
  989. Win95QueryClose( void ) {
  990.     short rc ;
  991.     __asm {
  992.         mov ah, 16h ;
  993.         mov al, 8Fh ;
  994.         mov dh, 1 ;
  995.         mov dl, 0 ;
  996.         int 2Fh ;
  997.         mov rc, ax ;
  998.     }
  999.     return !rc;
  1000. }
  1001.  
  1002. BOOL
  1003. Win95AcknowledgeClose( void ) {
  1004.     short rc ;
  1005.     __asm {
  1006.         mov ah, 16h ;
  1007.         mov al, 8Fh ;
  1008.         mov dh, 2 ;
  1009.         mov dl, 0 ;
  1010.         int 2Fh ;
  1011.         or ax, ax ;
  1012.         mov rc, ax ;
  1013.     }
  1014.     return rc ;
  1015. }
  1016.  
  1017. BOOL
  1018. Win95CancelClose( void ) {
  1019.     short rc ;
  1020.     __asm {
  1021.         mov ah, 16h ;
  1022.         mov al, 8Fh ;
  1023.         mov dh, 3 ;
  1024.         mov dl, 0 ;
  1025.         int 2Fh ;
  1026.         or ax, ax ;
  1027.         mov rc, ax ;
  1028.     }
  1029.     return rc;
  1030. }
  1031.  
  1032. BOOL
  1033. Win95EnableClose( void ) {
  1034.     short rc ;
  1035.     __asm {
  1036.         mov ah, 16h ;
  1037.         mov al, 8Fh ;
  1038.         mov dh, 0 ;
  1039.         mov dl, 01h ;
  1040.         int 2Fh ;
  1041.         or ax, ax ;
  1042.         mov rc, ax ;
  1043.     }
  1044.     return rc;
  1045.  
  1046. }
  1047.  
  1048. BOOL
  1049. Win95DisableClose( void ) {
  1050.     short rc ;
  1051.     __asm {
  1052.         mov ah, 16h ;
  1053.         mov al, 8Fh ;
  1054.         mov dh, 0 ;
  1055.         mov dl, 00h ;
  1056.         int 2Fh ;
  1057.         or ax, ax ;
  1058.         mov rc, ax ;
  1059.     }
  1060.     return rc;
  1061. }
  1062. #endif /* COMMENT */
  1063. #endif /* NT */
  1064.  
  1065.  
  1066. #ifdef NT
  1067. void
  1068. Win95AltGrInit( void )
  1069. {
  1070.     /*
  1071.     Performing a grep ALTGRUSED *.ASM in the ddk\keyb\samples\driver\layout
  1072.     directory show that at least of the samples only three layouts do not
  1073.     have an AltGr key.  So if we can read the layout, lets initialize the
  1074.     win95altgr variable to 1 if the layout is not one of those three.
  1075.     And 0 if we are unable to read the layout.
  1076.  
  1077.     Btw, 4NT.EXE just assumes that every layout has an AltGr key.
  1078.     */
  1079.     extern int win95altgr;
  1080.     CHAR    lpLayoutName[KL_NAMELENGTH]="";
  1081.     int rc ;
  1082.     rc = GetKeyboardLayoutName(lpLayoutName);
  1083.     debug(F111,"Win95 Keyboard Layout Name",lpLayoutName,rc);
  1084.     if ( lpLayoutName[0] ) {
  1085.         if ( !strcmp("00000409",lpLayoutName) )         /* US 101 */
  1086.             win95altgr = 0;
  1087.         else if ( !strcmp("00020409",lpLayoutName) )    /* US Dvorak */
  1088.             win95altgr = 0;
  1089.         else if ( !strcmp("00000411",lpLayoutName) )    /* Japan 101 */
  1090.             win95altgr = 0;
  1091.         else
  1092.             win95altgr = 1;
  1093.     }
  1094.     else
  1095.         win95altgr = 0;
  1096.     debug(F101,"Win95 AltGr Initialized","",win95altgr);
  1097. }
  1098.  
  1099. void
  1100. Win95DisplayLocale( void )
  1101. {
  1102.     LCID    Locale = LOCALE_SYSTEM_DEFAULT ;
  1103.     LCTYPE  LCType = 0;
  1104.     CHAR    lpLCDATA[1024]="";
  1105.     int     cchData=1024;
  1106.     int     rc=0;
  1107.     int     i=0;
  1108.     HKL     KBLayout=0;
  1109.     CHAR    lpLayoutName[KL_NAMELENGTH]="";
  1110.  
  1111.     KBLayout = GetKeyboardLayout(0);
  1112.     GetKeyboardLayoutName(lpLayoutName);
  1113.     printf("Keyboard Layout = %s [%u]\n",lpLayoutName,(unsigned short)KBLayout);
  1114.  
  1115.  
  1116.     printf("Locale Information:\n");
  1117.     for ( LCType=0 ; LCType<= 0x5A ; LCType++ ) {
  1118.         rc = GetLocaleInfo( LOCALE_SYSTEM_DEFAULT,LCType,lpLCDATA,cchData);
  1119.         printf("  LCType 0x%08x = \"%-25s\"",LCType,lpLCDATA);
  1120.         rc = GetLocaleInfo( LOCALE_USER_DEFAULT,LCType,lpLCDATA,cchData);
  1121.         printf("  \"%-25s\"\n",lpLCDATA);
  1122.     }
  1123. }
  1124. #endif /* NT */
  1125.  
  1126. char *
  1127. GetLocalUser()
  1128. {
  1129.     static char localuser[UIDBUFLEN]="";
  1130.  
  1131.     /* Initialize the Username buffer if possible */
  1132.     /* Allow environment variable to override the OS value */
  1133.     char * user;
  1134.     
  1135.     if (localuser[0])
  1136.         return(localuser);
  1137.     
  1138.     user = getenv( "USER" );
  1139.     if ( user ) {
  1140.         ckstrncpy( localuser, user, UIDBUFLEN );
  1141.     }
  1142.     else
  1143.         localuser[0] = '\0';
  1144.  
  1145. #ifdef NT
  1146.     if (!localuser[0]) {
  1147.         DWORD uidlen = UIDBUFLEN ;
  1148.         GetUserName( localuser, &uidlen );
  1149.     }
  1150. #endif /* NT */
  1151.     return(localuser);
  1152. }
  1153.  
  1154. #ifdef NT
  1155. VOID
  1156. firsttime(void)
  1157. {
  1158.     /* 
  1159.      *  What we will do is check to see if the Common and User App Data
  1160.      *  directories exist.  If they do not, we will create them.
  1161.      */
  1162.  
  1163.     char dir[CKMAXPATH+1], file[CKMAXPATH+1], *common, *appdata, *personal;
  1164.  
  1165.     common = (char *)GetAppData(1);
  1166.     if ( common ) {
  1167.         ckmakmsg(dir,CKMAXPATH+1,(char *)common, "Kermit 95/", NULL, NULL);
  1168.         if ( !isdir(dir) ) {
  1169.             zmkdir(dir);
  1170.  
  1171.             ckmakmsg(dir,CKMAXPATH+1,(char *)common, "Kermit 95/SSH/", NULL, NULL);
  1172.             zmkdir(dir);
  1173.  
  1174.             ckmakmsg(dir,CKMAXPATH+1,(char *)common, "Kermit 95/CERTS/", NULL, NULL);
  1175.             zmkdir(dir);
  1176.  
  1177.             ckmakmsg(dir,CKMAXPATH+1,(char *)common, "Kermit 95/CRLS/", NULL, NULL);
  1178.             zmkdir(dir);
  1179.  
  1180.             ckmakmsg(dir,CKMAXPATH+1,(char *)common, "Kermit 95/KEYMAPS/", NULL, NULL);
  1181.             zmkdir(dir);
  1182.  
  1183.             ckmakmsg(dir,CKMAXPATH+1,(char *)common, "Kermit 95/PHONES/", NULL, NULL);
  1184.             zmkdir(dir);
  1185.  
  1186.             ckmakmsg(dir,CKMAXPATH+1,(char *)common, "Kermit 95/SCRIPTS/", NULL, NULL);
  1187.             zmkdir(dir);
  1188.         }
  1189.     }
  1190.     appdata = (char *)GetAppData(0);
  1191.     if ( appdata ) {
  1192.         ckmakmsg(dir,CKMAXPATH+1,(char *)appdata, "Kermit 95/", NULL, NULL);
  1193.         if ( !isdir(dir) ) {
  1194.             zmkdir(dir);
  1195.  
  1196.             if ( common = (char *)GetAppData(1) ) {
  1197.                 ckmakmsg(file,CKMAXPATH+1,(char *)common, "Kermit 95/K95CUSTOM.INI", NULL, NULL);
  1198.                 zcopy(file,dir);
  1199.                 appdata = (char *)GetAppData(0);
  1200.             }
  1201.  
  1202.             ckmakmsg(dir,CKMAXPATH+1,(char *)appdata, "Kermit 95/SSH/", NULL, NULL);
  1203.             zmkdir(dir);
  1204.  
  1205.             ckmakmsg(dir,CKMAXPATH+1,(char *)appdata, "Kermit 95/CERTS/", NULL, NULL);
  1206.             zmkdir(dir);
  1207.  
  1208.             ckmakmsg(dir,CKMAXPATH+1,(char *)appdata, "Kermit 95/CRLS/", NULL, NULL);
  1209.             zmkdir(dir);
  1210.  
  1211.             ckmakmsg(dir,CKMAXPATH+1,(char *)appdata, "Kermit 95/KEYMAPS/", NULL, NULL);
  1212.             zmkdir(dir);
  1213.  
  1214.             ckmakmsg(dir,CKMAXPATH+1,(char *)appdata, "Kermit 95/PHONES/", NULL, NULL);
  1215.             zmkdir(dir);
  1216.  
  1217.             ckmakmsg(dir,CKMAXPATH+1,(char *)appdata, "Kermit 95/SCRIPTS/", NULL, NULL);
  1218.             zmkdir(dir);
  1219.         }
  1220.  
  1221.         personal = (char *)GetPersonal();
  1222.         if ( personal ) {
  1223.             ckmakmsg(dir,CKMAXPATH+1,(char *)personal, "DOWNLOAD/", NULL, NULL);
  1224.             if ( !isdir(dir) )
  1225.                 zmkdir(dir);
  1226.         }
  1227.     }
  1228.  
  1229. }
  1230. #endif /* NT */
  1231.  
  1232. /*  S Y S I N I T  --  System-dependent program initialization.  */
  1233.  
  1234. int SysInited = 0;
  1235.  
  1236. int
  1237. sysinit() {
  1238.     extern char uidbuf[] ;
  1239.     extern struct ck_p ptab[] ;
  1240.     extern int priority;
  1241.     extern int tt_mouse ;
  1242.     extern int tt_modechg;
  1243.     char *ptr;
  1244.     int n;
  1245.     extern unsigned long startflags;
  1246.     extern int DeleteStartupFile;
  1247.     extern int StartedFromDialer;
  1248.     extern int fdispla;
  1249.     extern int initvik;
  1250.     extern int tt_type;
  1251.  
  1252.     /* we raise the priority here because when we are not in
  1253.         connect mode, there is only thread (this one) which
  1254.         performs any serial or Network I/O.  So this has to
  1255.         be a server priority thread.
  1256.         Upon entering connect mode we will lower the priority
  1257.         of this thread, and then raise upon exiting.  This
  1258.         should provide snappy ckermit performance without too
  1259.         much damage to other processes.  That is because this
  1260.         thread remains blocked most of time waiting on our
  1261.         keyboard (event) buffer semaphore.  So even though the
  1262.         KbdHandler is Ready (at regular priority), this thread
  1263.         will be blocked unless we are waiting for serial or
  1264.         network I/O.
  1265.     */
  1266. #ifdef NT
  1267.     int    WinThreadInit=0;
  1268.     DWORD mode ;
  1269. #ifndef NOTERM
  1270.     extern int tt_attr_bug ;
  1271. #endif /* NOTERM */
  1272.  
  1273.     connoi() ;
  1274.     ck_sleepint = isWin95() ? CK_SLEEPINT : CK_SLEEPINT * 2;
  1275.     SetFileApisToOEM() ;  /* Otherwise, filenames are translated */
  1276.  
  1277.     /* Allocate memory for COMMCONFIG structure */
  1278.     savedcfg = (LPCOMMCONFIG) malloc( 1024 );
  1279.     if ( savedcfg ) {
  1280.         memset( savedcfg, 0, 1024 );
  1281.         savedcfg->dwSize = 1024;
  1282.     }
  1283.     ttycfg = (LPCOMMCONFIG) malloc( 1024 );
  1284.     if (ttycfg) {
  1285.         memset( ttycfg, 0, 1024 );
  1286.         ttycfg->dwSize = 1024;
  1287.     }
  1288.  
  1289. #ifndef NOLOCAL
  1290. #ifndef KUI
  1291.     Win32ConsoleInit() ;            /* Initialize the Console, Stdin, Stdout */
  1292. #endif /* KUI */
  1293. #endif /* NT */
  1294. #endif /* NOLOCAL */
  1295.  
  1296.     /* Construct the system ID string */
  1297. #ifdef NT
  1298.     {
  1299.         OSVERSIONINFO osverinfo ;
  1300.         osverinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO) ;
  1301.         GetVersionEx( &osverinfo ) ;
  1302.  
  1303.         if ( startflags & 1 )
  1304.             OSVer = VER_PLATFORM_WIN32_NT;
  1305.         else
  1306.             OSVer = osverinfo.dwPlatformId ;
  1307.  
  1308.         sprintf(ckxsystem, " %s %1d.%02d(%1d)%s%s",
  1309.                  ( osverinfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS ?
  1310.                    (osverinfo.dwMinorVersion == 0 ? "Windows 95" : "Windows 98")  :
  1311.                    osverinfo.dwPlatformId == VER_PLATFORM_WIN32_NT ?
  1312.                    (osverinfo.dwMajorVersion < 5 ? "Windows NT" : "Windows 2000/XP") :
  1313.                    "Windows Unknown" ),
  1314.                  osverinfo.dwMajorVersion,
  1315.                  osverinfo.dwMinorVersion,
  1316.                  LOWORD(osverinfo.dwBuildNumber),
  1317.                  osverinfo.szCSDVersion && osverinfo.szCSDVersion[0] ? " " : "",
  1318.                  osverinfo.szCSDVersion ? osverinfo.szCSDVersion : "");
  1319. #ifdef CK_UTSNAME
  1320.         sprintf(unm_nam,
  1321.                  ( osverinfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS ?
  1322.                    (osverinfo.dwMinorVersion == 0 ? "Windows 95" : "Windows 98")  :
  1323.                    osverinfo.dwPlatformId == VER_PLATFORM_WIN32_NT ?
  1324.                    (osverinfo.dwMajorVersion < 5 ? "Windows NT" : "Windows 2000/XP") :
  1325.                    "Windows Unknown" ));
  1326.         sprintf(unm_rel,"%1d.%02d",
  1327.                  osverinfo.dwMajorVersion,
  1328.                  osverinfo.dwMinorVersion);
  1329.         sprintf(unm_ver,"(%1d)%s%s",
  1330.                 LOWORD(osverinfo.dwBuildNumber),
  1331.                 osverinfo.szCSDVersion && osverinfo.szCSDVersion[0] ? " " : "",
  1332.                 osverinfo.szCSDVersion ? osverinfo.szCSDVersion : "");
  1333. #endif /* CK_UTSNAME */
  1334. #ifdef KUI
  1335.         InitCommonControls();
  1336. #endif /* KUI */
  1337.     }
  1338. #else /* NT */
  1339.     {
  1340.         ULONG StartIndex = QSV_VERSION_MAJOR ; /* Major Version Number */
  1341.         ULONG EndIndex   = QSV_VERSION_REVISION ; /* Revision Letter      */
  1342.         ULONG DataBuf[3] ;
  1343.         ULONG DataBufLen = 3 * sizeof(ULONG) ;
  1344.  
  1345.         DosQuerySysInfo( StartIndex,
  1346.                              EndIndex,
  1347.                              DataBuf,
  1348.                              DataBufLen );
  1349.         sprintf(ckxsystem, " %s OS/2 %1d.%02d", ckxrev, _osmajor / 10, _osminor);
  1350. #ifdef CK_UTSNAME
  1351.         sprintf(unm_nam,"OS/2");
  1352.         sprintf(unm_rel,"%1d.%02d", _osmajor / 10, _osminor);
  1353.         sprintf(unm_ver,"%c",DataBuf[2]);
  1354. #endif /* CK_UTSNAME */
  1355.     }
  1356. #endif /* NT */
  1357. #ifdef CK_UTSNAME
  1358.     sprintf(unm_mch,getcpu());
  1359. #endif /* CK_UTSNAME */
  1360.     debug(F110,"Operating System",ckxsystem,0);
  1361.  
  1362. #ifdef NT
  1363.     setlocale(LC_ALL, "" );             /* Import locale from OS */
  1364. #endif /* NT */
  1365.  
  1366.     if ( StartedFromDialer )            /* We delete the cmdfile by default  */
  1367.         DeleteStartupFile = 1;          /* only when started from the dialer */
  1368.  
  1369.     k95stdin = (startflags & 32) ? 1 : 0;
  1370.     k95stdout = (startflags & 64) ? 1 : 0;
  1371.  
  1372.     if ( k95stdout ) {
  1373.         extern int interm;
  1374.         interm = 0;                     /* SET INPUT TERMINAL OFF */
  1375.     }
  1376.  
  1377.     if ( k95stdin ) {
  1378. #ifdef NT
  1379.         _setmode(_fileno(stdin),_O_BINARY);
  1380. #else
  1381.         setmode(fileno(stdin),_O_BINARY);
  1382. #endif /* NT */
  1383.     }
  1384.     if ( k95stdout ) {
  1385. #ifdef NT
  1386.         _setmode(_fileno(stdout),_O_TEXT);
  1387. #else
  1388.         setmode(fileno(stdout),_O_TEXT);
  1389. #endif /* NT */
  1390.         setbuf(stdout,NULL);
  1391.         fdispla = XYFD_S;
  1392.     }
  1393. #ifdef OS2ONLY
  1394.     if ( IsOS2FullScreen() )
  1395.     {
  1396.         extern int trueunderline;
  1397.         extern int trueblink;
  1398.         trueunderline = FALSE;
  1399.         trueblink   = FALSE;
  1400.     }
  1401. #endif /* OS2ONLY */
  1402.  
  1403. #ifdef NTSIG
  1404.     TlsIndex = TlsAlloc();
  1405. #endif /* NTSIG */
  1406.  
  1407.     CreateAlarmMutex( FALSE ) ;
  1408. #ifndef NOLOCAL
  1409.     CreateScreenMutex( FALSE ) ;
  1410.     CreateVscrnMutex( FALSE ) ;
  1411.     CreateVscrnDirtyMutex( FALSE );
  1412.     CreateConnectModeMutex( FALSE ) ;
  1413. #endif /* NOLOCAL */
  1414.     CreateThreadMgmtMutex( FALSE );
  1415.     CreateTCPIPMutex( FALSE );
  1416.     CreateDebugMutex( FALSE ) ;
  1417.     CreateTelnetMutex( FALSE ) ;
  1418.     CreateCommMutex( FALSE );
  1419. #ifdef CK_SSL
  1420.     CreateSSLMutex( FALSE );
  1421. #endif /* CK_SSL */
  1422.     CreateAlarmSem( FALSE ) ;
  1423. #ifndef NOLOCAL
  1424.     CreateCommandModeSem( TRUE );
  1425.     CreateTerminalModeSem( FALSE );
  1426.     CreateAlarmSem( FALSE ) ;
  1427.     CreateRdComWrtScrThreadSem( FALSE ) ;
  1428.     CreateTermScrnUpdThreadSem( FALSE ) ;
  1429.     CreateConKbdHandlerThreadSem( FALSE ) ;
  1430.     CreateRdComWrtScrThreadDownSem( FALSE ) ;
  1431.     CreateTermScrnUpdThreadDownSem( FALSE ) ;
  1432.     CreateConKbdHandlerThreadDownSem( FALSE ) ;
  1433.     CreateKeyMapInitSem( FALSE ) ;
  1434.     CreateVscrnDirtySem( TRUE );
  1435. #endif /* NOLOCAL */
  1436.  
  1437. #ifndef NOSETKEY
  1438.     keymapinit();                       /* Initialize key maps */
  1439.     keynaminit();                       /* Initialize key names */
  1440. #endif /* NOSETKEY */
  1441. #ifdef OS2MOUSE
  1442.     mousemapinit(-1,-1);                /* Initialize mouse maps */
  1443. #endif /* OS2MOUSE */
  1444. #ifndef NOKVERBS
  1445.     initvik = 1;                        /* Remember that we did */
  1446. #endif /* NOKVERBS */
  1447.  
  1448. #ifdef NT
  1449. #ifndef NOTERM
  1450.     tt_attr_bug = isWin95();
  1451. #endif /* NOTERM */
  1452. #ifndef KUI
  1453.     hInstance = GetModuleHandle(NULL) ;
  1454.     debug(F101,"hInstance","",hInstance);
  1455.     hwndConsole = GetConsoleHwnd() ;
  1456.     if ( isWin95() )
  1457.     {
  1458.         MENUITEMINFO info;
  1459.         HMENU hMenu;
  1460.  
  1461.         hMenu = GetSystemMenu(hwndConsole, FALSE);
  1462.         info.cbSize = sizeof(info);
  1463.         RemoveMenu(hMenu, SC_CLOSE, MF_BYCOMMAND);
  1464.         DrawMenuBar(hwndConsole);
  1465.         CloseHandle(hMenu);
  1466.     }
  1467. #endif /* KUI */
  1468.     WinThreadInit = WindowThreadInit( (void *) hInstance );
  1469. #endif /* NT */
  1470.  
  1471. #ifdef OS2ONLY
  1472.     hab = WinInitialize(0);
  1473.     debug ( F101, "WinInitialize hab","",hab) ;
  1474.     ConnectToPM();
  1475. #endif /* OS2ONLY */
  1476.  
  1477.     pid = os2getpid() ;
  1478.     DisableHardErrors() ;
  1479.  
  1480.     le_init();
  1481.     alarm(0) ;          /* We must start the alarm thread */
  1482.  
  1483.     keybufinit() ;      /* Must come before the KbdHandler */
  1484.  
  1485. #ifndef NOLOCAL
  1486. #ifndef KUI
  1487. #ifdef IKSD
  1488.     if ( !inserver )
  1489. #endif /* IKSD */
  1490.     KbdHandlerInit() ;
  1491. #endif /* KUI */
  1492. #endif /* NOLOCAL */
  1493.  
  1494. #ifdef NT
  1495.     CreateSerialMutex( FALSE ) ;
  1496. #ifndef KUI
  1497. #ifdef COMMENT
  1498.     VioHandle = GetStdHandle( STD_OUTPUT_HANDLE ) ;
  1499. #else
  1500.     if ( !k95stdout )
  1501.     VioHandle = CreateFile( "CONOUT$", GENERIC_READ | GENERIC_WRITE,
  1502.                        FILE_SHARE_READ | FILE_SHARE_WRITE,
  1503.                        NULL,
  1504.                        OPEN_EXISTING,
  1505.                        0,
  1506.                        0) ;
  1507. #endif /* COMMENT */
  1508. #endif /* KUI */
  1509.     DuplicateHandle(GetCurrentProcess(),GetCurrentThread(),
  1510.                     GetCurrentProcess(),&tidCommand,
  1511.                     0,FALSE, DUPLICATE_SAME_ACCESS );
  1512.     debug(F101,"Command Thread Handle","",tidCommand);
  1513.     CommandID = GetCurrentThreadId() ;
  1514.     debug(F101,"Command Thread ID","",CommandID) ;
  1515. #endif /* NT */
  1516. #ifndef NOLOCAL
  1517. #ifndef KUI
  1518.     if ( !k95stdout ) {
  1519. #ifdef NT
  1520.         CK_VIDEOMODEINFO mi;
  1521. #endif /* NT */
  1522.         GetMode( &StartupConsoleModeInfo );
  1523. #ifdef NT
  1524.         if ( StartupConsoleModeInfo.col != StartupConsoleModeInfo.sbcol ||
  1525.              StartupConsoleModeInfo.row != StartupConsoleModeInfo.sbrow ) {
  1526.             memcpy(&mi, &StartupConsoleModeInfo, sizeof(CK_VIDEOMODEINFO));
  1527.             mi.sbcol = mi.col;
  1528.             mi.sbrow = mi.row;
  1529.             SetMode( &mi );
  1530.         }
  1531. #endif /* NT */
  1532.     }
  1533. #endif /* KUI */
  1534. #ifndef NT
  1535.     OpenClipboardServer() ;
  1536. #endif /* NT */
  1537.  
  1538.     getcmdcolor();
  1539.     os2gettitle(szOldTitle, sizeof(szOldTitle));
  1540.     debug(F110,"sysinit szOldTitle",szOldTitle,0);
  1541.     os2settitle("", TRUE);
  1542. #endif /* NOLOCAL */
  1543.  
  1544.     nOldCP = os2getcp();
  1545.  
  1546.     switch (nOldCP) {
  1547.     case 437:
  1548.         tcsl = TX_CP437 ;
  1549.         fcharset = FC_CP437;
  1550.         break;
  1551.     case 850:
  1552.         tcsl = TX_CP850;
  1553.         fcharset = FC_CP850;
  1554.         break;
  1555.     case 858:
  1556.         tcsl = TX_CP858;
  1557.         fcharset = FC_CP850;
  1558.         break;
  1559.     case 855:
  1560.         tcsl = TX_CP855;
  1561.         break;
  1562.     case 856:
  1563.         tcsl = TX_CP856;
  1564.         break;
  1565.     case 852:
  1566.         tcsl = TX_CP852;
  1567.         fcharset = FC_CP852;
  1568.         break;
  1569.     case 862:
  1570.         tcsl = TX_CP862;
  1571.         fcharset = FC_CP862;
  1572.         break;
  1573.     case 866:
  1574.         tcsl = TX_CP866;
  1575.         fcharset = FC_CP866;
  1576.         break;
  1577.     case 1004:  /* Windows 3.1 - supposed to be Latin-1 */
  1578.         tcsl = TX_8859_1;
  1579.         fcharset = FC_1LATIN;
  1580.         break;
  1581.     case 1252:  /* Win32 - like Latin-1 */
  1582.         tcsl = TX_CP1252;
  1583.         fcharset = FC_1LATIN;
  1584.         break;
  1585. #ifdef KUI
  1586.     default:
  1587.         tcsl = TX_CP1252;
  1588.         fcharset = FC_1LATIN;
  1589. #else
  1590.     default:
  1591.         tcsl = TX_CP437 ;
  1592.         fcharset = FC_CP437;
  1593. #endif
  1594.     }
  1595.  
  1596.  
  1597. #ifdef __IBMC__
  1598.     setvbuf(stdout, NULL, _IONBF, 0);
  1599.     setmode(1, _O_TEXT);
  1600. #endif /* __IBMC__ */
  1601.  
  1602. #ifdef NT
  1603.     {
  1604.         char * p = GetLoadPath();
  1605.         DWORD len;
  1606.  
  1607.         len = GetShortPathName(p,exedir,CKMAXPATH);
  1608.         if ( len == 0 || len > CKMAXPATH )
  1609.             ckstrncpy(exedir, p, CKMAXPATH);
  1610.     }
  1611. #else
  1612.     ckstrncpy(exedir, GetLoadPath(), CKMAXPATH);
  1613. #endif /* NT */
  1614.     if ( (ptr = strrchr(exedir, '\\')) != NULL )
  1615.         *ptr = 0;
  1616.     for (ptr = exedir; *ptr; ptr++)     /* Convert backslashes to slashes */
  1617.         if (*ptr == '\\')
  1618.             *ptr = '/';
  1619.     n = (int)strlen(exedir);            /* Add slash to end if necessary */
  1620.     if (n > -1 && n < CKMAXPATH) {
  1621.         if (exedir[n-1] != '/') {
  1622.             exedir[n] = '/';
  1623.             exedir[n+1] = '\0';
  1624.         }
  1625.     }
  1626. #ifdef NT
  1627.     {
  1628.         char * p = zgtdir();
  1629.         DWORD len;
  1630.  
  1631.         len = GetShortPathName(p,startupdir,CKMAXPATH);
  1632.         if ( len == 0 || len > CKMAXPATH )
  1633.             ckstrncpy(startupdir, p, CKMAXPATH);
  1634.     }
  1635. #else
  1636.     ckstrncpy(startupdir, zgtdir(), CKMAXPATH);
  1637. #endif /* NT */
  1638.     for (ptr = startupdir; *ptr; ptr++) { /* Convert backslashes to slashes */
  1639.         if (*ptr == '\\')
  1640.             *ptr = '/';
  1641.     }
  1642.     n = (int)strlen(startupdir);        /* Add slash to end if necessary */
  1643.     if (n > -1 && n < CKMAXPATH) {
  1644.         if (startupdir[n-1] != '/') {
  1645.             startupdir[n] = '/';
  1646.             startupdir[n+1] = '\0';
  1647.         }
  1648.     }
  1649.     ckstrncpy(ttnmsv, dftty, DEVNAMLEN+1);
  1650.     islocal = is_a_tty(0) && !ttiscom(0);
  1651.     if (!islocal) {
  1652.        os2setdtr(1);
  1653.        ttsettings(dfprty,stopbits);
  1654.        ttsetflow(flow);
  1655.        os2settimo(0,0);
  1656.        os2setcarr(ttcarr == CAR_ON);
  1657.     }
  1658.     else
  1659.        concooked();                     /* Initialize keyboard */
  1660. #ifndef NOLOCAL
  1661.     if ( !k95stdout ) {
  1662.         extern int row_init, col_init;
  1663.         ttgcwsz() ;
  1664.         if ( !row_init && !col_init )
  1665.             ttgwsiz() ;
  1666.     }
  1667.  
  1668.     debug(F100,"about to VscrnInit()","",0);
  1669.     /* Setup the Virtual Screens */
  1670.     VscrnInit( VCMD ) ;
  1671.     VscrnInit( VTERM ) ;
  1672.     /* VscrnInit( VCS ) ; */
  1673.     VscrnInit( VSTATUS ) ;
  1674.     settermtype(tt_type,1);
  1675. #endif /* NOLOCAL */
  1676. #ifdef KUI
  1677.     /* This does more than just display the Splash Screen */
  1678.     KuiInit( (void *) hInstance, &kui_init );
  1679.     hwndConsole = KuiThreadInit( (void *) hInstance ) ;
  1680. #endif /* KUI */
  1681.  
  1682. #ifdef CK_REXX
  1683.     os2rexxinit() ;
  1684. #endif /* CK_REXX */
  1685.  
  1686. #ifdef CK_SECURITY
  1687.     ck_security_loaddll();
  1688. #endif /* CK_SECURITY */
  1689.  
  1690. #ifdef CK_TAPI
  1691.     debug(F100,"Initializing TAPI","",0);
  1692.     if ( WinThreadInit && !(startflags & 4)) {
  1693.         /* TAPI requires a Window Handle */
  1694.         TAPIAvail = cktapiinit() ;
  1695.         if ( TAPIAvail ) {
  1696.             cktapiopen();
  1697. #ifndef NODIAL 
  1698.             CopyTapiLocationInfoToKermitDialCmd();
  1699. #endif /* NODIAL */
  1700.         }
  1701.     }
  1702. #endif /* CK_TAPI */
  1703.  
  1704. #ifdef CK_XYZ
  1705. #ifdef XYZ_DLL
  1706.     if ( !(startflags & 16) ) {
  1707.         debug(F100,"Initializing P_DLL","",0);
  1708.         p_avail = !load_p_dll() ;
  1709.         if ( !p_avail )
  1710.         {
  1711.             bleep(BP_WARN);
  1712. #ifdef NT
  1713.             printf("Unable to load P95.DLL - X,Y,Zmodem is unavailable\n");
  1714. #else /* NT */
  1715.             printf("Unable to load P2.DLL - X,Y,Zmodem is unavailable\n");
  1716. #endif /* NT */
  1717.         }
  1718.     }
  1719. #endif /* XYZ_DLL */
  1720. #endif /* CK_XYZ */
  1721.  
  1722. #ifndef NOLOCAL
  1723. #ifndef KUI
  1724. #ifdef ONETERMUPD
  1725.     if ( !(inserver && k95stdout) )
  1726.         tidTermScrnUpd = (TID) ckThreadBegin( &TermScrnUpd,
  1727.                                           THRDSTKSIZ, 0, TRUE, 0 ) ;
  1728. #endif /* ONETERMUPD */
  1729. #endif /* KUI */
  1730. #endif /* NOLOCAL */
  1731. #ifndef NOTERM
  1732.     updanswerbk();
  1733. #endif /* NOTERM */
  1734.  
  1735.     SetThreadPrty(priority,0);
  1736.  
  1737. #ifdef NT
  1738. #ifndef KUI
  1739.     debug(F100,"About to SetConsoleCtrlHandler","",0);
  1740.     if (SetConsoleCtrlHandler( (PHANDLER_ROUTINE) CloseHandler, TRUE ))
  1741.         debug(F100,"SetConsoleCtrlHandler succeeded","",0);
  1742.     else
  1743.         debug(F101,"SetConsoleCtrlHandler failed","",GetLastError());
  1744. #endif /* KUI */
  1745. #endif /* NT */
  1746.  
  1747. #ifndef KUI
  1748. #ifdef OS2MOUSE
  1749.     if (tt_mouse)
  1750.         os2_mouseon() ;
  1751. #endif /* OS2MOUSE */
  1752. #endif /* KUI */
  1753.  
  1754.     if ( quitonbreak )
  1755.         signal(SIGBREAK,term_signal);
  1756.     signal(SIGTERM,term_signal);
  1757.  
  1758. #ifdef IKSD
  1759.     if ( !inserver )
  1760. #endif /* IKSD */
  1761. #ifndef NOLOCAL
  1762.     StartConnectThreads();
  1763. #endif /* NOLOCAL */
  1764.  
  1765. #ifdef CK_ENVIRONMENT
  1766.     {
  1767.         extern char tn_env_acct[], tn_env_disp[], tn_env_job[],
  1768.         tn_env_prnt[], tn_env_sys[], uidbuf[];
  1769.         char *p;
  1770.         if (p = getenv("USER")) {
  1771.             ckstrncpy(uidbuf,p,UIDBUFLEN);
  1772.         }
  1773.         if (p = getenv("JOB")) {
  1774.             ckstrncpy(tn_env_job,p,64);
  1775.         }
  1776.         if (p = getenv("ACCT")) {
  1777.             ckstrncpy(tn_env_acct,p,64);
  1778.         }
  1779.         if (p = getenv("PRINTER")) {
  1780.             ckstrncpy(tn_env_prnt,p,64);
  1781.         }
  1782.         if (p = getenv("DISPLAY")) {
  1783.             ckstrncpy(tn_env_disp,p,64);
  1784.         }
  1785. #ifdef NT
  1786.         strcpy(tn_env_sys,"WIN32");
  1787. #else
  1788.         strcpy(tn_env_sys,"OS2");
  1789. #endif /* NT */
  1790.     }
  1791. #endif /* CK_ENVIRONMENT */
  1792. #ifdef CK_SNDLOC
  1793.     {
  1794.         extern char * tn_loc;
  1795.         char *p;
  1796.         if (p = getenv("LOCATION"))
  1797.           makestr(&tn_loc,p);
  1798.     }
  1799. #endif /* CK_SNDLOC */
  1800. #ifndef NOLOCAL
  1801.     os2InitFromRegistry();
  1802. #endif /* NOLOCAL */
  1803. #ifdef NT
  1804.     if ( isWin95() ) {
  1805. #ifdef BETADEBUG
  1806.         Win95DisplayLocale();
  1807. #endif /* BETADEBUG */
  1808.         Win95AltGrInit();
  1809.     }
  1810. #endif /* NT */
  1811.  
  1812. #ifdef NETCONN
  1813.     netinit();
  1814. #endif /* NETCONN */
  1815.  
  1816. #ifdef IKSD
  1817.     if ( !inserver )
  1818. #endif /* ISKD */
  1819.         ckstrncpy( uidbuf, GetLocalUser(), UIDBUFLEN );
  1820.  
  1821. #ifdef NT
  1822. #ifdef BETADEBUG
  1823.     printf("Console Window Handle=0x%x\n",hwndConsole);
  1824.     printf("WM_GETFONT=0x%x\n",(ULONG)SendMessage(hwndConsole,WM_GETFONT,0,0));
  1825. #endif /* BETADEBUG */
  1826. #endif /* NT */
  1827.  
  1828. #ifdef OS2ONLY
  1829.     if (getenv ("TZ") == NULL)  /* Default New York time. */
  1830.     {
  1831.         printf("Warning: TZ environment variable not set.  Using EST5EDT.\n\n");
  1832.         bleep(BP_WARN);
  1833.         _timezone = 18000;
  1834.         _daylight = 1;
  1835.         _tzname[0] = "EST";
  1836.         _tzname[1] = "EDT";
  1837.     }
  1838.     else
  1839. #endif /* OS2ONLY */
  1840.         _tzset() ;
  1841.  
  1842. #ifdef NT
  1843.     if ( isWin95() ) {                  /* Check TMP,TEMP,K95TMP */
  1844.         char * p = NULL;
  1845.         int warning = 0;
  1846.  
  1847.         p = getenv("K95TMP");
  1848.         if ( p ) {
  1849.             if ( strlen(p) == 3 && p[1] == ':' && p[2] == '\\' ) {
  1850.                 printf("\n  WARNING: K95TMP = %s\n",p);
  1851.                 warning = 1;
  1852.             }
  1853.         }
  1854.         p = getenv("TEMP");
  1855.         if ( p ) {
  1856.             if ( strlen(p) == 3 && p[1] == ':' && p[2] == '\\' ) {
  1857.                 if ( !warning )
  1858.                     printf("\n");
  1859.                 printf("  WARNING: TEMP = %s\n",p);
  1860.                 warning = 1;
  1861.             }
  1862.         }
  1863.         p = getenv("TMP");
  1864.         if ( p ) {
  1865.             if ( strlen(p) == 3 && p[1] == ':' && p[2] == '\\' ) {
  1866.                 if ( !warning )
  1867.                     printf("\n");
  1868.                 printf("  WARNING: TMP = %s\n",p);
  1869.                 warning = 1;
  1870.             }
  1871.         }
  1872.         if ( warning ) {
  1873.             printf("  The directory for temporary files in Windows 95 must be a subdirectory\n");
  1874.             printf("  to avoid problems with Kerberos, Tapi, and other subsystems.\n\n");
  1875.             bleep(BP_WARN);
  1876.         }
  1877.     }
  1878.  
  1879.     /* Check to make sure we have the default directory heirarchy */
  1880.     if ( !inserver )
  1881.         firsttime();
  1882. #endif /* NT */
  1883.  
  1884. #ifndef NOLOCAL
  1885.     VscrnForceFullUpdate();             /* Just in case command screen did not write */
  1886. #endif /* NOLOCAL */
  1887.     SysInited = 1;
  1888.     debug(F100,"sysinit complete","",0);
  1889.  
  1890.     chkexp();
  1891.     return(0);
  1892. }
  1893.  
  1894. /*  S Y S C L E A N U P  --  System-dependent program cleanup.  */
  1895.  
  1896. int
  1897. syscleanup() {
  1898.     extern int printtimo;
  1899.  
  1900.     if (!SysInited)
  1901.       return(0);
  1902.  
  1903.     SysInited = 0;
  1904.  
  1905.     printtimo = 0;                      /* Turn off delayed print closure */
  1906.     printeroff();                       /* Close printer if open */
  1907.  
  1908. #ifdef NT
  1909. #ifdef NEWRDCH
  1910.     OverlappedReadCleanup();
  1911. #endif /* NEWRDCH */
  1912. #endif /* NT */
  1913.  
  1914. #ifdef COMMENt
  1915. #ifndef NOLOCAL
  1916.     StopConnectThreads(0);
  1917. #endif /* NOLOCAL */
  1918. #endif /* COMMENT */
  1919. #ifdef NT
  1920. #ifdef CK_TAPI
  1921.     if ( TAPIAvail ) {
  1922.         debug(F100,"Close TAPI starting","",0);
  1923.         cktapiclose();
  1924.         cktapiunload() ;
  1925.         debug(F100,"Close TAPI done","",0);
  1926.     }
  1927. #endif /* CK_TAPI */
  1928. #ifndef KUI
  1929.     WindowThreadClose();
  1930. #endif /* KUI */
  1931. #endif /* NT */
  1932.  
  1933. #ifdef KUI
  1934.     KuiThreadCleanup( (void *) hInstance ) ;
  1935. #endif /* KUI */
  1936. #ifdef CK_SECURITY
  1937.     ck_security_unloaddll();
  1938. #endif /* CK_SECURITY */
  1939. #ifdef NETCONN
  1940.     netcleanup() ;
  1941. #endif /* NETCONN */
  1942.     os2settitle(szOldTitle,FALSE);
  1943.     os2setcp(nOldCP);
  1944.  
  1945.     signal(SIGINT, SIG_DFL);
  1946.     signal(SIGBREAK, SIG_DFL);
  1947.     signal(SIGTERM, SIG_DFL);
  1948.  
  1949. #ifndef KUI
  1950. #ifndef NOLOCAL
  1951.     if ( !k95stdout ) {
  1952. #ifdef NT
  1953.         if ( StartupConsoleModeInfo.sbrow != VscrnGetHeight(VCMD) ||
  1954.              StartupConsoleModeInfo.sbcol != VscrnGetWidth(VCMD) ) {
  1955.             clearcmdscreen();
  1956.             SetMode( &StartupConsoleModeInfo );
  1957.         }
  1958. #else /* NT */
  1959.         if ( StartupConsoleModeInfo.row != VscrnGetHeight(VCMD) ||
  1960.              StartupConsoleModeInfo.col != VscrnGetWidth(VCMD) ) {
  1961.             clearcmdscreen();
  1962.             SetMode( &StartupConsoleModeInfo );
  1963.         }
  1964. #endif /* NT */
  1965.     }
  1966.     KbdHandlerCleanup() ;   /* must come after os2settitle */
  1967.     debug(F100,"KbdHandlerCleanup done","",0);
  1968.     if ( isWin95() )            /* Win95 needs time to let the kbdthread die */
  1969.         msleep(50);
  1970.  
  1971.     keybufcleanup() ;
  1972.     debug(F100,"keybufcleanup done","",0);
  1973. #endif /* NOLOCAL */
  1974.  
  1975.     le_clean();
  1976.  
  1977.     CloseAlarmMutex() ;
  1978. #ifndef NOLOCAL
  1979.     CloseScreenMutex() ;
  1980.     CloseVscrnMutex() ;
  1981.     CloseVscrnDirtyMutex() ;
  1982.     CloseConnectModeMutex() ;
  1983.     CloseCommandModeSem() ;
  1984.     CloseTerminalModeSem() ;
  1985. #endif /* NOLOCAL */
  1986.     CloseCommMutex();
  1987.     CloseThreadMgmtMutex();
  1988.     CloseDebugMutex() ;
  1989.     CloseTelnetMutex() ;
  1990.     CloseTCPIPMutex() ;
  1991.     CloseAlarmSem() ;
  1992. #ifdef CK_SSL
  1993.     CloseSSLMutex() ;
  1994. #endif /* CK_SSL */
  1995. #ifndef NOLOCAL
  1996.     CloseRdComWrtScrThreadSem() ;
  1997.     CloseConKbdHandlerThreadSem() ;
  1998.     CloseTermScrnUpdThreadSem() ;
  1999.     CloseRdComWrtScrThreadDownSem() ;
  2000.     CloseConKbdHandlerThreadDownSem() ;
  2001.     CloseTermScrnUpdThreadDownSem() ;
  2002.     CloseKeyMapInitSem() ;
  2003.     CloseVscrnDirtySem() ;
  2004. #endif /* NOLOCAL */
  2005. #endif /* KUI */
  2006. #ifdef NT
  2007.     CloseSerialMutex() ;
  2008.     if ( !stdout )
  2009.         CloseHandle(VioHandle);
  2010.     VioHandle = 0 ;
  2011. #endif /* NT */
  2012.     CloseThreadMgmtMutex() ;
  2013.     debug(F100,"Close Mutexes and Semaphores done","",0);
  2014.  
  2015. #ifndef NOLOCAL
  2016. #ifndef NT
  2017.     CloseClipboardServer() ;
  2018.     debug(F100,"Close Clipboard done","",0);
  2019. #endif /* NT */
  2020. #endif /* NOLOCAL */
  2021.  
  2022. #ifdef NTSIG
  2023.     TlsFree(TlsIndex);
  2024.     TlsIndex = 0;
  2025.     debug(F100,"Free Thread Local Memory done","",0);
  2026. #endif /* NTSIG */
  2027.  
  2028. #ifdef OS2ONLY
  2029.     WinTerminate(hab) ;
  2030.     DisconnectFromPM();
  2031. #endif /* OS2ONLY */
  2032.  
  2033. #ifdef CK_XYZ
  2034. #ifdef XYZ_DLL
  2035.    if ( p_avail )
  2036.       unload_p_dll() ;
  2037.     debug(F100,"Zmodem released","",0);
  2038. #endif /* XYZ_DLL */
  2039. #endif /* CK_XYZ */
  2040.     return(0);
  2041. }
  2042.  
  2043. /* Timeout handler for communication line input functions */
  2044.  
  2045. static ckjmpbuf kbbuf;                  /* Timeout longjmp targets */
  2046. static ckjmpbuf sjbuf;
  2047.  
  2048. #ifndef __EMX__
  2049. unsigned alarm(unsigned);               /* Prototype */
  2050. #endif /* __EMX__ */
  2051. #ifdef OS2
  2052. SIGTYP (* volatile saval)(int) = NULL;  /* For saving alarm() handler */
  2053. #else /* OS2 */
  2054. SIGTYP (*saval)(int) = NULL;            /* For saving alarm() handler */
  2055. #endif /* OS2 */
  2056.  
  2057. VOID
  2058. ttimoff() {                             /* Turn off any timer interrupts */
  2059.     int xx;
  2060.     xx = alarm(0);
  2061.     if (saval) {                        /* Restore any previous */
  2062.         signal(SIGALRM,saval);          /* alarm handler. */
  2063.         saval = NULL;
  2064.     } else {
  2065.         signal(SIGALRM,SIG_IGN);
  2066.     }
  2067. }
  2068.  
  2069.  
  2070. /* O S 2 S E T T I M O -- set read and write timeouts */
  2071.  
  2072. int
  2073. os2settimo(int spd, int modem)
  2074. {
  2075. #ifdef NT
  2076.     COMMTIMEOUTS timeouts ;
  2077. #endif /* NT */
  2078.  
  2079.     debug(F111,"os2settimo","spd",spd);
  2080.     debug(F111,"os2settimo","modem",modem);
  2081.  
  2082. #ifdef NT
  2083.     /* Calculate the max overlapeed writes for this connection */
  2084.     /* A rethinking of how this number is calculated.
  2085.      * The fastest modem connection is 53,000 bits per second (6625 bytes per second)
  2086.      * the largest kermit packet is 9024 bytes.  Therefore, we can never process more
  2087.      * than one write/second therefore it makes no sense for this value to be anything
  2088.      * but 2 for modems.  For non-modems, use bytes/sec/max-packet 
  2089.      */
  2090.     if ( modem > 0 )
  2091.         maxow = 2;
  2092.     else
  2093.         maxow = 1 + (spd / 8 / 9024) ;
  2094.  
  2095.     if ( maxow > maxow_usr )
  2096.         maxow = maxow_usr;
  2097.  
  2098. #ifdef CK_TAPI
  2099.     if ( tttapi && !tapipass ) {
  2100.         HANDLE hModem = NULL;
  2101.         LPDEVCFG        lpDevCfg = NULL;
  2102.         LPCOMMCONFIG    lpCommConfig = NULL;
  2103.         LPMODEMSETTINGS lpModemSettings = NULL;
  2104.         DCB *           lpDCB = NULL;
  2105.  
  2106.         hModem = GetModemHandleFromLine( (HLINE) 0 );
  2107.         if ( hModem == NULL )
  2108.             return(-1);
  2109.  
  2110.         if (!GetCommTimeouts( hModem, &timeouts ))
  2111.         {
  2112.             CloseHandle( hModem );
  2113.             return -1 ;
  2114.         }
  2115.  
  2116.         /* Timeouts for Overlapped I/O from MS TTY.C example */
  2117.         timeouts.ReadIntervalTimeout = MAXDWORD;
  2118.         timeouts.ReadTotalTimeoutMultiplier = MAXDWORD /* 0 */ ;
  2119.         timeouts.ReadTotalTimeoutConstant = 1 ;
  2120.         timeouts.WriteTotalTimeoutMultiplier = (modem > 0 ? 250 : (2500000 / spd));
  2121.         timeouts.WriteTotalTimeoutConstant =  (modem > 0 ? 90000 : 0);
  2122.  
  2123.         if (!SetCommTimeouts( hModem, &timeouts )) {
  2124.             CloseHandle( hModem );
  2125.             return -1 ;
  2126.         }
  2127.         CloseHandle(hModem);
  2128.         return(0);
  2129.     }
  2130. #endif /* CK_TAPI */
  2131.     if (!GetCommTimeouts( (HANDLE) ttyfd, &timeouts ))
  2132.         return -1 ;
  2133.  
  2134.     if ( deblog )
  2135.         debugComm( "os2settimo initial values", NULL, &timeouts );
  2136.  
  2137.     /* Timeouts for Overlapped I/O from MS TTY.C example */
  2138.     timeouts.ReadIntervalTimeout = MAXDWORD;
  2139.     timeouts.ReadTotalTimeoutMultiplier = MAXDWORD /* 0 */;
  2140.     timeouts.ReadTotalTimeoutConstant = 1  ;
  2141.     timeouts.WriteTotalTimeoutMultiplier = (modem > 0 ? 250 : (2500000 / spd));
  2142.     timeouts.WriteTotalTimeoutConstant =  (modem > 0 ? 90000 : 0);
  2143.  
  2144.     debug(F111,"os2settimo SetCommTimeouts","WriteTotalTimeoutMultiplier",
  2145.               timeouts.WriteTotalTimeoutMultiplier);
  2146.     debug(F111,"os2settimo SetCommTimeouts","WriteTotalTimeoutConstant",
  2147.               timeouts.WriteTotalTimeoutConstant);
  2148.     if (!SetCommTimeouts( (HANDLE) ttyfd, &timeouts ))
  2149.         return -1 ;
  2150. #else /* not NT */
  2151.     /* Get the current settings */
  2152.     if (DosDevIOCtl(&ttydcb,sizeof(ttydcb),NULL,0,
  2153.                      ASYNC_GETDCBINFO,IOCTL_ASYNC,ttyfd))
  2154.         return(-1);
  2155.  
  2156.     /* set write timeout */
  2157.     ttydcb.fbTimeout &= ~MODE_NO_WRITE_TIMEOUT;
  2158. #ifdef COMMENT
  2159.     ttydcb.usWriteTimeout = 15 * 100;   /* 15-second timeout */
  2160. #else
  2161.     ttydcb.usWriteTimeout = ((100 / spd) + 1) * MAXSP
  2162.         + (modem > 0 ? 60 * 100 : 0);
  2163. #endif /* COMMENT */
  2164.  
  2165.     /* Read "some" data from line mode */
  2166.     ttydcb.fbTimeout &= ~MODE_NOWAIT_READ_TIMEOUT;
  2167.     ttydcb.fbTimeout |= MODE_WAIT_READ_TIMEOUT;
  2168.  
  2169.     /* Set DCB */
  2170.     if (DosDevIOCtl(NULL,0,&ttydcb,sizeof(ttydcb),
  2171.                      ASYNC_SETDCBINFO,IOCTL_ASYNC,ttyfd))
  2172.         return(-1);
  2173. #endif /* NT */
  2174.     return(0);
  2175. }
  2176.  
  2177. /*  T T S E T F L O W -- set flow state of tty */
  2178.  
  2179. int
  2180. ttsetflow(int nflow) {
  2181. #ifdef NT
  2182.    DWORD mode ;
  2183. #endif /* NT */
  2184.  
  2185.     debug(F101,"setflow","",nflow) ;
  2186.  
  2187. #ifdef TN_COMPORT
  2188.     if (network)
  2189.         return(tnsetflow(nflow));
  2190. #endif /* TN_COMPORT */
  2191.  
  2192. #ifdef NT
  2193. #ifdef CK_TAPI
  2194.     if ( tttapi && !tapipass ) {
  2195.         HANDLE hModem = NULL;
  2196.         LPDEVCFG        lpDevCfg = NULL;
  2197.         LPCOMMCONFIG    lpCommConfig = NULL;
  2198.         LPMODEMSETTINGS lpModemSettings = NULL;
  2199.         DCB *           lpDCB = NULL;
  2200.  
  2201.         hModem = GetModemHandleFromLine( (HLINE) 0 );
  2202.         if ( hModem == NULL )
  2203.             return(-1);
  2204.  
  2205.         if (!cktapiGetModemSettings(&lpDevCfg,&lpModemSettings,
  2206.                                      &lpCommConfig,&lpDCB))
  2207.         {
  2208.             CloseHandle( hModem );
  2209.             return -1 ;
  2210.         }
  2211.  
  2212.         if ( deblog )
  2213.             debugComm( "ttsetflow initial values", lpDCB, NULL );
  2214.  
  2215.         lpDCB->fDsrSensitivity = FALSE ;
  2216.         lpDCB->fDtrControl = DTR_CONTROL_ENABLE ;
  2217.  
  2218.         switch(nflow) {
  2219.         case FLO_XONX:
  2220.             lpDCB->fOutX = TRUE ;
  2221.             lpDCB->fInX = TRUE ;
  2222.             lpDCB->fRtsControl = RTS_CONTROL_ENABLE ;
  2223.             lpDCB->fOutxCtsFlow = FALSE ;
  2224.             lpDCB->fTXContinueOnXoff = /* TRUE */ FALSE ;
  2225.             break;
  2226.         case FLO_RTSC:
  2227.             lpDCB->fOutX = FALSE ;
  2228.             lpDCB->fInX = FALSE ;
  2229.             lpDCB->fRtsControl = RTS_CONTROL_HANDSHAKE ;
  2230.             lpDCB->fOutxCtsFlow = TRUE ;
  2231.             lpDCB->fTXContinueOnXoff = TRUE ;
  2232.             break;
  2233.         case FLO_KEEP:
  2234.             /* leave things exactly as they are */
  2235.             break;
  2236.         case FLO_NONE:
  2237.             /* turn off all flow control completely */
  2238.             lpDCB->fOutX = FALSE ;
  2239.             lpDCB->fInX = FALSE ;
  2240.             lpDCB->fRtsControl = RTS_CONTROL_ENABLE ;
  2241.             lpDCB->fOutxCtsFlow = FALSE ;
  2242.             lpDCB->fTXContinueOnXoff = TRUE ;
  2243.             break;
  2244.         }
  2245.  
  2246.         lpDCB->XonChar = 0x11 ;
  2247.         lpDCB->XoffChar = 0x13;
  2248.         lpDCB->XonLim = 10 ;
  2249.         lpDCB->XoffLim = 10 ;
  2250.  
  2251.         if (!cktapiSetModemSettings(lpDevCfg,lpCommConfig)) {
  2252.             CloseHandle( hModem );
  2253.             return -1 ;
  2254.         }
  2255.  
  2256.         if ( lpDCB->fRtsControl != RTS_CONTROL_HANDSHAKE )
  2257.             EscapeCommFunction( hModem, SETRTS ) ;
  2258.  
  2259.         CloseHandle(hModem);
  2260.         return(0);
  2261.     }
  2262. #endif /* CK_TAPI */
  2263.     ttydcb.DCBlength = sizeof(DCB);
  2264.  
  2265.     if (!GetCommState( (HANDLE) ttyfd, &ttydcb ))
  2266.         return -1 ;
  2267.  
  2268.     if ( deblog )
  2269.         debugComm( "ttsetflow initial values", &ttydcb, NULL );
  2270.  
  2271.     ttydcb.fDsrSensitivity = FALSE ;
  2272.     ttydcb.fDtrControl = DTR_CONTROL_ENABLE ;
  2273.  
  2274.     switch(nflow) {
  2275.     case FLO_XONX:
  2276.         ttydcb.fOutX = TRUE ;
  2277.         ttydcb.fInX = TRUE ;
  2278.         ttydcb.fRtsControl = RTS_CONTROL_ENABLE ;
  2279.         ttydcb.fOutxCtsFlow = FALSE ;
  2280.         ttydcb.fTXContinueOnXoff = /* TRUE */ FALSE ;
  2281.         break;
  2282.     case FLO_RTSC:
  2283.         ttydcb.fOutX = FALSE ;
  2284.         ttydcb.fInX = FALSE ;
  2285.         ttydcb.fRtsControl = RTS_CONTROL_HANDSHAKE ;
  2286.         ttydcb.fOutxCtsFlow = TRUE ;
  2287.         ttydcb.fTXContinueOnXoff = TRUE ;
  2288.         break;
  2289.     case FLO_KEEP:
  2290.         /* leave things exactly as they are */
  2291.         break;
  2292.     case FLO_NONE:
  2293.         /* turn off all flow control completely */
  2294.         ttydcb.fOutX = FALSE ;
  2295.         ttydcb.fInX = FALSE ;
  2296.         ttydcb.fRtsControl = RTS_CONTROL_ENABLE ;
  2297.         ttydcb.fOutxCtsFlow = FALSE ;
  2298.         ttydcb.fTXContinueOnXoff = TRUE ;
  2299.         break;
  2300.     }
  2301.  
  2302.     ttydcb.XonChar = 0x11 ;
  2303.     ttydcb.XoffChar = 0x13;
  2304.     ttydcb.XonLim = 10 ;
  2305.     ttydcb.XoffLim = 10 ;
  2306.  
  2307.     if (!SetCommState( (HANDLE) ttyfd, &ttydcb ))
  2308.         return -1 ;
  2309.  
  2310.     if ( ttydcb.fRtsControl != RTS_CONTROL_HANDSHAKE )
  2311.         EscapeCommFunction( (HANDLE) ttyfd, SETRTS ) ;
  2312. #else /* not NT */
  2313.     /* Get the current settings */
  2314.     if (DosDevIOCtl(&ttydcb,sizeof(ttydcb),NULL,0,
  2315.                      ASYNC_GETDCBINFO,IOCTL_ASYNC,ttyfd))
  2316.         return(-1);
  2317.  
  2318.     ttydcb.fbCtlHndShake = MODE_DTR_CONTROL;
  2319.     ttydcb.fbFlowReplace &= ~(MODE_AUTO_RECEIVE | MODE_AUTO_TRANSMIT |
  2320.     /* clear only a few */    MODE_RTS_CONTROL  | MODE_RTS_HANDSHAKE);
  2321.  
  2322.     if (nflow == FLO_XONX) {
  2323.         ttydcb.fbFlowReplace |=
  2324.             (MODE_AUTO_RECEIVE | MODE_AUTO_TRANSMIT | MODE_RTS_CONTROL);
  2325.     }
  2326.     else if (nflow == FLO_RTSC) {
  2327.         ttydcb.fbCtlHndShake |= MODE_CTS_HANDSHAKE;
  2328.         ttydcb.fbFlowReplace |= MODE_RTS_HANDSHAKE;
  2329.     }
  2330.     else if ( nflow != FLO_KEEP ) {
  2331.         ttydcb.fbFlowReplace |= MODE_RTS_CONTROL;
  2332.     }
  2333.  
  2334.     /* Set DCB */
  2335.     if (DosDevIOCtl(NULL,0,&ttydcb,sizeof(ttydcb),
  2336.                      ASYNC_SETDCBINFO,IOCTL_ASYNC,ttyfd))
  2337.         return(-1);
  2338.  
  2339.     if (nflow != FLO_RTSC && nflow != FLO_KEEP) {/* keep RTS permanently on */
  2340.         MODEMSTATUS ms;
  2341.         UINT data;
  2342.         ms.fbModemOn = RTS_ON;
  2343.         ms.fbModemOff = 255;
  2344.         DosDevIOCtl(&data,sizeof(data),&ms,sizeof(ms),
  2345.                     ASYNC_SETMODEMCTRL,IOCTL_ASYNC,ttyfd);
  2346.     }
  2347. #endif /* NT */
  2348.     return(0);
  2349. }
  2350.  
  2351. static int
  2352. os2setcarr(int ncarr) {
  2353.     debug(F101,"setcarr","",ncarr) ;
  2354. #ifdef NT
  2355. #ifdef COMMENT
  2356.     ttydcb.DCBlength = sizeof(DCB);
  2357.     if (!GetCommState( (HANDLE) ttyfd, &ttydcb ))
  2358.         return -1 ;
  2359.  
  2360.     if ( deblog )
  2361.         debugComm( "os2setcarr initial values", &ttydcb, NULL );
  2362.  
  2363.    if (!SetCommState( (HANDLE) ttyfd, &ttydcb ))
  2364.         return -1 ;
  2365. #endif /* COMMENT */
  2366. #else /* not NT */
  2367.     /* Get the current settings */
  2368.     if (DosDevIOCtl(&ttydcb,sizeof(ttydcb),NULL,0,
  2369.                     ASYNC_GETDCBINFO,IOCTL_ASYNC,ttyfd))
  2370.         return(-1);
  2371.  
  2372.     if (ncarr)
  2373.       ttydcb.fbCtlHndShake |=  MODE_DCD_HANDSHAKE;
  2374.     else
  2375.       ttydcb.fbCtlHndShake &= ~MODE_DCD_HANDSHAKE;
  2376.  
  2377.     /* Set DCB */
  2378.     if (DosDevIOCtl(NULL,0,&ttydcb,sizeof(ttydcb),
  2379.                     ASYNC_SETDCBINFO,IOCTL_ASYNC,ttyfd))
  2380.         return(-1);
  2381. #endif
  2382.     return(0);
  2383. }
  2384.  
  2385.  
  2386. /*  O S 2 S E T D T R -- set state of DTR signal */
  2387.  
  2388. static int
  2389. os2setdtr(int on) {
  2390. #ifdef NT
  2391.    DWORD mode = 0;
  2392. #else /* NT */
  2393.     MODEMSTATUS ms;
  2394.     UINT data;
  2395. #endif /* NT */
  2396.  
  2397.     debug(F101,"setdtr","",on);
  2398.  
  2399.     if (ttyfd == -1
  2400. #ifdef CK_TAPI
  2401.          || (tttapi && ttyfd == -2)
  2402. #endif /* CK_TAPI */
  2403.          )
  2404.         return(0);
  2405.  
  2406. #ifdef TN_COMPORT
  2407.     if (network) {
  2408.         if (istncomport()) {
  2409.             return(tnc_set_dtr_state(on));
  2410.         } else
  2411.             return(-1);
  2412.     }
  2413. #endif /* TN_COMPORT */
  2414.  
  2415. #ifdef NT
  2416. #ifdef CK_TAPI
  2417.     if ( tttapi && !tapipass )
  2418.     {
  2419.         HANDLE hModem = NULL;
  2420.  
  2421.         hModem = GetModemHandleFromLine( (HLINE) 0 );
  2422.         if ( hModem == NULL )
  2423.             return(-1);
  2424.  
  2425.         mode = on ? SETDTR : CLRDTR ;
  2426.         if (!EscapeCommFunction( hModem, mode ))
  2427.         {
  2428.             int error = GetLastError() ;
  2429.             debug(F101,"os2setdtr EscapeCommFunction failed","",error) ;
  2430.             CloseHandle( hModem );
  2431.             return -1 ;
  2432.         }
  2433.  
  2434.         CloseHandle( hModem );
  2435.         return(0);
  2436.     }
  2437. #endif /* CK_TAPI */
  2438.  
  2439.    mode = on ? SETDTR : CLRDTR ;
  2440.    if (!EscapeCommFunction( (HANDLE) ttyfd, mode ))
  2441.    {
  2442.       int error = GetLastError() ;
  2443.       debug(F101,"os2setdtr EscapeCommFunction failed","",error) ;
  2444.       return -1 ;
  2445.    }
  2446.    return 0;
  2447. #else /* NT */
  2448.     ms.fbModemOn = on ? DTR_ON : 0;
  2449.     ms.fbModemOff = on ? 255 : DTR_OFF;
  2450.     return(DosDevIOCtl(&data,sizeof(data),&ms,sizeof(ms),
  2451.                        ASYNC_SETMODEMCTRL,IOCTL_ASYNC,ttyfd));
  2452. #endif
  2453. }
  2454.  
  2455.  
  2456. /*  T T S E T T I N G S  --  Set the device driver parity and stop bits */
  2457.  
  2458. static int
  2459. ttsettings(int par, int stop) {
  2460. #ifdef OS2ONLY
  2461.     LINECONTROL lc;
  2462. #endif /* OS2ONLY */
  2463.  
  2464. #ifdef TN_COMPORT
  2465.     if (network)
  2466.         return(tnsettings(par,stop));
  2467. #endif /* TN_COMPORT */
  2468.  
  2469. #ifdef NT
  2470. #ifdef CK_TAPI
  2471.     if ( tttapi && !tapipass )
  2472.     {
  2473.         HANDLE hModem = NULL;
  2474.         LPDEVCFG        lpDevCfg = NULL;
  2475.         LPCOMMCONFIG    lpCommConfig = NULL;
  2476.         LPMODEMSETTINGS lpModemSettings = NULL;
  2477.         DCB *           lpDCB = NULL;
  2478.  
  2479.         hModem = GetModemHandleFromLine( (HLINE) 0 );
  2480.         if ( hModem == NULL )
  2481.             return(-1);
  2482.  
  2483.         if (!cktapiGetModemSettings(&lpDevCfg,&lpModemSettings,
  2484.                                      &lpCommConfig,&lpDCB)) {
  2485.             CloseHandle( hModem );
  2486.             return -1 ;
  2487.         }
  2488.  
  2489.         lpDCB->fBinary = TRUE ;
  2490.         lpDCB->fErrorChar = FALSE ;
  2491.         lpDCB->fAbortOnError = FALSE ;
  2492.         lpDCB->ErrorChar = '?' ;
  2493.  
  2494.         if (hwparity) {
  2495.             switch (hwparity) {
  2496.             case 'e':
  2497.                 lpDCB->Parity = EVENPARITY ;
  2498.                 break;
  2499.             case 'o':
  2500.                 lpDCB->Parity = ODDPARITY ;
  2501.                 break;
  2502.             case 'm':
  2503.                 lpDCB->Parity = MARKPARITY ;
  2504.                 break;
  2505.             case 's':
  2506.                 lpDCB->Parity = SPACEPARITY ;
  2507.                 break;
  2508.             default:
  2509.                 lpDCB->Parity = NOPARITY ;
  2510.             }
  2511.             lpDCB->fParity = TRUE;
  2512.             lpDCB->ByteSize = 8;
  2513.             ttprty = 0;
  2514.         } else {
  2515.             lpDCB->Parity = NOPARITY;
  2516.             lpDCB->fParity = FALSE;
  2517.             lpDCB->ByteSize = 8;
  2518.             ttprty = par;
  2519.         }
  2520.  
  2521.         switch(stop) {
  2522.         case 2:
  2523.             lpDCB->StopBits = TWOSTOPBITS ;
  2524.             break;
  2525.         case 1:
  2526.             lpDCB->StopBits = ONESTOPBIT ;
  2527.             break;
  2528.         default:
  2529.             ; /* no change */
  2530.         }
  2531.  
  2532.         if (!cktapiSetModemSettings(lpDevCfg,lpCommConfig))  {
  2533.             CloseHandle( hModem );
  2534.             return -1 ;
  2535.         }
  2536.  
  2537.         CloseHandle( hModem );
  2538.         return (0);
  2539.     }
  2540. #endif /* CK_TAPI */
  2541.  
  2542.     ttydcb.DCBlength = sizeof(DCB);
  2543.     if (!GetCommState( (HANDLE) ttyfd, &ttydcb ))
  2544.         return -1 ;
  2545.  
  2546.  
  2547.     if ( deblog )
  2548.         debugComm( "ttsettings initial values", &ttydcb, NULL );
  2549.  
  2550.     ttydcb.fBinary = TRUE ;
  2551.     ttydcb.fErrorChar = FALSE ;
  2552.     ttydcb.fAbortOnError = FALSE ;
  2553.     ttydcb.ErrorChar = '?' ;
  2554.  
  2555.     if (hwparity) {
  2556.         switch (hwparity) {
  2557.         case 'e':
  2558.             ttydcb.Parity = EVENPARITY ;
  2559.             break;
  2560.         case 'o':
  2561.             ttydcb.Parity = ODDPARITY ;
  2562.             break;
  2563.         case 'm':
  2564.             ttydcb.Parity = MARKPARITY ;
  2565.             break;
  2566.         case 's':
  2567.             ttydcb.Parity = SPACEPARITY ;
  2568.             break;
  2569.         default:
  2570.             ttydcb.Parity = NOPARITY ;
  2571.         }
  2572.         ttydcb.fParity = TRUE;
  2573.         ttydcb.ByteSize = 8;
  2574.         ttprty = 0;
  2575.     } else {
  2576.         ttydcb.Parity = NOPARITY;
  2577.         ttydcb.fParity = FALSE;
  2578.         ttydcb.ByteSize = 8;
  2579.         ttprty = par;
  2580.     }
  2581.  
  2582.     switch(stop) {
  2583.     case 2:
  2584.         ttydcb.StopBits = TWOSTOPBITS ;
  2585.         break;
  2586.     case 1:
  2587.         ttydcb.StopBits = ONESTOPBIT ;
  2588.         break;
  2589.     default:
  2590.         ; /* no change */
  2591.     }
  2592.  
  2593.     if (!SetCommState( (HANDLE) ttyfd, &ttydcb ))
  2594.         return -1 ;
  2595.  
  2596. #else /* NT */
  2597.     if (DosDevIOCtl(&lc,sizeof(lc),NULL,0,
  2598.                     ASYNC_GETLINECTRL,IOCTL_ASYNC,ttyfd))
  2599.       return(-1); /* Get line */
  2600.  
  2601. #ifdef HWPARITY
  2602.     if (hwparity) {
  2603.         switch (hwparity) {
  2604.         case 'o':
  2605.             lc.bDataBits = 8;   /* Data bits */
  2606.             lc.bParity   = 1;
  2607.             break;
  2608.         case 'e':
  2609.             lc.bDataBits = 8;   /* Data bits */
  2610.             lc.bParity   = 2;
  2611.             break;
  2612.         case 'm':
  2613.             lc.bDataBits = 8;   /* Data bits */
  2614.             lc.bParity   = 3;
  2615.             break;
  2616.         case 's':
  2617.             lc.bDataBits = 8;   /* Data bits */
  2618.             lc.bParity   = 4;
  2619.             break;
  2620.         default :
  2621.             lc.bDataBits = 8;   /* Data bits */
  2622.             lc.bParity   = 0;   /* No parity */
  2623.         }
  2624.         ttprty = 0;
  2625.     } else
  2626. #endif /* HWPARITY */
  2627.     {
  2628.         /* Always let Kermit handle parity itself */
  2629.         lc.bDataBits = 8;   /* Data bits */
  2630.         lc.bParity   = 0;   /* No parity */
  2631.         ttprty = par;
  2632.     }
  2633.     switch (stop) {
  2634.         case 2:
  2635.             lc.bStopBits = 2;   /* Two stop bits */
  2636.             break;
  2637.         case 1:
  2638.             lc.bStopBits = 0;   /* One stop bit */
  2639.             break;
  2640.         default:                /* No change */
  2641.             break;
  2642.     }
  2643.     if (DosDevIOCtl(NULL,0,&lc,sizeof(lc),
  2644.                     ASYNC_SETLINECTRL,IOCTL_ASYNC,ttyfd))
  2645.       return(-1); /* Set line */
  2646. #endif /* NT */
  2647.     return(0);
  2648. }
  2649.  
  2650. void
  2651. ttname2title(char * ttname)
  2652. {                                       /* Set session title */
  2653.     char * p, name[72];                 /* in window list. */
  2654.     p = name ;
  2655.     ckstrncpy(name, ttname, 72);
  2656.     while (*p) {                        /* Uppercase it for emphasis. */
  2657.         if (islower(*p))
  2658.           *p = toupper(*p);
  2659.         p++;
  2660.     }
  2661.     os2settitle((char *) name, 1);
  2662. }
  2663.  
  2664. /*  T T O P E N  --  Open a tty for exclusive access.  */
  2665.  
  2666. /*  Returns 0 on success, -1 on failure.  */
  2667. /*
  2668.   If called with lcl < 0, sets value of lcl as follows:
  2669.   0: the terminal named by ttname is the job's controlling terminal.
  2670.   1: the terminal named by ttname is not the job's controlling terminal.
  2671.   But watch out: if a line is already open, or if requested line can't
  2672.   be opened, then lcl remains (and is returned as) -1.
  2673. */
  2674. ttopen(char *ttname, int *lcl, int modem, int spare) {
  2675.     char *x;
  2676.     extern char* ttyname();
  2677.     int rc=0 ;
  2678.     U_INT action, res;
  2679. #ifdef NT
  2680.     int i ;
  2681.     SECURITY_ATTRIBUTES security ;
  2682.     char portname[267];
  2683. #endif
  2684.  
  2685.     debug(F111,"ttopen DEVNAMLEN","",DEVNAMLEN);
  2686.     debug(F111,"ttopen entry modem",ttname,modem);
  2687.     debug(F101,"ttopen ttyfd","",ttyfd);
  2688.     debug(F111,"ttopen ttnmsv",ttnmsv,(int) strlen(ttnmsv));
  2689.     debug(F111,"ttopen ttname",ttname,(int) strlen(ttname));
  2690.  
  2691.     rdchbuf.length = rdchbuf.index = 0;
  2692.  
  2693.     if (ttyfd != -1
  2694. #ifdef COMMENT
  2695. #ifdef CK_TAPI
  2696.          && ttyfd != -2
  2697. #endif /* CK_TAPI */
  2698. #endif /* COMMENT */
  2699.          ) {                            /* if device already opened */
  2700.        if ((ttname[0] == '_' ||
  2701.              ttname[0] == '$' ||
  2702.              ttname[0] == '!')
  2703.             && ttyfd == atoi(&ttname[1]))
  2704.            return(0);
  2705.  
  2706. #ifdef NT
  2707.         /* Support for Pragma Systems Telnet/Terminal Servers */
  2708.         if (!strcmp(ttname,"0")) {
  2709.             char * p = getenv("PRAGMASYS_INETD_SOCK");
  2710.             if ( p && ttyfd == atoi(p))
  2711.                 return(0);
  2712.         }
  2713. #endif /* NT */
  2714.  
  2715.        if ( strncmp(ttname,ttnmsv,DEVNAMLEN) ) { /* new & old names equal? */
  2716.            debug(F111,"ttopen closing",ttname,ttyfd);
  2717.            ttclos(0);                   /* no, close old ttname, open new */
  2718.        } else {                         /* else same, ignore this call, */
  2719.            debug(F111,"ttopen already open",ttname,ttyfd);
  2720.            ttname2title(ttname);
  2721.  
  2722.            /* This next line is a work around in case 'local' gets set   */
  2723.            /* somehow to remote mode which will result in file transfers */
  2724.            /* failing. */
  2725.            if (*lcl == -1) {
  2726. #ifdef IKSD
  2727.                if ( inserver )
  2728.                    *lcl = 0;
  2729.                else
  2730. #endif /* IKSD */
  2731.                *lcl = 1;                /* we can't open in remote mode */
  2732.            }
  2733.            return(0);                   /* and return. */
  2734.        }
  2735.     }
  2736.  
  2737.  
  2738.     wasclosed = 0;
  2739.     ishandle = 0;
  2740.     ttmdm = modem;                      /* Make this available to other fns */
  2741.  
  2742.     /* We need to catch the sequence of commands:
  2743.      *   set net type ...
  2744.      *   set host ...
  2745.      *   set modem type ...
  2746.      *
  2747.      * since that will reset the 'modem' variable to a positive
  2748.      * value.
  2749.      */
  2750.     if (network && ckstrcmp(ttname,ttnmsv,-1,0) || modem < 0) {
  2751.         network = 1;
  2752.     } else {
  2753.         network = 0;
  2754.     }
  2755.     tt_mode = TT_MODE_NONE;
  2756.  
  2757. #ifdef NT
  2758.     /* Support for Pragma Systems Telnet/Terminal Servers */
  2759.     if ( !strcmp(ttname,"0") )
  2760.     {
  2761.         char * p = getenv("PRAGMASYS_INETD_SOCK");
  2762.         if ( p ) {
  2763.             /* We are running under PragmaSys Telnetd/Inetd */
  2764.             extern int reliable;
  2765.             debug(F110,"PRAGMASYS_INETD_SOCK",p,0);
  2766.             ckstrncpy(ttnmsv, ttname, DEVNAMLEN); /* Keep copy of name locally. */
  2767.             ttyfd = atoi(p);
  2768.             if ( p = getenv("PRAGMASYS_COMPORT") ) {
  2769.                 /* 
  2770.                  * The PragaSys sample code puts a DuplicateHandle here
  2771.                  */
  2772.                 debug(F110,"PRAGMASYS_COMPORT",p,0);
  2773.                 network = 0;
  2774.                 reliable = 0;
  2775.             } else {
  2776.                 network = 1;
  2777.                 nettype = NET_TCPB;
  2778.                 ttnproto = NP_TELNET;
  2779.                 reliable = 1;
  2780.             }
  2781.             *lcl = 0;
  2782.             return(0);
  2783.         }
  2784.     }
  2785. #endif /* NT */
  2786.  
  2787. #ifndef NOTERM
  2788.     doreset(1);         /* Soft Reset the terminal - clrscreen && home cursor */
  2789. #endif /* NOTERM */
  2790.  
  2791. #ifdef SESLIMIT
  2792.     start_time = time( NULL ) ;
  2793.     warn[0] = warn[1] = warn[2] = warn[3] = 1;
  2794. #endif /* SESLIMIT */
  2795.  
  2796. #ifdef NETCONN
  2797. #ifdef TCPSOCKET
  2798.     {
  2799.         extern int tcpsrv_fd;
  2800.         if ( tcpsrv_fd != -1 && ttname[0] != '*')
  2801.             tcpsrv_close();
  2802.     }
  2803. #endif /* TCPSOCKET */
  2804.     if (network) {
  2805.         debug(F100,"ttopen calling os2_netflui()","",0);
  2806.         os2_netflui();
  2807.         debug(F100,"ttopen calling os2_netopen()","",0);
  2808.         rc = os2_netopen(ttname, lcl, modem < 0 ? -modem : modem);
  2809.         debug(F111,"ttname changed to",ttname,(int) strlen(ttname));
  2810.         if (!rc) {
  2811.             ckstrncpy(ttnmsv, ttname, DEVNAMLEN);   /* Keep copy of name locally. */
  2812.             ttname2title(ttname);
  2813.         }
  2814.     }
  2815.     else
  2816. #endif /* NETCONN */
  2817.     {
  2818. #ifdef CK_TAPI
  2819.     if ( tttapi )  /* We are trying to open a TAPI Line Device */
  2820.     {
  2821.         rc = tapi_open(ttname) ;
  2822.         debug(F111,"tapi_open rc",ttname,rc);
  2823.         ckstrncpy(ttnmsv, ttname, DEVNAMLEN );
  2824.         if (!rc) {
  2825.             *lcl = 1;                   /* Assume it's local. */
  2826. #ifdef COMMENT
  2827.             /* ttmdm is now set in tapi_open() */
  2828.             if (!tapipass)
  2829.                 ttmdm = 38;             /* ckudia.c */
  2830. #endif /* COMMENT */
  2831.         }
  2832.     }
  2833.     else
  2834. #endif /* CK_TAPI */
  2835.     {
  2836.         /*
  2837.         This code lets you give Kermit an open file descriptor for a serial
  2838.         communication device, rather than a device name.  Kermit assumes that the
  2839.         line is already open, conditioned with the right parameters, etc.
  2840.         */
  2841.         for (x = ttname; isdigit(*x); x++) ; /* Check for all digits */
  2842.  
  2843.         if (*x == '\0') {
  2844.             ttyfd = atoi(ttname);
  2845.             ishandle = 1;
  2846.             exithangup = 0;  /* Do not close on exit */
  2847.             *lcl = 1;                   /* Assume it's local. */
  2848.             if (ttiscom(ttyfd))
  2849.             {
  2850.                 rc = savetty();
  2851.                 if ( !rc )
  2852.                     ttname2title(ttname);
  2853.                 return rc;
  2854.             }
  2855.             ttyfd = -1;
  2856.             wasclosed = 1;
  2857.             return(-4);
  2858.         }
  2859.  
  2860. #ifdef NT
  2861.         memset(&security, 0, sizeof(SECURITY_ATTRIBUTES));
  2862.         security.nLength = sizeof(SECURITY_ATTRIBUTES);
  2863.         security.lpSecurityDescriptor = NULL ;
  2864.         security.bInheritHandle = TRUE ;
  2865.  
  2866.         /*
  2867.          * If DOS device names terminate with backslash on Windows 95/98
  2868.          * K95 will crash.
  2869.          */
  2870.         if ( isWin95() &&
  2871.              (!ckstrcmp(ttname,"lpt",3,0) ||
  2872.               !ckstrcmp(ttname,"com",3,0) ||
  2873.               !ckstrcmp(ttname,"prn",3,0)) ) {
  2874.             while ( ttname[strlen(ttname)-1] == '\\' )
  2875.                 ttname[strlen(ttname)-1] = '\0';
  2876.         }
  2877.  
  2878.         if ( ttname[0] == '\\' || ttname[strlen(ttname)-1] == '$' )
  2879.             ckstrncpy(portname,ttname,267);
  2880.         else {
  2881.             strcpy(portname,"\\\\.\\");
  2882.             ckstrncpy(&portname[4],ttname,263);
  2883.         }
  2884.         if ( (HANDLE)(ttyfd =
  2885.                        (int) CreateFile(portname,
  2886.                                          GENERIC_READ | GENERIC_WRITE,
  2887.                                          ttshare ? (FILE_SHARE_READ | FILE_SHARE_WRITE) : 0,
  2888.                                          &security,
  2889.                                          OPEN_EXISTING,
  2890.                                          FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
  2891.                                          NULL)) == INVALID_HANDLE_VALUE) {
  2892.             debug(F111,"ttopen CreateFile","GetLastError",GetLastError());
  2893.             ttyfd = -1 ;
  2894.             wasclosed = 1;
  2895.             return -1 ;
  2896.         }
  2897. #else /* not NT */
  2898.         if (ttslip) {
  2899.             rc = SlipOpen( ttname ) ;
  2900.             if ( rc ) {
  2901.                 PPPSlipClose() ;
  2902.                 ttyfd = -1 ;
  2903.                 wasclosed = 1;
  2904.                 return -6 ;
  2905.             }
  2906.         }
  2907.         else if ( ttppp ) {
  2908.             rc = PPPOpen( ttname ) ;
  2909.             if ( rc ) {
  2910.                 PPPSlipClose() ;
  2911.                 ttyfd = -1 ;
  2912.                 wasclosed = 1;
  2913.                 return -6 ;
  2914.             }
  2915.         }
  2916.  
  2917.         if (res = DosOpen(ttname,(PHFILE)&ttyfd,&action,0L,0,FILE_OPEN,
  2918.                            OPEN_ACCESS_READWRITE |
  2919.                            ( (ttshare || ttppp || ttslip) ? OPEN_SHARE_DENYNONE : OPEN_SHARE_DENYREADWRITE) |
  2920.                            OPEN_FLAGS_FAIL_ON_ERROR ,0L)) {
  2921.             debug(F111,"ttopen DosOpen","res",res);
  2922.             if (ttslip)
  2923.                 PPPSlipClose() ;
  2924.             ttyfd = -1;
  2925.             wasclosed = 1;
  2926.             return((res == ERROR_SHARING_VIOLATION) ? -5 : -1);
  2927.         }
  2928. #endif /* NT */
  2929.         ckstrncpy(ttnmsv, ttname, DEVNAMLEN );
  2930.     }
  2931.     debug(F111,"ttopen ok",ttname,*lcl);
  2932.  
  2933.     /* Caller wants us to figure out if line is controlling tty */
  2934.     if (*lcl == -1) {
  2935.         *lcl = 1;                       /* Can never transfer with console */
  2936.     }
  2937.     if (*lcl) {
  2938.         if (!ttiscom(ttyfd)) {          /* Not a serial port */
  2939.             ttclos(0);
  2940.             return(-4);
  2941.         }
  2942.  
  2943. #ifdef NT
  2944. #ifdef BETADEBUG
  2945.         DisplayCommProperties((HANDLE)ttyfd);
  2946. #endif /* BETADEBUG */
  2947.         SetCommMask( (HANDLE) ttyfd, EV_RXCHAR ) ;
  2948.         SetupComm( (HANDLE) ttyfd, 20000, 20000 ) ;
  2949.         PurgeComm( (HANDLE) ttyfd,
  2950.                    PURGE_RXABORT | PURGE_TXABORT |
  2951.                    PURGE_RXCLEAR | PURGE_TXCLEAR );
  2952. #endif /* NT */
  2953.         savetty();
  2954.         ttprty = dfprty;                        /* Make parity the default parity */
  2955.         if (ttsettings(ttprty,stopbits))
  2956.             return(-1);
  2957.         rc = ttflui();
  2958.  
  2959. #ifdef NT
  2960. #ifdef NEWRDCH
  2961.         /* Reset the Overlapped I/O structures */
  2962.         OverlappedWriteInit();
  2963.         OverlappedReadInit();
  2964. #endif
  2965. #endif
  2966.     }
  2967.     }
  2968.  
  2969.     if ( !rc )
  2970.         ttname2title(ttname);
  2971.  
  2972.     return rc;
  2973. }
  2974.  
  2975. /*  T T I S C O M  --  Is the given handle an open COM port? */
  2976.  
  2977. ttiscom(int f) {
  2978. #ifdef NT
  2979.     DCB testdcb;
  2980. #else /* NT */
  2981.     DCBINFO testdcb;
  2982. #endif /* NT */
  2983. #ifdef COMMENT
  2984. #ifdef TN_COMPORT
  2985.     /* TELNET REMOTE COM PORT option means we are a com port */
  2986.     if (istncomport())
  2987.         return(1);
  2988. #endif /* TN_COMPORT */
  2989. #endif /* COMMENT */
  2990. #ifdef NT
  2991. #ifdef CK_TAPI
  2992.     if ( tttapi && !tapipass )
  2993.     {
  2994.         HANDLE hModem = NULL;
  2995.  
  2996.         hModem = GetModemHandleFromLine( (HLINE) 0 );
  2997.         if ( hModem == NULL )
  2998.             return(0);
  2999.  
  3000.         memset( ttycfg, 0, 1024 );
  3001.         ttycfg->dwSize = 1024;
  3002.         cfgsize = 1024;
  3003.  
  3004.         if (!GetCommConfig( hModem, ttycfg, &cfgsize )) {
  3005.             CloseHandle(hModem);
  3006.             return 0 ;
  3007.         }
  3008.         CloseHandle( hModem );
  3009.         return (1);
  3010.     }
  3011. #endif /* CK_TAPI */
  3012.  
  3013.     testdcb.DCBlength = sizeof(DCB);
  3014.     if (!GetCommState( (HANDLE) ttyfd, &testdcb))
  3015.         return(0);
  3016. #else /* NT */
  3017.     /* Read DCB */
  3018.     if (DosDevIOCtl(&testdcb,sizeof(testdcb),NULL,0,
  3019.                     ASYNC_GETDCBINFO,IOCTL_ASYNC,f)) {
  3020.         return( 0 );                    /* Bad, not a serial port */
  3021.     }
  3022. #endif /* NT */
  3023.     return( 1 );                        /* Good */
  3024. }
  3025.  
  3026. /*  T T C L O S  --  Close the TTY.  */
  3027.  
  3028. ttclos(int spare) {
  3029.     int rc = 0;
  3030.  
  3031.     if (ttyfd == -1
  3032. #ifdef CK_TAPI
  3033.          || (!tttapi && ttyfd == -2)
  3034. #endif /* CK_TAPI */
  3035.          ) return(0);           /* Wasn't open. */
  3036.  
  3037. #ifdef NT
  3038.     /* Support for Pragma Systems Telnet/Terminal Servers */
  3039.     {
  3040.         char * p = getenv("PRAGMASYS_INETD_SOCK");
  3041.         if ( p && ttyfd == atoi(p)) {
  3042.             /* We are running under PragmaSys Telnetd/Inetd */
  3043.             ttyfd = -1;
  3044.             wasclosed = 1;
  3045.             return(0);
  3046.         }
  3047.     }
  3048. #endif /* NT */
  3049.  
  3050.     os2settitle("",TRUE);
  3051.  
  3052. #ifdef NETCONN
  3053.     if (network) {
  3054.         rc = os2_netclos();
  3055.     }
  3056.     else
  3057. #endif /* NETCONN */
  3058. #ifdef CK_TAPI
  3059.     if ( tttapi ) /* Closing a TAPI Line Device */
  3060.     {
  3061.         rc = tapi_clos();
  3062.     }
  3063.     else
  3064. #endif /* CK_TAPI */
  3065.     {
  3066.         if (savedtty
  3067. #ifdef OS2ONLY
  3068.             && !ttslip && !ttppp        /* Restoring the line has a tendancy */
  3069.                                         /* to drop DTR, which hangs up the   */
  3070.                                         /* connection, not a good thing      */
  3071. #endif /* OS2ONLY */
  3072.             )
  3073.            restoretty();
  3074.         if (!ishandle) {
  3075. #ifdef NT
  3076.            CloseHandle( (HANDLE) ttyfd ) ;
  3077. #else /* NT */
  3078.            DosClose(ttyfd);
  3079. #endif /* NT */
  3080.         }
  3081.         ishandle = 0;
  3082.         ttyfd = -1;
  3083.         wasclosed = 1;
  3084.         savedtty = 0 ;
  3085.  
  3086. #ifndef NT
  3087.         PPPSlipClose() ;
  3088. #endif /* NT */
  3089.     }
  3090.     return(rc);
  3091. }
  3092.  
  3093. /*  T T G S P D  --  return speed of COM port, or of default line */
  3094.  
  3095. long
  3096. ttgspd() {
  3097. #ifndef NT
  3098.     long sp = 0;
  3099.     struct {
  3100.       long current_rate;
  3101.       char current_fract;
  3102.       long minimum_rate;
  3103.       char minimum_fract;
  3104.       long maximum_rate;
  3105.       char maximum_fract;
  3106.     } speed;
  3107. #endif /* NT */
  3108.  
  3109.     if (ttyfd == -1
  3110. #ifdef CK_TAPI
  3111.          || (!tttapi && ttyfd == -2)
  3112. #endif /* CK_TAPI */
  3113.          )
  3114.         return -1 ;
  3115. #ifdef TN_COMPORT
  3116.     if ( network) {
  3117.         if (istncomport()) {
  3118.             return(tnc_get_baud());
  3119.         } else
  3120.             return(-1);
  3121.     }
  3122. #endif /* TN_COMPORT */
  3123. #ifdef NT
  3124. #ifdef CK_TAPI
  3125.     if ( tttapi && !tapipass )
  3126.     {
  3127.         HANDLE hModem = NULL;
  3128.  
  3129.         hModem = GetModemHandleFromLine( (HLINE) 0 );
  3130.         if ( hModem == NULL )
  3131.             return(-1);
  3132.  
  3133.         memset( ttycfg, 0, 1024 );
  3134.         ttycfg->dwSize = 1024;
  3135.         cfgsize = 1024;
  3136.  
  3137.         if (!GetCommConfig( hModem, ttycfg, &cfgsize )) {
  3138.             CloseHandle( hModem );
  3139.             return -1 ;
  3140.         }
  3141.         CloseHandle( hModem );
  3142.         return ttycfg->dcb.BaudRate;
  3143.     }
  3144. #endif /* CK_TAPI */
  3145.  
  3146.     ttydcb.DCBlength = sizeof(DCB);
  3147.     if (!GetCommState( (HANDLE) ttyfd, &ttydcb))
  3148.         return -1 ;
  3149.     else
  3150.         return ttydcb.BaudRate ;
  3151. #else /* NT */
  3152.     if (DosDevIOCtl(&speed,sizeof(speed),NULL,0,0x0063,IOCTL_ASYNC,ttyfd) == 0)
  3153.       return speed.current_rate;
  3154.     else
  3155.       if (DosDevIOCtl(&sp,sizeof(sp),NULL,0,
  3156.                       ASYNC_GETBAUDRATE,IOCTL_ASYNC,ttyfd) == 0)
  3157.       return sp;
  3158.     else
  3159.       return -1;
  3160. #endif /* NT */
  3161. }
  3162.  
  3163. ttsetspd(long sp) {
  3164. #ifdef NT
  3165.         int rc=0;
  3166. #else
  3167.     struct {
  3168.       long rate;
  3169.       char fract;
  3170.     } speed;
  3171.  
  3172. #endif /* NT */
  3173.  
  3174.     if (ttyfd == -1
  3175. #ifdef CK_TAPI
  3176.          || (tttapi && ttyfd == -2)
  3177. #endif /* CK_TAPI */
  3178.          ) return -1 ;
  3179. #ifdef TN_COMPORT
  3180.     if ( network) {
  3181.         if (istncomport()) {
  3182.             return(tnc_set_baud(sp));
  3183.         } else
  3184.             return(-1);
  3185.     }
  3186. #endif /* TN_COMPORT */
  3187. #ifdef NT
  3188. #ifdef CK_TAPI
  3189.     if ( tttapi && !tapipass )
  3190.     {
  3191.         HANDLE hModem = NULL;
  3192.         LPDEVCFG        lpDevCfg = NULL;
  3193.         LPCOMMCONFIG    lpCommConfig = NULL;
  3194.         LPMODEMSETTINGS lpModemSettings = NULL;
  3195.         DCB *           lpDCB = NULL;
  3196.  
  3197.         hModem = GetModemHandleFromLine( (HLINE) 0 );
  3198.         if ( hModem == NULL )
  3199.             return(-1);
  3200.  
  3201.         if (!cktapiGetModemSettings(&lpDevCfg,&lpModemSettings,&lpCommConfig,&lpDCB)) {
  3202.             CloseHandle( hModem );
  3203.             return -1 ;
  3204.         }
  3205.  
  3206.         lpDCB->BaudRate = sp ;
  3207.  
  3208.         if (!cktapiSetModemSettings(lpDevCfg,lpCommConfig)) {
  3209.             CloseHandle( hModem );
  3210.             return -1 ;
  3211.         }
  3212.  
  3213.         CloseHandle( hModem );
  3214.         return (0);
  3215.     }
  3216. #endif /* CK_TAPI */
  3217.  
  3218.     ttydcb.DCBlength = sizeof(DCB);
  3219.     if (!GetCommState( (HANDLE) ttyfd, &ttydcb))
  3220.         return -1 ;
  3221.  
  3222.  
  3223.     if ( deblog )
  3224.         debugComm( "ttsetspd initial values", &ttydcb, NULL );
  3225.  
  3226.  
  3227.     ttydcb.BaudRate = sp ;
  3228.     rc = SetCommState( (HANDLE) ttyfd, &ttydcb ) ;
  3229.         if (!rc) {
  3230.             printf("ttsetspd failed: %d\n", GetLastError());
  3231.             return -1;
  3232.         }
  3233.         else
  3234.             return 0;
  3235. #else
  3236.     if (sp > 65535L) {
  3237.       speed.rate = sp;
  3238.       speed.fract = 0;
  3239.       return DosDevIOCtl(NULL,0,&speed,sizeof(speed),0x0043,IOCTL_ASYNC,ttyfd);
  3240.     } else
  3241.       return DosDevIOCtl(NULL,0,&sp,sizeof(sp),
  3242.                          ASYNC_SETBAUDRATE,IOCTL_ASYNC,ttyfd);
  3243. #endif /* NT */
  3244. }
  3245.  
  3246.  
  3247.  
  3248. /*  T T H A N G -- Hangup phone line */
  3249.  
  3250. tthang() {
  3251.     extern int what;
  3252.  
  3253.     if ( ttyfd == -1
  3254. #ifdef CK_TAPI
  3255.          || (tttapi && ttyfd == -2)
  3256. #endif /* CK_TAPI */
  3257.          )
  3258.         return(0);              /* Nothing to do */
  3259. #ifdef NETCONN
  3260.     if (network 
  3261. #ifdef TN_COMPORT
  3262.      && !istncomport()
  3263. #endif /* TN_COMPORT */
  3264.      ) {
  3265.         int rc = os2_netclos();
  3266.         if (network && tn_exit && ttyfd == -1) {
  3267.             DialerSend(OPT_KERMIT_HANGUP, 0);
  3268.             doexit(GOOD_EXIT,xitsta);   /* Exit with good status */
  3269.         }
  3270.         return rc;
  3271.     }
  3272. #endif /* NETCONN */
  3273.     if ( exitonclose && !(what & W_DIALING) && (ttchk() < 0) ) {
  3274.         DialerSend(OPT_KERMIT_HANGUP, 0);
  3275.         doexit(GOOD_EXIT,xitsta);       /* Exit with good status */
  3276.     }
  3277. #ifdef CK_TAPI
  3278.     if ( tttapi && !tapipass )
  3279.         return cktapihangup();
  3280. #endif /* CK_TAPI */
  3281.  
  3282.  /*
  3283.   Perhaps better to either let user specify the hangup interval, or else
  3284.   do something with carrier -- e.g. if CD was on when we entered this routine,
  3285.   then cancel the sleep as soon as it goes down, so we don't sleep longer
  3286.   than we need to.
  3287. */
  3288.     if (os2setdtr(0))
  3289.        return -1;
  3290.     msleep(HUPTIME);
  3291.     os2setdtr(1);
  3292.     return 1;
  3293. }
  3294.  
  3295. #ifdef PARSENSE
  3296. static int needpchk = 1;
  3297. #else /* PARSENSE */
  3298. static int needpchk = 0;
  3299. #endif /* PARSENSE */
  3300.  
  3301. #ifdef TCPSOCKET
  3302. static int nodelay_sav = -1;
  3303. #endif /* TCPSOCKET */
  3304. #ifndef NOTERM
  3305. static int tt_update_sav = -1;
  3306. extern int tt_update;
  3307. #endif /* NOTERM */
  3308.  
  3309. #ifdef NT
  3310. /* For support of Pragma Systems Telnet/Terminal Servers */
  3311. HANDLE  hPragmaSysInputMutex = NULL;
  3312. HANDLE  hPragmaSysOutputMutex = NULL;
  3313.  
  3314. #define SET_TELNETD_INPUT_MUTEX(V,P)    sprintf( V, "TelnetDInput%dMutex", P )
  3315. #define SET_TELNETD_OUTPUT_MUTEX(V,P)   sprintf( V, "TelnetDOutput%dMutex", P )
  3316. #endif /* NT */
  3317.  
  3318.  
  3319. /*  T T R E S  --  Restore terminal to "normal" mode.  */
  3320.  
  3321. ttres() {                               /* Restore the tty to normal. */
  3322.     if (ttyfd == -1
  3323. #ifdef CK_TAPI
  3324.          || (tttapi && ttyfd == -2)
  3325. #endif /* CK_TAPI */
  3326.          )
  3327.         return(-1);     /* Not open */
  3328.  
  3329. #ifndef NOTERM
  3330.     if ( tt_update_sav > -1 ) {
  3331.         tt_update = tt_update_sav;
  3332.         tt_update_sav = -1;
  3333.     }
  3334. #endif /* NOTERM */
  3335.  
  3336. #ifdef COMMENT
  3337.     if (tt_mode == TT_MODE_NORM)
  3338.         return(0);
  3339. #endif /* COMMENT */
  3340.  
  3341. #ifdef NT
  3342.     /* Support for Pragma Systems Telnet/Terminal Servers */
  3343.     {
  3344.         char * p = getenv("PRAGMASYS_INETD_SOCK");
  3345.         if ( p && ttyfd == atoi(p)) {
  3346.             if ( hPragmaSysOutputMutex ) {
  3347.                 ReleaseMutex(hPragmaSysOutputMutex);
  3348.                 CloseHandle(hPragmaSysOutputMutex);
  3349.                 hPragmaSysOutputMutex = NULL;
  3350.             }
  3351.             if ( hPragmaSysInputMutex ) {
  3352.                 ReleaseMutex(hPragmaSysInputMutex);
  3353.                 CloseHandle(hPragmaSysInputMutex);
  3354.                 hPragmaSysInputMutex = NULL;
  3355.             }
  3356.             tt_mode = TT_MODE_NORM;
  3357.             return(0);
  3358.         }
  3359.     }
  3360. #endif /* NT */
  3361.  
  3362.     if (network) {
  3363. #ifdef TCPSOCKET
  3364. #ifdef TCP_NODELAY
  3365.         if ( network && nettype == NET_TCPB ) {
  3366.             extern int tcp_nodelay;
  3367.             if ( nodelay_sav > -1 ) {
  3368.                 no_delay(ttyfd,nodelay_sav);
  3369.                 nodelay_sav = -1;
  3370.             }
  3371.         }
  3372. #endif /* TCP_NODELAY */
  3373. #ifdef TN_COMPORT
  3374.         if (network && istncomport()) {
  3375.             int rc = -1;
  3376.             if ((rc = tnsetflow(flow)) < 0)
  3377.                 return(rc);
  3378.             if (speed <= 0)
  3379.                 speed = tnc_get_baud();
  3380.             else if ((rc = tnc_set_baud(speed)) < 0)
  3381.                 return(rc);
  3382.             tnc_set_datasize(8);
  3383.             if (hwparity) {
  3384.                 switch (hwparity) {
  3385.                 case 'e':                       /* Even */
  3386.                     debug(F100,"ttres 8 bits + even parity","",0);
  3387.                     tnc_set_parity(3);
  3388.                     break;
  3389.                 case 'o':                       /* Odd */
  3390.                     debug(F100,"ttres 8 bits + odd parity","",0);
  3391.                     tnc_set_parity(2);
  3392.                     break;
  3393.                 case 'm':                       /* Mark */
  3394.                     debug(F100,"ttres 8 bits + invalid parity: mark","",0);
  3395.                     tnc_set_parity(4);
  3396.                     break;
  3397.                 case 's':                       /* Space */
  3398.                     debug(F100,"ttres 8 bits + invalid parity: space","",0);
  3399.                     tnc_set_parity(5);
  3400.                     break;
  3401.                 }
  3402.             } else {
  3403.                 tnc_set_parity(1);              /* None */
  3404.             }
  3405.             tnc_set_stopsize(stopbits);
  3406.             tt_mode = TT_MODE_NORM;
  3407.             return(0);
  3408.         }
  3409. #endif /* TN_COMPORT */
  3410. #endif /* TCPSOCKET */
  3411. #ifdef NETDLL
  3412.         if ( network && nettype == NET_DLL ) {
  3413.             extern int (*net_dll_ttres)(void);
  3414.             extern char * (*net_dll_errorstr)(int);
  3415.             int rc = 0;
  3416.             if ( net_dll_ttres ) {
  3417.                 rc = net_dll_ttres();
  3418.                 debug(F111,"net_dll_ttres()",
  3419.                        (net_dll_errorstr && rc<0)?net_dll_errorstr(rc):"",rc);
  3420.                 if (rc < 0)
  3421.                     return(-1);
  3422.             }
  3423.             else
  3424.                 return(-1);
  3425.         }
  3426. #endif /* NETDLL */
  3427.     }
  3428.  
  3429.     ResetThreadPrty();
  3430.  
  3431.     tt_mode = TT_MODE_NORM;
  3432.     return(0);
  3433. }
  3434.  
  3435. /*  T T P K T  --  Condition the communication line for packets. */
  3436. /*              or for modem dialing */
  3437.  
  3438. /*  If called with speed > -1, also set the speed.  */
  3439. /*  Returns 0 on success, -1 on failure.  */
  3440.  
  3441. ttpkt(long speed, int flow, int parity) {
  3442.     extern int priority;
  3443.     int s;
  3444. #ifdef NT
  3445.     char * p = NULL;
  3446. #endif /* NT */
  3447.  
  3448.     debug(F111,"ttpkt","speed",speed);
  3449.     debug(F111,"ttpkt","flow",flow);
  3450.     debug(F111,"ttpkt","parity",parity);
  3451. #ifdef HWPARITY
  3452.     debug(F111,"ttpkt","hwparity",hwparity);
  3453.     debug(F111,"ttpkt","stopbits",stopbits);
  3454. #endif /* HWPARITY */
  3455.  
  3456. #ifdef COMMENT
  3457.     if ( tt_mode == TT_MODE_PKT )
  3458.         return(0);
  3459. #endif /* COMMENT */
  3460.     if ( tt_mode != TT_MODE_NORM && tt_mode != TT_MODE_PKT )
  3461.         ttres();
  3462.  
  3463.     if (ttyfd == -1
  3464. #ifdef CK_TAPI
  3465.          || (tttapi && ttyfd == -2)
  3466. #endif /* CK_TAPI */
  3467.          )
  3468.         return(-1);             /* Not open. */
  3469.  
  3470.     ttprty = parity;
  3471.     ttpmsk = ttprty ? 0177 : 0377;      /* Parity stripping mask */
  3472. #ifdef PARSENSE
  3473.     needpchk = ttprty ? 0 : 1;          /* Parity check needed? */
  3474. #else
  3475.     needpchk = 0;
  3476. #endif /* PARSENSE */
  3477.     debug(F101,"ttpkt ttpmsk","",ttpmsk);
  3478.  
  3479. #ifdef NT
  3480.     SetThreadPrty(priority,isWin95() ? 9 : 13);
  3481. #else /* NT */
  3482.     SetThreadPrty(priority,3);
  3483. #endif /* NT */
  3484.  
  3485. #ifdef NT
  3486.     /* Support for Pragma Systems Telnet/Terminal Servers */
  3487.     p = getenv("PRAGMASYS_INETD_SOCK");
  3488.     if ( p && ttyfd == atoi(p)) {
  3489.         char PragmaSysInputMutexName[MAX_PATH];
  3490.         char PragmaSysOutputMutexName[MAX_PATH];
  3491.  
  3492.         p = getenv("PRAGMASYS_TELNETD_PID");
  3493.         if ( p )
  3494.         {
  3495.             debug(F111,"ttpkt","PRAGMASYS_TELNETD_PID",atoi(p));
  3496.             SET_TELNETD_INPUT_MUTEX(PragmaSysInputMutexName,(DWORD)atoi(p));
  3497.             SET_TELNETD_OUTPUT_MUTEX(PragmaSysOutputMutexName,(DWORD)atoi(p));
  3498.             debug(F110,"ttpkt",PragmaSysInputMutexName,0);
  3499.             debug(F110,"ttpkt",PragmaSysOutputMutexName,0);
  3500.  
  3501.             hPragmaSysOutputMutex = OpenMutex( SYNCHRONIZE, FALSE, PragmaSysOutputMutexName);
  3502.             if ( hPragmaSysOutputMutex == NULL )
  3503.             {
  3504.                 debug(F111,"ttpkt","PragmaSys unable to OpenMutex(Output)",
  3505.                        GetLastError());
  3506.                 return(-1);
  3507.             }
  3508.  
  3509.             if (WaitForSingleObject( hPragmaSysOutputMutex,  5000 ) != WAIT_OBJECT_0)
  3510.             {
  3511.                 debug(F111,"ttpkt","PragmaSys unable to WaitForSingleObject(Output)",
  3512.                        GetLastError());
  3513.                 CloseHandle(hPragmaSysOutputMutex);
  3514.                 hPragmaSysOutputMutex = NULL;
  3515.                 return(-1);
  3516.             }
  3517.  
  3518.             hPragmaSysInputMutex = OpenMutex( SYNCHRONIZE, FALSE, PragmaSysInputMutexName);
  3519.             if ( hPragmaSysInputMutex == NULL )
  3520.             {
  3521.                 debug(F111,"ttpkt","PragmaSys unable to OpenMutex(Input)",
  3522.                        GetLastError());
  3523.                 CloseHandle(hPragmaSysOutputMutex);
  3524.                 hPragmaSysOutputMutex = NULL;
  3525.                 return(-1);
  3526.             }
  3527.  
  3528.             if (WaitForSingleObject( hPragmaSysInputMutex,  5000 ) != WAIT_OBJECT_0)
  3529.             {
  3530.                 debug(F111,"ttpkt","PragmaSys unable to WaitForSingleObject(Input)",
  3531.                        GetLastError());
  3532.                 CloseHandle(hPragmaSysOutputMutex);
  3533.                 hPragmaSysOutputMutex = NULL;
  3534.                 CloseHandle(hPragmaSysInputMutex);
  3535.                 hPragmaSysInputMutex = NULL;
  3536.                 return(-1);
  3537.             }
  3538.             debug(F100,"ttpkt success","",0);
  3539.             tt_mode = TT_MODE_PKT;
  3540.             return(0);
  3541.         }
  3542.         debug(F110,"ttpkt","PragmaSys unable to getenv(PRAGMASYS_TELNETD_PID)",0);
  3543.         return(-1);
  3544.     }
  3545. #endif /* NT */
  3546.  
  3547.     if (network) {
  3548. #ifdef TCPSOCKET
  3549. #ifdef TCP_NODELAY
  3550.         if ( network && nettype == NET_TCPB ) {
  3551.             extern int tcp_nodelay;
  3552.             nodelay_sav = tcp_nodelay;
  3553.             no_delay(ttyfd,1);
  3554.         }
  3555. #endif /* TCP_NODELAY */
  3556. #ifdef TN_COMPORT
  3557.         if (network && istncomport()) {
  3558.             int rc = -1;
  3559.             if ((rc = tnsetflow(flow)) < 0)
  3560.                 return(rc);
  3561.             if (speed <= 0)
  3562.                 speed = tnc_get_baud();
  3563.             else if ((rc = tnc_set_baud(speed)) < 0)
  3564.                 return(rc);
  3565.             tnc_set_datasize(8);
  3566.             if (hwparity) {
  3567.                 switch (hwparity) {
  3568.                 case 'e':                       /* Even */
  3569.                     debug(F100,"ttpkt 8 bits + even parity","",0);
  3570.                     tnc_set_parity(3);
  3571.                     break;
  3572.                 case 'o':                       /* Odd */
  3573.                     debug(F100,"ttpkt 8 bits + odd parity","",0);
  3574.                     tnc_set_parity(2);
  3575.                     break;
  3576.                 case 'm':                       /* Mark */
  3577.                     debug(F100,"ttpkt 8 bits + invalid parity: mark","",0);
  3578.                     tnc_set_parity(4);
  3579.                     break;
  3580.                 case 's':                       /* Space */
  3581.                     debug(F100,"ttpkt 8 bits + invalid parity: space","",0);
  3582.                     tnc_set_parity(5);
  3583.                     break;
  3584.                 }
  3585.             } else {
  3586.                 tnc_set_parity(1);              /* None */
  3587.             }
  3588.             tnc_set_stopsize(stopbits);
  3589.             tt_mode = TT_MODE_PKT;
  3590.             return(0);
  3591.         }
  3592. #endif /* TN_COMPORT */
  3593. #endif /* TCPSOCKET */
  3594. #ifdef NETDLL
  3595.         if ( network && nettype == NET_DLL ) {
  3596.             extern int (*net_dll_ttpkt)(void);
  3597.             extern char * (*net_dll_errorstr)(int);
  3598.             int rc = 0;
  3599.             if ( net_dll_ttpkt ) {
  3600.                 rc = net_dll_ttpkt();
  3601.                 debug(F111,"net_dll_ttpkt()",
  3602.                        (net_dll_errorstr && rc<0)?net_dll_errorstr(rc):"",rc);
  3603.                 if (rc<0)
  3604.                     return(-1);
  3605.             }
  3606.             else
  3607.                 return(-1);
  3608.         }
  3609. #endif /* NETDLL */
  3610.         debug(F100,"ttpkt success","",0);
  3611.         tt_mode = TT_MODE_PKT;
  3612.         return(0);
  3613.     }
  3614.  
  3615.     if (speed < 0)
  3616.         return(-1);
  3617.  
  3618.     os2setdtr(1);
  3619.     if (ttsetspd(speed))
  3620.         return(-1);
  3621.     if (ttsettings(ttprty,stopbits))
  3622.         return(-1);
  3623.     if (ttsetflow(flow))
  3624.         return(-1);
  3625.     if (os2settimo(speed,ttmdm))
  3626.         return(-1);
  3627.     if (os2setcarr(ttcarr == CAR_ON && flow != FLO_DIAL))
  3628.         return(-1);
  3629.  
  3630.     debug(F100,"ttpkt success","",0);
  3631.     tt_mode = TT_MODE_PKT;
  3632.     return(0);
  3633. }
  3634.  
  3635.  
  3636. /*  T T V T -- Condition communication line for use as virtual terminal  */
  3637.  
  3638. ttvt(long speed, int flow) {
  3639.     extern int priority;
  3640. #ifdef NT
  3641.     char * p = NULL;
  3642. #endif /* NT */
  3643.  
  3644.     debug(F111,"ttvt","speed",speed);
  3645.     debug(F111,"ttvt","flow",flow);
  3646.     debug(F111,"ttvt","parity",parity);
  3647.  
  3648. #ifdef COMMENT
  3649.     if (tt_mode == TT_MODE_VT)
  3650.         return(0);
  3651. #endif
  3652.     if ( tt_mode != TT_MODE_NORM && tt_mode != TT_MODE_NORM )
  3653.         ttres();
  3654.  
  3655.     if (ttyfd == -1
  3656. #ifdef CK_TAPI
  3657.          || (tttapi && ttyfd == -2)
  3658. #endif /* CK_TAPI */
  3659.          ) {
  3660.         if ( ttchk() > 0 )
  3661.             return(0);          /* Data waiting to be read */
  3662.         else
  3663.             return(-1);         /* Not open. */
  3664.     }
  3665. #ifndef NOTERM
  3666.     if ( tt_update_sav > -1 ) {
  3667.         tt_update = tt_update_sav;
  3668.         tt_update_sav = -1;
  3669.     }
  3670. #endif /* NOTERM */
  3671.     ResetThreadPrty();
  3672.  
  3673. #ifdef NT
  3674.     /* Support for Pragma Systems Telnet/Terminal Servers */
  3675.     p = getenv("PRAGMASYS_INETD_SOCK");
  3676.     if ( p && ttyfd == atoi(p)) {
  3677.         char PragmaSysInputMutexName[MAX_PATH];
  3678.         char PragmaSysOutputMutexName[MAX_PATH];
  3679.  
  3680.         p = getenv("PRAGMASYS_TELNETD_PID");
  3681.         if ( p )
  3682.         {
  3683.             if ( hPragmaSysOutputMutex && hPragmaSysInputMutex )
  3684.                 return(0);
  3685.  
  3686.             debug(F111,"ttvt","PRAGMASYS_TELNETD_PID",atoi(p));
  3687.             SET_TELNETD_INPUT_MUTEX(PragmaSysInputMutexName,(DWORD)atoi(p));
  3688.             SET_TELNETD_OUTPUT_MUTEX(PragmaSysOutputMutexName,(DWORD)atoi(p));
  3689.             debug(F110,"ttvt",PragmaSysInputMutexName,0);
  3690.             debug(F110,"ttvt",PragmaSysOutputMutexName,0);
  3691.  
  3692.             hPragmaSysOutputMutex = OpenMutex( SYNCHRONIZE, FALSE, PragmaSysOutputMutexName);
  3693.             if ( hPragmaSysOutputMutex == NULL )
  3694.             {
  3695.                 debug(F111,"ttvt","PragmaSys unable to OpenMutex(Output)",
  3696.                        GetLastError());
  3697.                 return(-1);
  3698.             }
  3699.  
  3700.             if (WaitForSingleObject( hPragmaSysOutputMutex,  5000 ) != WAIT_OBJECT_0)
  3701.             {
  3702.                 debug(F111,"ttvt","PragmaSys unable to WaitForSingleObject(Output)",
  3703.                        GetLastError());
  3704.                 CloseHandle(hPragmaSysOutputMutex);
  3705.                 hPragmaSysOutputMutex = NULL;
  3706.                 return(-1);
  3707.             }
  3708.  
  3709.             hPragmaSysInputMutex = OpenMutex( SYNCHRONIZE, FALSE, PragmaSysInputMutexName);
  3710.             if ( hPragmaSysInputMutex == NULL )
  3711.             {
  3712.                 debug(F111,"ttvt","PragmaSys unable to OpenMutex(Input)",
  3713.                        GetLastError());
  3714.                 CloseHandle(hPragmaSysOutputMutex);
  3715.                 hPragmaSysOutputMutex = NULL;
  3716.                 return(-1);
  3717.             }
  3718.  
  3719.             if (WaitForSingleObject( hPragmaSysInputMutex,  5000 ) != WAIT_OBJECT_0)
  3720.             {
  3721.                 debug(F111,"ttvt","PragmaSys unable to WaitForSingleObject(Input)",
  3722.                        GetLastError());
  3723.                 CloseHandle(hPragmaSysOutputMutex);
  3724.                 hPragmaSysOutputMutex = NULL;
  3725.                 CloseHandle(hPragmaSysInputMutex);
  3726.                 hPragmaSysInputMutex = NULL;
  3727.                 return(-1);
  3728.             }
  3729.             debug(F100,"ttvt success","",0);
  3730.             tt_mode = TT_MODE_VT;
  3731.             return(0);
  3732.         }
  3733.         debug(F110,"ttvt","PragmaSys unable to getenv(PRAGMASYS_TELNETD_PID)",0);
  3734.         return(-1);
  3735.     }
  3736. #endif /* NT */
  3737.  
  3738.     if (network) {
  3739. #ifdef TCPSOCKET
  3740. #ifdef TCP_NODELAY
  3741.         if ( network && nettype == NET_TCPB ) {
  3742.             extern int tcp_nodelay;
  3743.             if ( nodelay_sav > -1 ) {
  3744.                 no_delay(ttyfd,nodelay_sav);
  3745.                 nodelay_sav = -1;
  3746.             }
  3747.         }
  3748. #endif /* TCP_NODELAY */
  3749. #ifdef TN_COMPORT
  3750.         if (network && istncomport()) {
  3751.             int rc = -1;
  3752.             if ((rc = tnsetflow(flow)) < 0)
  3753.                 return(rc);
  3754.             if (speed <= 0)
  3755.                 speed = tnc_get_baud();
  3756.             else if ((rc = tnc_set_baud(speed)) < 0)
  3757.                 return(rc);
  3758.             tnc_set_datasize(8);
  3759.             if (hwparity) {
  3760.                 switch (hwparity) {
  3761.                 case 'e':                       /* Even */
  3762.                     debug(F100,"ttvt 8 bits + even parity","",0);
  3763.                     tnc_set_parity(3);
  3764.                     break;
  3765.                 case 'o':                       /* Odd */
  3766.                     debug(F100,"ttvt 8 bits + odd parity","",0);
  3767.                     tnc_set_parity(2);
  3768.                     break;
  3769.                 case 'm':                       /* Mark */
  3770.                     debug(F100,"ttvt 8 bits + invalid parity: mark","",0);
  3771.                     tnc_set_parity(4);
  3772.                     break;
  3773.                 case 's':                       /* Space */
  3774.                     debug(F100,"ttvt 8 bits + invalid parity: space","",0);
  3775.                     tnc_set_parity(5);
  3776.                     break;
  3777.                 }
  3778.             } else {
  3779.                 tnc_set_parity(1);              /* None */
  3780.             }
  3781.             tnc_set_stopsize(stopbits);
  3782.             tt_mode = TT_MODE_VT;
  3783.             return(0);
  3784.         }
  3785. #endif /* TN_COMPORT */
  3786. #endif /* TCPSOCKET */
  3787. #ifdef NETDLL
  3788.         if ( network && nettype == NET_DLL ) {
  3789.             extern int (*net_dll_ttvt)(void);
  3790.             extern char * (*net_dll_errorstr)(int);
  3791.             int rc = 0;
  3792.             if ( net_dll_ttvt ) {
  3793.                 rc = net_dll_ttvt();
  3794.                 debug(F111,"net_dll_ttvt()",
  3795.                        (net_dll_errorstr && rc<0)?net_dll_errorstr(rc):"",rc);
  3796.                 if ( rc < 0 )
  3797.                     return(-1);
  3798.             }
  3799.             else
  3800.                 return(-1);
  3801.         }
  3802. #endif /* NETDLL */
  3803.         debug(F100,"ttvt success","",0);
  3804.         tt_mode = TT_MODE_VT;
  3805.         return(0);
  3806.     }   /* end of network */
  3807.  
  3808.     if (speed < 0)
  3809.         return(-1);
  3810.  
  3811.     ttprty = parity;
  3812.     ttpmsk = 0xff;
  3813.  
  3814.     os2setdtr(1);
  3815.     if (ttsetspd(speed))
  3816.         return(-1);
  3817.     if (ttsettings(ttprty,stopbits))
  3818.         return(-1);
  3819.     if (ttsetflow(flow))
  3820.         return (-1);
  3821.     if (os2settimo(speed,ttmdm))
  3822.         return(-1);
  3823.     if (os2setcarr(ttcarr == CAR_ON || ttcarr == CAR_AUT))
  3824.         return(-1);
  3825.  
  3826.     debug(F100,"ttvt success","",0);
  3827.     tt_mode = TT_MODE_VT;
  3828.     return(0);
  3829. }
  3830.  
  3831.  
  3832. /*  T T S S P D  --  Return the speed if OK, otherwise -1 */
  3833.  
  3834. int
  3835. ttsspd(int speed) {
  3836.     long s;
  3837.  
  3838.     if (speed < 0) return(-1);
  3839.  
  3840.     s = (long) speed * 10L;
  3841.     ttsetspd(s);
  3842.     return(0);
  3843. }
  3844.  
  3845. /* The following functions will provide the interface for the local echo */
  3846. /* buffer to be used when 'duplex' is TRUE                               */
  3847.  
  3848. #ifdef OS2ONLY
  3849. #define LOCAL_ECHO_BUFSIZE (65536/sizeof(USHORT))
  3850. #else /* OS2ONLY */
  3851. #define LOCAL_ECHO_BUFSIZE 65536
  3852. #endif /* OS2ONLY */
  3853.  
  3854. static USHORT LocalEchoBuf[LOCAL_ECHO_BUFSIZE] ;
  3855. static int LocalEchoStart=0, LocalEchoEnd=0, LocalEchoData=0 ;
  3856.  
  3857. void
  3858. le_init( void ) {
  3859.     CreateLocalEchoAvailSem( FALSE );
  3860.     CreateLocalEchoMutex( TRUE ) ;
  3861.     memset(LocalEchoBuf,0,LOCAL_ECHO_BUFSIZE*sizeof(USHORT)) ;
  3862.     LocalEchoStart = 0 ;
  3863.     LocalEchoEnd = 0 ;
  3864.     LocalEchoData = 0;
  3865.     ReleaseLocalEchoMutex() ;
  3866. }
  3867.  
  3868. void
  3869. le_clean( void ) {
  3870.     CloseLocalEchoMutex() ;
  3871.     CloseLocalEchoAvailSem() ;
  3872. }
  3873.  
  3874. int
  3875. le_inbuf( void ) {
  3876.     int rc = 0 ;
  3877.  
  3878.     RequestLocalEchoMutex( SEM_INDEFINITE_WAIT ) ;
  3879.     if ( LocalEchoStart != LocalEchoEnd )
  3880.     {
  3881.         rc = (LocalEchoEnd - LocalEchoStart + LOCAL_ECHO_BUFSIZE)%LOCAL_ECHO_BUFSIZE;
  3882.     }
  3883.     ReleaseLocalEchoMutex() ;
  3884.     return rc ;
  3885. }
  3886.  
  3887. int
  3888. le_putstr( char * s )
  3889. {
  3890.     int rc = 0;
  3891.     if ( s && s[0] )
  3892.         rc = le_puts( s, strlen(s) ) ;
  3893.     return rc ;
  3894. }
  3895.  
  3896. int
  3897. le_puts( char * s, int n )
  3898. {
  3899.     int rc = 0 ;
  3900.     int i = 0;
  3901.  
  3902.     hexdump("LocalEchoPutChars",s,n);
  3903.     RequestLocalEchoMutex( SEM_INDEFINITE_WAIT ) ;
  3904.     for ( i=0 ; i<n ; i++ ) {
  3905.         while ( (LocalEchoStart - LocalEchoEnd == 1) ||
  3906.                 ( LocalEchoStart == 0 && LocalEchoEnd == LOCAL_ECHO_BUFSIZE - 1 ) )
  3907.             /* Buffer is full */
  3908.         {
  3909.             debug(F111,"LocalEchoPutChar","Buffer is Full",s[i]);
  3910.             ReleaseLocalEchoMutex() ;
  3911.             msleep(250);
  3912.             RequestLocalEchoMutex( SEM_INDEFINITE_WAIT ) ;
  3913.         }
  3914.  
  3915.         LocalEchoBuf[LocalEchoEnd++] = s[i];
  3916.         if ( LocalEchoEnd == LOCAL_ECHO_BUFSIZE )
  3917.             LocalEchoEnd = 0 ;
  3918.         LocalEchoData = TRUE;
  3919.         PostLocalEchoAvailSem()  ;
  3920.     }
  3921.     ReleaseLocalEchoMutex() ;
  3922.     debug(F101,"LocalEchoPutChars","",rc);
  3923.     return rc ;
  3924. }
  3925.  
  3926. int
  3927. le_putchar( char ch ) {
  3928.     int rc = 0 ;
  3929.  
  3930.     RequestLocalEchoMutex( SEM_INDEFINITE_WAIT ) ;
  3931.     while ( (LocalEchoStart - LocalEchoEnd == 1) ||
  3932.             ( LocalEchoStart == 0 && LocalEchoEnd == LOCAL_ECHO_BUFSIZE - 1 ) )
  3933.         /* Buffer is full */
  3934.     {
  3935.         debug(F111,"LocalEchoPutChar","Buffer is Full",ch);
  3936.         ReleaseLocalEchoMutex() ;
  3937.         msleep(250);
  3938.         RequestLocalEchoMutex( SEM_INDEFINITE_WAIT ) ;
  3939.     }
  3940.  
  3941.     LocalEchoBuf[LocalEchoEnd++] = ch ;
  3942.     if ( LocalEchoEnd == LOCAL_ECHO_BUFSIZE )
  3943.         LocalEchoEnd = 0 ;
  3944.     LocalEchoData = TRUE;
  3945.     PostLocalEchoAvailSem()  ;
  3946.     ReleaseLocalEchoMutex() ;
  3947.     return rc ;
  3948. }
  3949.  
  3950. int
  3951. le_getchar( CHAR * pch )
  3952. {
  3953.     int rc = 0 ;
  3954.  
  3955.     RequestLocalEchoMutex( SEM_INDEFINITE_WAIT ) ;
  3956.     if ( LocalEchoStart != LocalEchoEnd ) {
  3957.         *pch = LocalEchoBuf[LocalEchoStart] ;
  3958.         LocalEchoBuf[LocalEchoStart]=0;
  3959.         LocalEchoStart++ ;
  3960.  
  3961.         if ( LocalEchoStart == LOCAL_ECHO_BUFSIZE )
  3962.           LocalEchoStart = 0 ;
  3963.  
  3964.         if ( LocalEchoStart == LocalEchoEnd ) {
  3965.             LocalEchoData = FALSE;
  3966.             ResetLocalEchoAvailSem() ;
  3967.         }
  3968.         rc++ ;
  3969.     }
  3970.     else
  3971.     {
  3972.         *pch = 0 ;
  3973.     }
  3974.     ReleaseLocalEchoMutex() ;
  3975.     return rc ;
  3976. }
  3977.  
  3978. /*  T T F L U I  --  Flush tty input buffer */
  3979.  
  3980. ttflui() {
  3981.     char parm=0;
  3982.     long int data;
  3983.     int i;
  3984.  
  3985.     ttpush = -1;                               /* Clear the peek-ahead char */
  3986.  
  3987.     while ( LocalEchoData && (le_inbuf() > 0) ) {
  3988.         char ch=0;
  3989.         if ( le_getchar(&ch) > 0 ) {
  3990.             debug(F111,"ttflui le_getchar","ch",ch);
  3991.         }
  3992.     }
  3993.  
  3994. #ifdef NETCONN
  3995.     if (network) {
  3996. #ifdef TN_COMPORT
  3997. #ifdef COMMENT
  3998.         if (istncomport())
  3999.             tnc_send_purge_data(TNC_PURGE_RECEIVE);
  4000. #endif /* TN_COMPORT */
  4001. #endif /* COMMENT */
  4002.         return os2_netflui() ;
  4003.     }
  4004. #endif /* NETCONN */
  4005.     rdchbuf.index = rdchbuf.length = 0;         /* Flush internal buffer */
  4006.  
  4007. #ifdef NT
  4008.     PurgeComm( (HANDLE) ttyfd, PURGE_RXCLEAR | PURGE_RXABORT ) ;
  4009. #else /* NT */
  4010.     DosDevIOCtl(&data,sizeof(data),&parm,sizeof(parm),
  4011.                 DEV_FLUSHINPUT,IOCTL_GENERAL,ttyfd); /* Flush driver */
  4012. #endif /* NT */
  4013.     return(0);
  4014. }
  4015.  
  4016.  
  4017. /*  T T C H K  --  Tell how many characters are waiting in tty input buffer  */
  4018.  
  4019. ttchk() {
  4020.     int count=0;
  4021. #ifdef NT
  4022.     DWORD rc, lasterror;
  4023.     DWORD errors ;
  4024.     COMSTAT comstat ;
  4025. #else /* NT */
  4026.     USHORT data[2]={0,0};
  4027. #endif /* NT */
  4028.  
  4029.     if ( ttyfd == -1
  4030. #ifdef CK_TAPI
  4031.          || (tttapi && ttyfd == -2)
  4032. #endif /* CK_TAPI */
  4033.          ) {
  4034.         if ( ttpush >= 0 )
  4035.             count++;
  4036.         count += le_inbuf();
  4037.         return(count>0?count:-1);                       /* No connection */
  4038.     }
  4039.  
  4040. #ifdef NETCONN
  4041.     if (network) {
  4042.         count = os2_nettchk();
  4043.         if ( count >= 0 ) {
  4044.             if ( ttpush >= 0 )
  4045.                 count++;
  4046.             count += le_inbuf();
  4047. #ifdef TN_COMPORT
  4048.             if (count == 0 && istncomport() && ttcarr != CAR_OFF) {
  4049.                 /* Check carrier */
  4050.                 extern int clsondisc;
  4051.                 int mdmsig = tngmdm();
  4052.                 if ( mdmsig >= 0 && (mdmsig & BM_DCD) == 0 ) {
  4053.                     debug(F111,"ttchk","Carrier not detected",ttcarr);
  4054.                     if (clsondisc) {        /* If "close-on-disconnect" */
  4055.                         debug(F100,"ttchk close-on-disconnect","",0);
  4056.                         ttclos(0);      /* close device */
  4057.                         return(-2);
  4058.                     }
  4059.                     return(-1);
  4060.                 }
  4061.             }
  4062. #endif /* TN_COMPORT */
  4063.             debug(F101,"ttchk() network istncomport returns","",count);
  4064.             return count;
  4065.         }
  4066.         else {
  4067.             int count2 = 0;
  4068.             if ( ttpush >= 0 )
  4069.                 count2++;
  4070.             count2 += le_inbuf();
  4071.             debug(F101,"ttchk() network !istncomport returns","",
  4072.                    count2?count2:count);
  4073.             return(count2?count2:count);
  4074.         }
  4075.     }
  4076. #endif /* NETCONN */
  4077.  
  4078. #ifdef NT
  4079.     RequestCommMutex(SEM_INDEFINITE_WAIT);
  4080.     rc = ClearCommError( (HANDLE) ttyfd, &errors, &comstat );
  4081.     ReleaseCommMutex();
  4082.     lasterror = GetLastError();
  4083.     if (!rc) {
  4084.         debug(F101,"ttchk() ClearCommError failed","",lasterror);
  4085.         count = -1;
  4086.     } else {
  4087.         if ( errors && deblog )
  4088.         {
  4089.             if ( errors & CE_RXOVER )
  4090.                 debug(F110,"ttchk ClearCommError","Receive Queue overflow",0);
  4091.             if ( errors & CE_OVERRUN )
  4092.                 debug(F110,"ttchk ClearCommError","Receive Overrun error",0);
  4093.             if ( errors & CE_RXPARITY )
  4094.                 debug(F110,"ttchk ClearCommError","Receive Parity error",0);
  4095.             if ( errors & CE_FRAME )
  4096.                 debug(F110,"ttchk ClearCommError","Receive Framing error",0);
  4097.             if ( errors & CE_BREAK )
  4098.                 debug(F110,"ttchk ClearCommError","Break detected",0);
  4099.             if ( errors & CE_TXFULL )
  4100.                 debug(F110,"ttchk ClearCommError","TX Queue is full",0);
  4101.             if ( errors & CE_PTO )
  4102.                 debug(F110,"ttchk ClearCommError","LPTx Timeout",0);
  4103.             if ( errors & CE_IOE )
  4104.                 debug(F110,"ttchk ClearCommError","LPTx I/O Error",0);
  4105.             if ( errors & CE_DNS )
  4106.                 debug(F110,"ttchk ClearCommError","LPTx Device Not Selected",0);
  4107.             if ( errors & CE_OOP )
  4108.                 debug(F110,"ttchk ClearCommError","LPTx Out Of Paper",0);
  4109.         }
  4110.         count = comstat.cbInQue+(rdchbuf.length-rdchbuf.index);
  4111.     }
  4112. #else /* NT */
  4113.     if ( DosDevIOCtl(data,sizeof(USHORT),NULL,0,
  4114.                       ASYNC_GETCOMMERROR,IOCTL_ASYNC,ttyfd)) {
  4115.         if ( data[0] & RX_QUE_OVERRUN ) {
  4116.             debug( F100,"ttchk RX_QUE_OVERRUN","",0);
  4117.         }
  4118.         if ( data[0] & RX_HARDWARE_OVERRUN ) {
  4119.             debug( F100,"ttchk RX_HARDWARE_OVERRUN", "", 0 );
  4120.         }
  4121.     }
  4122.  
  4123.     if(DosDevIOCtl(data,sizeof(data),NULL,0,
  4124.                     ASYNC_GETINQUECOUNT,IOCTL_ASYNC,ttyfd))
  4125.         count = 0;
  4126.     else
  4127.         count = rdchbuf.length-rdchbuf.index+data[0];
  4128. #endif /* NT */
  4129.  
  4130.     if ( count >= 0 ) {
  4131.         if ( ttpush >= 0 )
  4132.             count++;
  4133.         count += le_inbuf();
  4134.  
  4135.         if (count == 0 && ttcarr != CAR_OFF) {
  4136.             /* Check carrier */
  4137.             extern int clsondisc;
  4138.             int mdmsig = ttgmdm();
  4139.             if ( mdmsig >= 0 && (mdmsig & BM_DCD) == 0 ) {
  4140.                 debug(F111,"ttchk","Carrier not detected",ttcarr);
  4141.                 if (clsondisc) {        /* If "close-on-disconnect" */
  4142.                     debug(F100,"ttchk close-on-disconnect","",0);
  4143.                     ttclos(0);      /* close device */
  4144.                     return(-2);
  4145.                 }
  4146.                 return(-1);
  4147.             }
  4148.         }
  4149.  
  4150. #ifdef NT
  4151. #ifdef NEWRDCH
  4152.         /* Is there anything in the overlapped I/O buffers? */
  4153.         /* Network Overlapped I/O is handled in nettchk()   */
  4154.         count += OverlappedDataWaiting();
  4155. #endif /* NEWRDCH */
  4156. #endif /* NT */
  4157.     } else {
  4158.         int cnt = 0;
  4159.         if ( ttpush >= 0 )
  4160.             cnt++;
  4161.         cnt += le_inbuf();
  4162.         if ( cnt )
  4163.             count = cnt;
  4164.     }
  4165.     debug(F101,"ttchk() !network returns","",count);
  4166.     return(count);
  4167. }
  4168.  
  4169.  
  4170. /*  T T X I N  --  Get n characters from tty input buffer  */
  4171.  
  4172. /*  Returns number of characters actually gotten, or -1 on failure  */
  4173.  
  4174. /*  Intended for use only when it is known that n characters are actually */
  4175. /*  available in the input buffer because this function blocks.           */
  4176.  
  4177. int
  4178. ttxin(int n, CHAR *buf) {
  4179.     int i=0, j=0, k=0;
  4180.     CHAR m=0 ;
  4181.  
  4182.     m = (ttprty) ? 0177 : 0377;         /* Parity stripping mask. */
  4183.  
  4184.     buf[0] = '\0';              /* make it easy to read the buffer in a debugger */
  4185.  
  4186.     if (ttyfd == -1
  4187. #ifdef CK_TAPI
  4188.          || (tttapi && ttyfd == -2)
  4189. #endif /* CK_TAPI */
  4190. )
  4191.         return(-1);             /* Not open. */
  4192.  
  4193.     debug(F101,"ttxin n","",n);
  4194.     if ( n <= 0 )
  4195.         return(0);
  4196.  
  4197.     if ( ttpush >= 0 ) {
  4198.         buf[0] = ttpush & m; /* set first char of buffer to pushed char */
  4199.         ttpush = -1;              /* clear the push buffer                   */
  4200.         if ( ttchk() > 0 )
  4201.             return(ttxin( n-1, &buf[1] ) + 1);      /* recurse the call */
  4202.         else
  4203.             return(1);
  4204.     }
  4205.  
  4206.     if ( LocalEchoData ) {
  4207.         while ( le_inbuf() > 0 ) {
  4208.             le_getchar( &buf[i] );
  4209.             buf[i] &= m;
  4210.             i++;
  4211.             n--;
  4212.         }
  4213.         if (ttchk() > 0)
  4214.             return(ttxin( n, &buf[i] ) + i);
  4215.         else
  4216.             return(i);
  4217.     }
  4218.  
  4219. #ifdef NETCONN
  4220.     if (network) {
  4221.         j = os2_netxin(n,buf);
  4222.         if ( ttprty ) {
  4223.             for ( i=0;i<j;i++ )
  4224.                 buf[i] &= m;
  4225.         }
  4226.     }
  4227.     else {
  4228. #endif /* NETCONN */
  4229.         debug( F101,"ttxin rdchbuf.index","",rdchbuf.index);
  4230.         debug( F101,"ttxin rdchbuf.length","",rdchbuf.length);
  4231.         if ( rdchbuf.index == rdchbuf.length ) {
  4232.             if ( (j = rdch(0)) < 0 )
  4233.                 return(j);
  4234.             rdchbuf.index-- ;
  4235.         }
  4236.         i = rdchbuf.length - rdchbuf.index ;
  4237.         debug(F101,"ttxin i","",i);
  4238.         if (i <= n) {
  4239.             debug( F100,"ttxin i <= n","",0);
  4240.             memcpy(buf, &rdchbuf.buffer[rdchbuf.index], i );
  4241.             rdchbuf.index = rdchbuf.length ;
  4242.             j = i;
  4243.         }
  4244.         else {
  4245.             debug( F100,"ttxin i > n","",0);
  4246.             memcpy(buf, &rdchbuf.buffer[rdchbuf.index], n ) ;
  4247.             rdchbuf.index += n ;
  4248.             j = n;
  4249.         }
  4250.         if ( ttprty ) {
  4251.             for ( i=0;i<j;i++ )
  4252.                 buf[i] &= m;
  4253.         }
  4254. #ifdef NETCONN
  4255.     }
  4256. #endif /* NETCONN */
  4257.     return(j);
  4258. }
  4259.  
  4260.  
  4261. #ifdef NT
  4262. /* Overlapped I/O code */
  4263.  
  4264. int
  4265. getOverlappedIndex( int serial ) {
  4266.     int ow ;
  4267.     /* get an overlapped_write structure that is not in use */
  4268.     for ( ow=0 ; ow<maxow ; ow++ ) {
  4269.         if ( !ow_inuse[ow] )
  4270.             break;
  4271.     }
  4272.  
  4273.     debug(F111,"getOverlappedIndex","next available ow",ow);
  4274.     if ( ow == maxow ) {
  4275.         /* They are all in use.  So lets either find or wait */
  4276.         /* for one which is complete.                        */
  4277.         ow = -1;
  4278.         while(!GetOverlappedResult( (HANDLE) ttyfd,
  4279.                                     &overlapped_write[++ow],
  4280.                                     &nActuallyWritten, owwait ))
  4281.         {
  4282.             DWORD error = GetLastError() ;
  4283.             if ( error == ERROR_IO_INCOMPLETE ) {
  4284.                 debug(F111,"getOverlappedIndex ERROR_IO_INCOMPLETE","ow",ow);
  4285.                 debug(F111,"getOverlappedIndex waiting to complete",ow_ptr[ow],ow);
  4286.                 if ( (ow+1) >= maxow ) {
  4287.  
  4288.                     if ( serial ) {
  4289.                     /* All buffers are still outstanding */
  4290.                     /* Lets see if we can figure out why */
  4291.                     DWORD errorflags ;
  4292.                     COMSTAT comstat ;
  4293.                     RequestCommMutex(SEM_INDEFINITE_WAIT);
  4294.                     ClearCommError( (HANDLE) ttyfd, &errorflags, &comstat ) ;
  4295.                     ReleaseCommMutex();
  4296.                     debug(F101,"getOverlappedIndex ClearCommError",
  4297.                            "",errorflags) ;
  4298. #ifdef BETADEBUG
  4299.                     printf("\nClearCommError: %d\n",errorflags);
  4300.                     if ( errorflags ) {
  4301.                         if ( errorflags & CE_RXOVER )
  4302.                             printf("  Receive Queue overflow\n");
  4303.                         if ( errorflags & CE_OVERRUN )
  4304.                             printf("  Receive Overrun error\n");
  4305.                         if ( errorflags & CE_RXPARITY )
  4306.                             printf("  Receive Parity error\n");
  4307.                         if ( errorflags & CE_FRAME )
  4308.                             printf("  Receive Framing error\n");
  4309.                         if ( errorflags & CE_BREAK )
  4310.                             printf("  Break detected\n");
  4311.                         if ( errorflags & CE_TXFULL )
  4312.                             printf("  TX Queue is full\n");
  4313.                         if ( errorflags & CE_PTO )
  4314.                             printf("  LPTx Timeout\n");
  4315.                         if ( errorflags & CE_IOE )
  4316.                             printf("  LPTx I/O Error\n");
  4317.                         if ( errorflags & CE_DNS )
  4318.                             printf("  LPTx Device Not Selected\n");
  4319.                         if ( errorflags & CE_OOP )
  4320.                             printf("  LPTx Out Of Paper\n");
  4321.                     }
  4322.                     printf("Port Status:\n");
  4323.                     printf("  Cts Hold:  %d\n",comstat.fCtsHold);
  4324.                     printf("  Dsr Hold:  %d\n",comstat.fDsrHold);
  4325.                     printf("  Rlsd Hold: %d\n",comstat.fRlsdHold);
  4326.                     printf("  Xoff Hold: %d\n",comstat.fXoffHold);
  4327.                     printf("  Xoff Sent: %d\n",comstat.fXoffSent);
  4328.                     printf("  Eof:       %d\n",comstat.fEof);
  4329.                     printf("  Tx Immed:  %d\n",comstat.fTxim);
  4330.                     printf("  In Que:    %d\n",comstat.cbInQue);
  4331.                     printf("  Out Que:   %d\n",comstat.cbOutQue);
  4332. #endif /* BETADEBUG */
  4333.                     if ( errorflags && deblog )
  4334.                     {
  4335.                         if ( errorflags & CE_RXOVER )
  4336.                             debug(F110,"ClearCommError","Receive Queue overflow",0);
  4337.                         if ( errorflags & CE_OVERRUN )
  4338.                             debug(F110,"ClearCommError","Receive Overrun error",0);
  4339.                         if ( errorflags & CE_RXPARITY )
  4340.                             debug(F110,"ClearCommError","Receive Parity error",0);
  4341.                         if ( errorflags & CE_FRAME )
  4342.                             debug(F110,"ClearCommError","Receive Framing error",0);
  4343.                         if ( errorflags & CE_BREAK )
  4344.                             debug(F110,"ClearCommError","Break detected",0);
  4345.                         if ( errorflags & CE_TXFULL )
  4346.                             debug(F110,"ClearCommError","TX Queue is full",0);
  4347.                         if ( errorflags & CE_PTO )
  4348.                             debug(F110,"ClearCommError","LPTx Timeout",0);
  4349.                         if ( errorflags & CE_IOE )
  4350.                             debug(F110,"ClearCommError","LPTx I/O Error",0);
  4351.                         if ( errorflags & CE_DNS )
  4352.                             debug(F110,"ClearCommError","LPTx Device Not Selected",0);
  4353.                         if ( errorflags & CE_OOP )
  4354.                             debug(F110,"ClearCommError","LPTx Out Of Paper",0);
  4355.                     }
  4356.                     if ( deblog ) {
  4357.                         debug(F111,"ClearCommError","Cts Hold",comstat.fCtsHold);
  4358.                         debug(F111,"ClearCommError","Dsr Hold",comstat.fDsrHold);
  4359.                         debug(F111,"ClearCommError","Rlsd Hold",comstat.fRlsdHold);
  4360.                         debug(F111,"ClearCommError","Xoff Hold",comstat.fXoffHold);
  4361.                         debug(F111,"ClearCommError","Xoff Sent",comstat.fXoffSent);
  4362.                         debug(F111,"ClearCommError","Eof",comstat.fEof);
  4363.                         debug(F111,"ClearCommError","Tx Immed",comstat.fTxim);
  4364.                         debug(F111,"ClearCommError","In Que",comstat.cbInQue);
  4365.                         debug(F111,"ClearCommError","Out Que",comstat.cbOutQue);
  4366.                     }
  4367.                     }
  4368.                     ow = -1;
  4369.                     Sleep(100); /* take a breather */
  4370.                 }
  4371.                 continue;
  4372.             }
  4373.             else if ( error == ERROR_OPERATION_ABORTED )
  4374.             {
  4375.                 debug(F100,"getOverlappedIndex OPERATION ABORTED","",0);
  4376.                 ResetEvent( overlapped_write[ow].hEvent ) ;
  4377.                 ow_inuse[ow] = FALSE ;
  4378.                 break;
  4379.             }
  4380.             else
  4381.             {
  4382.                 LPVOID lpMsgBuf;
  4383.                 int    freebuf = 1;
  4384.                 if ( !FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
  4385.                                     FORMAT_MESSAGE_FROM_SYSTEM |
  4386.                                     FORMAT_MESSAGE_IGNORE_INSERTS,
  4387.                                     NULL,
  4388.                                     error,
  4389.                                      MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  4390.                                      (LPTSTR) &lpMsgBuf,
  4391.                                      0,
  4392.                                      NULL)) {
  4393.                     lpMsgBuf = "";
  4394.                     freebuf = 0;
  4395.                 }
  4396.                 debug(F111,"getOverlappedIndex Overlapped I/O Error",
  4397.                        (char *) lpMsgBuf, error) ;
  4398.                 if ( freebuf )
  4399.                     LocalFree(lpMsgBuf);
  4400.  
  4401.                 if ( serial ) {
  4402.                     DWORD errorflags ;
  4403.                     COMSTAT comstat ;
  4404.                     ClearCommError( (HANDLE) ttyfd, &errorflags, &comstat ) ;
  4405.                     debug(F101,"getOverlappedIndex ClearCommError",
  4406.                            "",errorflags) ;
  4407.                     if ( errorflags && deblog )
  4408.                     {
  4409.                         if ( errorflags & CE_RXOVER )
  4410.                             debug(F110,"ClearCommError","Receive Queue overflow",0);
  4411.                         if ( errorflags & CE_OVERRUN )
  4412.                             debug(F110,"ClearCommError","Receive Overrun error",0);
  4413.                         if ( errorflags & CE_RXPARITY )
  4414.                             debug(F110,"ClearCommError","Receive Parity error",0);
  4415.                         if ( errorflags & CE_FRAME )
  4416.                             debug(F110,"ClearCommError","Receive Framing error",0);
  4417.                         if ( errorflags & CE_BREAK )
  4418.                             debug(F110,"ClearCommError","Break detected",0);
  4419.                         if ( errorflags & CE_TXFULL )
  4420.                             debug(F110,"ClearCommError","TX Queue is full",0);
  4421.                         if ( errorflags & CE_PTO )
  4422.                             debug(F110,"ClearCommError","LPTx Timeout",0);
  4423.                         if ( errorflags & CE_IOE )
  4424.                             debug(F110,"ClearCommError","LPTx I/O Error",0);
  4425.                         if ( errorflags & CE_DNS )
  4426.                             debug(F110,"ClearCommError","LPTx Device Not Selected",0);
  4427.                         if ( errorflags & CE_OOP )
  4428.                             debug(F110,"ClearCommError","LPTx Out Of Paper",0);
  4429.                     }
  4430.                     if ( deblog ) {
  4431.                         debug(F111,"ClearCommError","Cts Hold",comstat.fCtsHold);
  4432.                         debug(F111,"ClearCommError","Dsr Hold",comstat.fDsrHold);
  4433.                         debug(F111,"ClearCommError","Rlsd Hold",comstat.fRlsdHold);
  4434.                         debug(F111,"ClearCommError","Xoff Hold",comstat.fXoffHold);
  4435.                         debug(F111,"ClearCommError","Xoff Sent",comstat.fXoffSent);
  4436.                         debug(F111,"ClearCommError","Eof",comstat.fEof);
  4437.                         debug(F111,"ClearCommError","Tx Immed",comstat.fTxim);
  4438.                         debug(F111,"ClearCommError","In Que",comstat.cbInQue);
  4439.                         debug(F111,"ClearCommError","Out Que",comstat.cbOutQue);
  4440.                     }
  4441.                 }
  4442.                 ResetEvent( overlapped_write[ow].hEvent ) ;
  4443.                 ow_inuse[ow] = FALSE ;
  4444.                 break;
  4445.             }
  4446.         }
  4447.         debug(F111,"getOverlappedIndex COMPLETE","ow",ow);
  4448.         debug(F111,"getOverlappedIndex COMPLETE",ow_ptr[ow],ow);
  4449.         debug(F111,"getOverlappedIndex COMPLETE","nActuallyWritten",
  4450.                nActuallyWritten);
  4451.     }
  4452.  
  4453.     debug(F111,"GetOverlappedIndex","available ow",ow);
  4454.     return ow ;
  4455. }
  4456.  
  4457. int
  4458. freeOverlappedComplete( int serial ) {
  4459.     int ow, rc = -1 ;
  4460.  
  4461.     debug(F100,"freeOverlappedComplete","",0);
  4462.  
  4463. #ifdef COMMENT
  4464.     if ( owwait )       /* if owwait, then we will wait for completion */
  4465.         return ;        /* before attempting the next write            */
  4466. #endif /* COMMENT */
  4467.  
  4468.     /* free any which are complete */
  4469.     for ( ow=0 ; ow<maxow ; ow++ ) {
  4470.         if ( ow_inuse[ow] ) {
  4471.             if ( !owwait && !HasOverlappedIoCompleted(&overlapped_write[ow]) )
  4472.                 continue;
  4473.  
  4474.             if ( GetOverlappedResult( (HANDLE) ttyfd,
  4475.                                       &overlapped_write[ow],
  4476.                                       &nActuallyWritten, owwait ) )
  4477.             {
  4478.                 debug(F111,"freeOverlappedIndex COMPLETE","ow",ow);
  4479.                 debug(F111,"freeOverlappedIndex COMPLETE",ow_ptr[ow],ow);
  4480.                 debug(F111,"freeOverlappedIndex COMPLETE","nActuallyWritten",
  4481.                        nActuallyWritten);
  4482.                 ow_inuse[ow] = FALSE ;
  4483.                 ResetEvent( overlapped_write[ow].hEvent ) ;
  4484.                 rc = nActuallyWritten ;
  4485.             }
  4486.             else
  4487.             {
  4488.                 DWORD error = GetLastError() ;
  4489.                 if ( error == ERROR_IO_INCOMPLETE ) {
  4490.                     debug(F111,"freeOverlappedIndex ERROR_IO_INCOMPLETE","ow",ow);
  4491.                     debug(F111,"freeOverlappedIndex waiting to complete",ow_ptr[ow],ow);
  4492.                     continue;
  4493.                 }
  4494.                 else if ( error == ERROR_OPERATION_ABORTED )
  4495.                 {
  4496.                     debug(F111,"freeOverlappedIndex OPERATION ABORTED","ow",ow);
  4497.                     debug(F111,"freeOverlappedIndex OPERATION ABORTED",ow_ptr[ow],ow);
  4498.                     ow_inuse[ow] = FALSE ;
  4499.                     // ResetEvent( overlapped_write[ow].hEvent ) ;
  4500.                     rc = -1;
  4501.                 }
  4502.                 else
  4503.                 {
  4504.                     debug(F101,"freeOverlappedComplete Overlapped I/O Error",
  4505.                            "",error ) ;
  4506.                     if ( serial ) {
  4507.                     DWORD errorflags ;
  4508.                     COMSTAT comstat ;
  4509.                     ClearCommError( (HANDLE) ttyfd, &errorflags, &comstat ) ;
  4510.                     debug(F101,"freeOverlappedComplete ClearCommError",
  4511.                            "",errorflags) ;
  4512.                     if ( errorflags && deblog )
  4513.                     {
  4514.                         if ( errorflags & CE_RXOVER )
  4515.                             debug(F110,"ClearCommError","Receive Queue overflow",0);
  4516.                         if ( errorflags & CE_OVERRUN )
  4517.                             debug(F110,"ClearCommError","Receive Overrun error",0);
  4518.                         if ( errorflags & CE_RXPARITY )
  4519.                             debug(F110,"ClearCommError","Receive Parity error",0);
  4520.                         if ( errorflags & CE_FRAME )
  4521.                             debug(F110,"ClearCommError","Receive Framing error",0);
  4522.                         if ( errorflags & CE_BREAK )
  4523.                             debug(F110,"ClearCommError","Break detected",0);
  4524.                         if ( errorflags & CE_TXFULL )
  4525.                             debug(F110,"ClearCommError","TX Queue is full",0);
  4526.                         if ( errorflags & CE_PTO )
  4527.                             debug(F110,"ClearCommError","LPTx Timeout",0);
  4528.                         if ( errorflags & CE_IOE )
  4529.                             debug(F110,"ClearCommError","LPTx I/O Error",0);
  4530.                         if ( errorflags & CE_DNS )
  4531.                             debug(F110,"ClearCommError","LPTx Device Not Selected",0);
  4532.                         if ( errorflags & CE_OOP )
  4533.                             debug(F110,"ClearCommError","LPTx Out Of Paper",0);
  4534.                     }
  4535.                     }
  4536.                     ResetEvent( overlapped_write[ow].hEvent ) ;
  4537.                     ow_inuse[ow] = FALSE ;
  4538.                     rc = -1 ;
  4539.                 }
  4540.             }
  4541.         }
  4542.     }
  4543.     return rc ;
  4544. }
  4545. #endif /* NT */
  4546.  
  4547. /*  T T X O U T -- Similar to ttxin, but for writing.  */
  4548. /*                 Performs conversions as necessary.  */
  4549. /*
  4550.   Outputs all n characters of s, or else fails with -2 if the
  4551.   connection is broken, or with -1 upon some other kind of error.
  4552.   Relies on ttol() or os2_netxout() to perform the real work.
  4553. */
  4554.  
  4555. int
  4556. ttxout(char *s, int n) {
  4557.     int rc = 0, i=0 ;
  4558. #ifndef NOLOCAL
  4559.     extern int tt_pacing;               /* output pacing */
  4560.  
  4561.     if ( tt_pacing != 0 )
  4562.     {
  4563.         if ( ttprty ) {
  4564.             for ( ;i<n;i++ ) {
  4565.                 ttoc(dopar(s[i]));
  4566.                 msleep(tt_pacing);
  4567.             }
  4568.         }
  4569.     }
  4570.     else
  4571. #endif /* NOLOCAL */
  4572.     {
  4573.         if ( ttprty ) {
  4574.             for ( ;i<n;i++ ) {
  4575.                 s[i] = dopar(s[i]);
  4576.             }
  4577.         }
  4578.  
  4579.         if (network)
  4580.             rc = os2_netxout(s,n);
  4581.         else
  4582.             rc = ttol(s,n);
  4583.     }
  4584.     return(rc);
  4585. }
  4586.  
  4587. #ifdef NT
  4588. int
  4589. OverlappedWrite( int serial, char * chars, int charsleft )
  4590. {
  4591.     DWORD i ;
  4592.     int ow = 0, iopending = 0 ;
  4593.     int rc = 0;
  4594.  
  4595.     debug(F111,"OverlappedWrite","charsleft",charsleft);
  4596.     ow = getOverlappedIndex(serial) ;
  4597.  
  4598.     if ( ow_size[ow] < charsleft ) {
  4599.         if ( ow_ptr[ow] ) {
  4600.             debug(F111,"OverlappedWrite","free(ow_ptr[ow])",ow);
  4601.             free( ow_ptr[ow] );
  4602.             ow_ptr[ow] = NULL;
  4603.             ow_size[ow] = 0;
  4604.         }
  4605.  
  4606.         ow_ptr[ow] = (char *) malloc( charsleft * 2 );
  4607.         if ( !ow_ptr[ow] ) {
  4608.             debug(F110,"OverlappedWrite","malloc() failed",0);
  4609.             return -1;
  4610.         }
  4611.         ow_size[ow] = charsleft * 2 ;
  4612.     }
  4613.  
  4614.     debug(F111,"OverlappedWrite chars to send",ow_ptr[ow],charsleft);
  4615.     memcpy( ow_ptr[ow], chars, charsleft );
  4616.  
  4617.     if ( overlapped_write[ow].hEvent == (HANDLE) -1 )
  4618.     {
  4619.         overlapped_write[ow].hEvent = CreateEvent( NULL,    // no security
  4620.                                                    TRUE,    // explicit reset req
  4621.                                                    FALSE,   // initial event reset
  4622.                                                    NULL ) ; // no name
  4623.         if ( overlapped_write[ow].hEvent == (HANDLE) -1 )
  4624.             debug(F101,"Overlapped Write CreateEvent error","",GetLastError() ) ;
  4625.     }
  4626.     overlapped_write[ow].Offset = overlapped_write[ow].OffsetHigh = 0 ;
  4627.     ResetEvent( overlapped_write[ow].hEvent ) ;
  4628.     nActuallyWritten = 0 ;
  4629.  
  4630.     if ( !WriteFile( (HANDLE) ttyfd, ow_ptr[ow], charsleft, &nActuallyWritten,
  4631.                      &overlapped_write[ow]) )
  4632.     {
  4633.         DWORD error = GetLastError() ;
  4634.         if ( error != ERROR_IO_PENDING )
  4635.         {
  4636.             debug(F101,"OverlappedWrite WriteFile - real error occurred","",error) ;
  4637.             ResetEvent( overlapped_write[ow].hEvent ) ;
  4638.             ow_inuse[ow] = FALSE ;
  4639.             return -1 ;
  4640.         }
  4641.         else {
  4642.             debug(F111,"OverlappedWrite WriteFile ERROR_IO_PENDING","ow",ow) ;
  4643.             ow_inuse[ow] = TRUE ;
  4644.             rc = charsleft;
  4645.             iopending = TRUE ;
  4646.         }
  4647.     }
  4648.     else {
  4649.         debug(F111,"OverlappedWrite WriteFile COMPLETE","nActuallyWritten",
  4650.                nActuallyWritten) ;
  4651.         rc = nActuallyWritten;
  4652.         ResetEvent( overlapped_write[ow].hEvent ) ;
  4653.         ow_inuse[ow] = FALSE ;
  4654.     }
  4655.  
  4656.     i = freeOverlappedComplete(serial) ;
  4657.     if ( owwait && iopending )
  4658.         rc = i ;
  4659.  
  4660.     return(rc);
  4661. }
  4662.  
  4663.  
  4664. int
  4665. OverlappedWriteInit( void )
  4666. {
  4667.     int i;
  4668.     for ( i=0;i<maxow;i++ )
  4669.         ow_inuse[i] = FALSE;
  4670.     return(0);
  4671. }
  4672.  
  4673. static int OldReadPending = FALSE ;
  4674. static int NextReadPending = 0;
  4675.  
  4676. #ifdef NEWRDCH
  4677. int
  4678. OverlappedReadInit( void )
  4679. {
  4680.     int i;
  4681.  
  4682.     debug(F111,"OverlappedReadInit","OldReadPending",OldReadPending);
  4683.  
  4684.     if ( OldReadPending )
  4685.         OverlappedReadCleanup();
  4686.  
  4687.     if ( owwait )
  4688.         return(0);
  4689.  
  4690.     for ( i=0; i < maxow; i++ ) {
  4691.         if ( overlapped_read[i].hEvent == (HANDLE) -1 ) {
  4692.             overlapped_read[i].hEvent = CreateEvent( NULL,   /* no security */
  4693.                                                      TRUE,   /* explicit reset req */
  4694.                                                      FALSE,  /* initial event set */
  4695.                                                      NULL    /* no name */
  4696.                                                      );
  4697.             }
  4698.             if (overlapped_read[i].hEvent == (HANDLE) -1)
  4699.                 debug(F101,"OverlappedRead CreateEvent error","",GetLastError() ) ;
  4700.             overlapped_read[i].Offset = overlapped_read[i].OffsetHigh = 0 ;
  4701.             or_ptr[i] = malloc(32768);
  4702.             if ( or_ptr[i] == NULL ) {
  4703.                 debug(F101,"OverlappedRead malloc error","",GetLastError() ) ;
  4704.                 or_size[i] = 0;
  4705.             }
  4706.             else
  4707.                 or_size[i] = 32768;
  4708.             ResetEvent( overlapped_read[i].hEvent );
  4709.             ReadFile((HANDLE) ttyfd, or_ptr[i], or_size[i], &or_read[i],
  4710.                       &overlapped_read[i]);
  4711.     }
  4712.     OldReadPending = TRUE;
  4713.     return(1);
  4714. }
  4715.  
  4716. int
  4717. OverlappedReadFlush( void )
  4718. {
  4719. }
  4720.  
  4721. int
  4722. OverlappedReadCleanup( void )
  4723. {
  4724.     int i;
  4725.     OverlappedReadFlush();
  4726.  
  4727.     for ( i=0; i < 5; i++ ) {
  4728.         if ( overlapped_read[i].hEvent != (HANDLE) -1 ) {
  4729.             CloseHandle(overlapped_read[i].hEvent);
  4730.             overlapped_read[i].hEvent = (HANDLE) -1;
  4731.         }
  4732.         overlapped_read[i].Offset = overlapped_read[i].OffsetHigh = 0 ;
  4733.         free(or_ptr[i]);
  4734.         or_ptr[i];
  4735.         or_size[i] = 0;
  4736.     }
  4737.     OldReadPending = FALSE;
  4738.     return(1);
  4739. }
  4740.  
  4741. int
  4742. OverlappedDataWaiting( void )
  4743. {
  4744.     int i;
  4745.     int count = 0;
  4746.     for ( i=0;i<maxow;i++ )
  4747.         count += or_read[i];
  4748.     return(count);
  4749. }
  4750.  
  4751. int
  4752. WaitForOverlappedReadData( int timo )
  4753. {
  4754.     int rc=0;
  4755.     if ( !OldReadPending )
  4756.         return TRUE;
  4757.  
  4758.     if ( OverlappedDataWaiting() )
  4759.         return TRUE;
  4760.  
  4761.     rc = WaitForSingleObjectEx( overlapped_read[NextReadPending].hEvent,
  4762.         timo < 0 ? -timo : timo == 0 ? -1 :timo*1000, TRUE );
  4763.     if ( rc != WAIT_OBJECT_0 )
  4764.         return FALSE;
  4765.     return TRUE;
  4766. }
  4767.  
  4768. int
  4769. OverlappedRead( int serial, char * buf, int bufsize, int timo )
  4770. {
  4771.     int len=0;
  4772.  
  4773.  
  4774. #ifdef BETADEBUG
  4775.     if ( bufsize < 32768 )
  4776.         printf("bufsize too small (%d)- potential data loss\n",
  4777.                 bufsize);
  4778. #endif /* BETADEBUG */
  4779.  
  4780.     if ( !OldReadPending ) {
  4781.         debug(F110,"rdch","!OldReadPending",0);
  4782.         OverlappedReadInit();
  4783.     }
  4784.  
  4785.     debug(F111,"rdch","NextReadPending",NextReadPending);
  4786.  
  4787.     if (OldReadPending
  4788. #ifdef COMMENT
  4789.          ||         !ReadFile((HANDLE) ttyfd,
  4790.                     buf,
  4791.                     bufsize,
  4792.                     &nActuallyRead,
  4793.                     &overlapped_read)
  4794. #endif /* COMMENT */
  4795.          ) {
  4796.         DWORD error = GetLastError() ;
  4797.         nActuallyRead = 0;
  4798.         if ( OldReadPending || error == ERROR_IO_PENDING ) {
  4799.             int timedout=FALSE;
  4800. #ifndef COMMENT
  4801.             debug(F100,"rdch ReadFile ERROR_IO_PENDING","",0);
  4802. #endif /* COMMENT */
  4803.             while(!GetOverlappedResult( (HANDLE) ttyfd,
  4804.                                         &overlapped_read[NextReadPending],
  4805.                                         &nActuallyRead,
  4806.                                         FALSE )
  4807.                    ) {
  4808.                 DWORD error = GetLastError() ;
  4809.                 if ( error == ERROR_IO_INCOMPLETE ) {
  4810.                     int rc=0;
  4811.                     debug(F100,"rdch ReadFile ERROR_IO_INCOMPLETE","",0);
  4812.                     if ( timedout ) {
  4813.                         debug(F110,"rdch ReadFile","timedout",0);
  4814.                         OldReadPending = TRUE;
  4815.                         return(-1);
  4816.                     }
  4817.                     rc = WaitForSingleObjectEx( overlapped_read[NextReadPending].hEvent,
  4818.                                                 timo, TRUE ) ;
  4819.                     debug(F111,"rdch","NextReadPending",NextReadPending);
  4820.                     debug(F111,"rdch WaitForSingleObjectEx","rc",rc);
  4821.                     if ( rc != WAIT_OBJECT_0 )
  4822.                         timedout = TRUE;
  4823.                     continue;
  4824.                 } else if ( error == ERROR_OPERATION_ABORTED ) {
  4825.                     debug(F100,"rdch ReadFile OPERATION ABORTED","",0);
  4826.                     ResetEvent( overlapped_read[NextReadPending].hEvent ) ;
  4827.                     if ( nActuallyRead > 0 )
  4828.                         memcpy(buf,or_ptr[NextReadPending],
  4829.                                 bufsize<nActuallyRead?bufsize:nActuallyRead);
  4830.                     ReadFile((HANDLE) ttyfd, or_ptr[NextReadPending],
  4831.                               or_size[NextReadPending],
  4832.                               &or_read[NextReadPending],
  4833.                               &overlapped_read[NextReadPending]);
  4834.                     or_read[NextReadPending] = 0;
  4835.                     NextReadPending++;
  4836.                     NextReadPending %= maxow;
  4837.                     if ( nActuallyRead > 0 )
  4838.                         return(nActuallyRead);
  4839.                     else
  4840.                         return (-1); /* fdc */
  4841.                 } else {
  4842.                     if ( serial ) {
  4843.                     DWORD errorflags ;
  4844.                     COMSTAT comstat ;
  4845.                     debug(F101,"rdch ReadFile Overlapped I/O Error",
  4846.                            "",error);
  4847.                     ClearCommError( (HANDLE) ttyfd,
  4848.                                     &errorflags,
  4849.                                     &comstat );
  4850.                     debug(F101,"rdch ClearCommError","",errorflags);
  4851.                     if ( errorflags && deblog )
  4852.                     {
  4853.                         if ( errorflags & CE_RXOVER )
  4854.                             debug(F110,"ClearCommError","Receive Queue overflow",0);
  4855.                         if ( errorflags & CE_OVERRUN )
  4856.                             debug(F110,"ClearCommError","Receive Overrun error",0);
  4857.                         if ( errorflags & CE_RXPARITY )
  4858.                             debug(F110,"ClearCommError","Receive Parity error",0);
  4859.                         if ( errorflags & CE_FRAME )
  4860.                             debug(F110,"ClearCommError","Receive Framing error",0);
  4861.                         if ( errorflags & CE_BREAK )
  4862.                             debug(F110,"ClearCommError","Break detected",0);
  4863.                         if ( errorflags & CE_TXFULL )
  4864.                             debug(F110,"ClearCommError","TX Queue is full",0);
  4865.                         if ( errorflags & CE_PTO )
  4866.                             debug(F110,"ClearCommError","LPTx Timeout",0);
  4867.                         if ( errorflags & CE_IOE )
  4868.                             debug(F110,"ClearCommError","LPTx I/O Error",0);
  4869.                         if ( errorflags & CE_DNS )
  4870.                             debug(F110,"ClearCommError","LPTx Device Not Selected",0);
  4871.                         if ( errorflags & CE_OOP )
  4872.                             debug(F110,"ClearCommError","LPTx Out Of Paper",0);
  4873.                     }
  4874.                     if ( deblog ) {
  4875.                         debug(F111,"ClearCommError","Cts Hold",comstat.fCtsHold);
  4876.                         debug(F111,"ClearCommError","Dsr Hold",comstat.fDsrHold);
  4877.                         debug(F111,"ClearCommError","Rlsd Hold",comstat.fRlsdHold);
  4878.                         debug(F111,"ClearCommError","Xoff Hold",comstat.fXoffHold);
  4879.                         debug(F111,"ClearCommError","Xoff Sent",comstat.fXoffSent);
  4880.                         debug(F111,"ClearCommError","Eof",comstat.fEof);
  4881.                         debug(F111,"ClearCommError","Tx Immed",comstat.fTxim);
  4882.                         debug(F111,"ClearCommError","In Que",comstat.cbInQue);
  4883.                         debug(F111,"ClearCommError","Out Que",comstat.cbOutQue);
  4884.                     }
  4885.                     }
  4886.                     ResetEvent( overlapped_read[NextReadPending].hEvent ) ;
  4887.                     if ( nActuallyRead > 0 )
  4888.                         memcpy(buf,or_ptr[NextReadPending],
  4889.                                 bufsize<nActuallyRead?bufsize:nActuallyRead);
  4890.                     ReadFile((HANDLE) ttyfd, or_ptr[NextReadPending],
  4891.                               or_size[NextReadPending],
  4892.                               &or_read[NextReadPending],
  4893.                               &overlapped_read[NextReadPending]);
  4894.                     or_read[NextReadPending] = 0;
  4895.                     NextReadPending++;
  4896.                     NextReadPending %= maxow;
  4897.                     if ( nActuallyRead > 0 ) {
  4898.                         return(nActuallyRead);
  4899.                     }
  4900.                     return -1;
  4901.                 }
  4902.             }
  4903.         } else {
  4904.             if ( serial ) {
  4905.             DWORD errorflags ;
  4906.             COMSTAT comstat ;
  4907.             debug(F101,"rdch ReadFile - real error occurred","",error) ;
  4908.             ClearCommError( (HANDLE) ttyfd,
  4909.                             &errorflags,
  4910.                             &comstat );
  4911.             debug(F101,"rdch ClearCommError","",errorflags);
  4912.             if ( errorflags && deblog )
  4913.             {
  4914.                 if ( errorflags & CE_RXOVER )
  4915.                     debug(F110,"ClearCommError","Receive Queue overflow",0);
  4916.                 if ( errorflags & CE_OVERRUN )
  4917.                     debug(F110,"ClearCommError","Receive Overrun error",0);
  4918.                 if ( errorflags & CE_RXPARITY )
  4919.                     debug(F110,"ClearCommError","Receive Parity error",0);
  4920.                 if ( errorflags & CE_FRAME )
  4921.                     debug(F110,"ClearCommError","Receive Framing error",0);
  4922.                 if ( errorflags & CE_BREAK )
  4923.                     debug(F110,"ClearCommError","Break detected",0);
  4924.                 if ( errorflags & CE_TXFULL )
  4925.                     debug(F110,"ClearCommError","TX Queue is full",0);
  4926.                 if ( errorflags & CE_PTO )
  4927.                     debug(F110,"ClearCommError","LPTx Timeout",0);
  4928.                 if ( errorflags & CE_IOE )
  4929.                     debug(F110,"ClearCommError","LPTx I/O Error",0);
  4930.                 if ( errorflags & CE_DNS )
  4931.                     debug(F110,"ClearCommError","LPTx Device Not Selected",0);
  4932.                 if ( errorflags & CE_OOP )
  4933.                     debug(F110,"ClearCommError","LPTx Out Of Paper",0);
  4934.             }
  4935.             if ( deblog ) {
  4936.                 debug(F111,"ClearCommError","Cts Hold",comstat.fCtsHold);
  4937.                 debug(F111,"ClearCommError","Dsr Hold",comstat.fDsrHold);
  4938.                 debug(F111,"ClearCommError","Rlsd Hold",comstat.fRlsdHold);
  4939.                 debug(F111,"ClearCommError","Xoff Hold",comstat.fXoffHold);
  4940.                 debug(F111,"ClearCommError","Xoff Sent",comstat.fXoffSent);
  4941.                 debug(F111,"ClearCommError","Eof",comstat.fEof);
  4942.                 debug(F111,"ClearCommError","Tx Immed",comstat.fTxim);
  4943.                 debug(F111,"ClearCommError","In Que",comstat.cbInQue);
  4944.                 debug(F111,"ClearCommError","Out Que",comstat.cbOutQue);
  4945.             }
  4946.             }
  4947.             ResetEvent( overlapped_read[NextReadPending].hEvent ) ;
  4948.             if ( nActuallyRead > 0 )
  4949.                 memcpy(buf,or_ptr[NextReadPending],
  4950.                         bufsize<nActuallyRead?bufsize:nActuallyRead);
  4951.             ReadFile((HANDLE) ttyfd, or_ptr[NextReadPending],
  4952.                       or_size[NextReadPending],
  4953.                       &or_read[NextReadPending],
  4954.                       &overlapped_read[NextReadPending]);
  4955.             or_read[NextReadPending] = 0;
  4956.             NextReadPending++;
  4957.             NextReadPending %= maxow;
  4958.             if ( nActuallyRead > 0 ) {
  4959.                 return(nActuallyRead);
  4960.             }
  4961.             return -2 ;
  4962.         }
  4963.     }
  4964.     ResetEvent( overlapped_read[NextReadPending].hEvent ) ;
  4965. #ifndef COMMENT
  4966.     debug(F101,"rdch nActuallyRead","",nActuallyRead ) ;
  4967.     debug(F101,"rdch overlapped_read.Offset","",
  4968.            overlapped_read[NextReadPending].Offset) ;
  4969. #endif /* COMMENT */
  4970.     if ( nActuallyRead > 0 )
  4971.         memcpy(buf,or_ptr[NextReadPending],
  4972.                 bufsize<nActuallyRead?bufsize:nActuallyRead);
  4973.     ReadFile((HANDLE) ttyfd, or_ptr[NextReadPending],
  4974.               or_size[NextReadPending],
  4975.               &or_read[NextReadPending],
  4976.               &overlapped_read[NextReadPending]);
  4977.     or_read[NextReadPending] = 0;
  4978.     NextReadPending++;
  4979.     NextReadPending %= maxow;
  4980.     return(nActuallyRead);
  4981. }
  4982. #endif /* NEWRDCH */
  4983. #endif /* NT */
  4984.  
  4985.  
  4986. /*  T T O L  --  Similar to "ttinl", but for writing.  */
  4987. #ifdef CK_ENCRYPTION
  4988. static CHAR * xpacket = NULL;
  4989. static int nxpacket = 0;
  4990. #endif /* CK_ENCRYPTION */
  4991.  
  4992. int
  4993. ttol(CHAR *s, int n) {
  4994.     UINT i;
  4995.     int  rc = 0 ;
  4996.     int  charsleft;
  4997.     CHAR *chars;
  4998. #ifdef CKXXCHAR
  4999.     extern int dblflag;                 /* For SET SEND DOUBLE-CHAR */
  5000.     extern short dblt[];
  5001.     CHAR *p = NULL, *p2, *s2, c;
  5002.     int n2 = 0;
  5003.  
  5004.     /*  Double any characters that must be doubled.  */
  5005.     debug(F101,"ttol dblflag","",dblflag);
  5006.     if (dblflag) {
  5007.         p = (CHAR *) malloc(n + n + 1);
  5008.         if (p) {
  5009.             s2 = s;
  5010.             p2 = p;
  5011.             n2 = 0;
  5012.             while (*s2) {
  5013.                 c = *s2++;
  5014.                 *p2++ = c;
  5015.                 n2++;
  5016.                 if (dblt[(unsigned) c] & 2) {
  5017.                     *p2++ = c;
  5018.                     n2++;
  5019.                 }
  5020.             }
  5021.             s = p;
  5022.             n = n2;
  5023.         }
  5024.     }
  5025. #endif /* CKXXCHAR */
  5026.  
  5027. #ifdef CK_ENCRYPTION
  5028. /*
  5029.   This is to avoid encrypting a packet that is already encrypted, e.g.
  5030.   when we resend a packet directly out of the packet buffer, and also to
  5031.   avoid encrypting a constant (literal) string, which can cause a memory
  5032.   fault.
  5033. */
  5034.     if (TELOPT_ME(TELOPT_ENCRYPTION)) {
  5035.         int x;
  5036.         if (nxpacket < n) {
  5037.             if (xpacket) {
  5038.                 free(xpacket);
  5039.                 xpacket = NULL;
  5040.                 nxpacket = 0;
  5041.             }
  5042.             x = n > 10240 ? n : 10240;
  5043.             xpacket = (CHAR *)malloc(x);
  5044.             if (!xpacket) {
  5045.                 fprintf(stderr,"ttol malloc failure\n");
  5046.                 return(-1);
  5047.             } else
  5048.               nxpacket = x;
  5049.         }
  5050.         memcpy((char *)xpacket,(char *)s,n);
  5051.         s = xpacket;
  5052.     }
  5053. #endif /* CK_ENCRYPTION */
  5054.  
  5055.  
  5056.     chars = s;
  5057.     charsleft = n;
  5058.  
  5059.     while ( rc >= 0 && charsleft > 0 ) {
  5060. #ifdef NETCONN
  5061.         if (network) {
  5062.             debug(F111,"ttol()","charsleft",charsleft);
  5063.             rc = os2_nettol(chars,charsleft);
  5064.             debug(F111,"ttol()","os2_nettol() returns",rc);
  5065.         } else {
  5066. #endif /* NETCONN */
  5067. #ifdef COMMENT
  5068.             if (ttchk() < 0)
  5069.                 rc = -1 ;               /* Not open. */
  5070.             else
  5071. #endif /* COMMENT */
  5072.             {
  5073. #ifdef NT
  5074.                 rc = OverlappedWrite( TRUE, chars, charsleft );
  5075. #else /* NT */
  5076.                 if(DosWrite(ttyfd,chars,charsleft,(PVOID)&i))
  5077.                     rc = -1 ;
  5078.                 else
  5079.                     rc = i ;
  5080. #endif /* NT */
  5081.             }
  5082. #ifdef NETCONN
  5083.         }
  5084. #endif /* NETCONN */
  5085.  
  5086.         if ( rc >= 0 ) {
  5087.             charsleft -= rc ;
  5088.             chars += rc ;
  5089.         }
  5090.     }
  5091.     debug( F101, "ttol returns","",rc >= 0 ? (n-charsleft) : rc ) ;
  5092.  
  5093. #ifdef CKXXCHAR
  5094.     if (p) free(p);
  5095. #endif /* CKXXCHAR */
  5096.     if ( rc < 0 ) {
  5097.         if ( ttchk() < 0 )
  5098.             return -2;          /* connection dropped */
  5099.         else
  5100.             return -1;          /* soft error - timeout ? */
  5101.     }
  5102.     else
  5103.         return( n - charsleft ) ;
  5104. }
  5105.  
  5106.  
  5107. /*  T T O C  --  Output a character to the communication line  */
  5108. int
  5109. ttoc(char c) {
  5110.     int rc = 0 ;
  5111. #ifdef NT
  5112.     DWORD i ;
  5113.     int ow = 0 ;
  5114. #else /* NT */
  5115.     UINT i;
  5116. #endif /* NT */
  5117.     if (ttyfd == -1
  5118. #ifdef CK_TAPI
  5119.          || (tttapi && ttyfd == -2)
  5120. #endif /* CK_TAPI */
  5121. ) return(-1);           /* Not open. */
  5122. #ifdef NETCONN
  5123.     if (network)
  5124.         return os2_nettoc(c);
  5125. #endif /* NETCONN */
  5126. #ifdef NT
  5127. #ifndef COMMENT
  5128.      rc = OverlappedWrite( TRUE, &c, 1 );
  5129. #else /* COMMENT */
  5130.     ow = getOverlappedIndex() ;
  5131.  
  5132.     if ( ow_size[ow] < 1 ) {
  5133.         if ( ow_ptr[ow] ) {
  5134.             free( ow_ptr[ow] );
  5135.             ow_ptr[ow] = NULL;
  5136.             ow_size[ow] = 0;
  5137.         }
  5138.  
  5139.         ow_ptr[ow] = (char *) malloc( 128 );
  5140.         if ( !ow_ptr[ow] ) {
  5141.             return -1;
  5142.         }
  5143.         ow_size[ow] = 128 ;
  5144.     }
  5145.     ow_ptr[ow][0] = c;
  5146.     ow_ptr[ow][1] = NUL;
  5147.     debug(F111,"ttoc chars to send",ow_ptr[ow],1);
  5148.  
  5149.     if ( overlapped_write[ow].hEvent == (HANDLE) -1 )
  5150.     {
  5151.         overlapped_write[ow].hEvent = CreateEvent( NULL,    // no security
  5152.                                                    TRUE,    // explicit reset req
  5153.                                                    FALSE,   // initial event reset
  5154.                                                    NULL ) ; // no name
  5155.         if ( overlapped_write[ow].hEvent == (HANDLE) -1 )
  5156.         {
  5157.             debug(F101,"ttoc CreateEvent error","",GetLastError() ) ;
  5158.         }
  5159.     }
  5160.     overlapped_write[ow].Offset = overlapped_write[ow].OffsetHigh = 0 ;
  5161.     ResetEvent( overlapped_write[ow].hEvent ) ;
  5162.  
  5163.     nActuallyWritten = 0 ;
  5164.     if ( !WriteFile( (HANDLE) ttyfd, ow_ptr[ow], 1, &nActuallyWritten,
  5165.                      &overlapped_write[ow]) )
  5166.     {
  5167.         DWORD error = GetLastError() ;
  5168.         if ( error != ERROR_IO_PENDING )
  5169.         {
  5170.             debug(F101,"ttoc WriteFile - real error occurred","",error) ;
  5171.             ResetEvent( overlapped_write[ow].hEvent ) ;
  5172.             ow_inuse[ow] = FALSE ;
  5173.             return -1 ;
  5174.         }
  5175.         else
  5176.             ow_inuse[ow] = TRUE ;
  5177.     }
  5178.     else {
  5179.         ResetEvent( overlapped_write[ow].hEvent ) ;
  5180.         ow_inuse[ow] = FALSE ;
  5181.     }
  5182. #ifndef COMMENT
  5183.     debug(F101,"ttoc nActuallyWritten","",nActuallyWritten ) ;
  5184. #endif /* COMMENT */
  5185.  
  5186.     freeOverlappedComplete() ;
  5187.     rc = 1 ;
  5188. #endif /* COMMENT */
  5189. #else /* NT */
  5190.     if(DosWrite(ttyfd,&c,1,(PVOID)&i))
  5191.        rc = -1;
  5192.     else rc = i;
  5193. #endif /* NT */
  5194.     return rc ;
  5195. }
  5196.  
  5197. #ifndef NOTTOCI
  5198. #define NEWTTOCI
  5199. #endif /* NOTTOCI */
  5200.  
  5201. /*  T T O C I  --  Output a character to the communication line immediately */
  5202. #ifdef NEWTTOCI
  5203. int
  5204. ttoci(char c) {
  5205.     int x;
  5206.     BYTE i;
  5207.     ULONG Data = 0L ;
  5208. #ifdef NT
  5209.    DWORD errors ;
  5210.    COMSTAT comstat ;
  5211. #endif /* NT */
  5212.  
  5213.     if (ttyfd == -1
  5214. #ifdef CK_TAPI
  5215.          || (tttapi && ttyfd == -2)
  5216. #endif /* CK_TAPI */
  5217. ) return(-1);          /* Not open. */
  5218. #ifdef NETCONN
  5219.     if (network)
  5220.         return os2_nettoc(c);
  5221. #endif /* NETCONN */
  5222.  
  5223. #ifdef NT
  5224.     if ( ttoc(c) )                      /* write the character first */
  5225.         return(0);
  5226.  
  5227.     /* if an error occurs, then try to clear it and try again */
  5228.     ClearCommError( (HANDLE) ttyfd, &errors, &comstat ) ;
  5229.     if ( errors && deblog )
  5230.     {
  5231.         debug( F101, "ttoci: ClearCommError errors","",errors ) ;
  5232.         if ( errors & CE_RXOVER )
  5233.             debug(F110,"ClearCommError","Receive Queue overflow",0);
  5234.         if ( errors & CE_OVERRUN )
  5235.             debug(F110,"ClearCommError","Receive Overrun error",0);
  5236.         if ( errors & CE_RXPARITY )
  5237.             debug(F110,"ClearCommError","Receive Parity error",0);
  5238.         if ( errors & CE_FRAME )
  5239.             debug(F110,"ClearCommError","Receive Framing error",0);
  5240.         if ( errors & CE_BREAK )
  5241.             debug(F110,"ClearCommError","Break detected",0);
  5242.         if ( errors & CE_TXFULL )
  5243.             debug(F110,"ClearCommError","TX Queue is full",0);
  5244.         if ( errors & CE_PTO )
  5245.             debug(F110,"ClearCommError","LPTx Timeout",0);
  5246.         if ( errors & CE_IOE )
  5247.             debug(F110,"ClearCommError","LPTx I/O Error",0);
  5248.         if ( errors & CE_DNS )
  5249.             debug(F110,"ClearCommError","LPTx Device Not Selected",0);
  5250.         if ( errors & CE_OOP )
  5251.             debug(F110,"ClearCommError","LPTx Out Of Paper",0);
  5252.     }
  5253.     Data = comstat.fCtsHold |
  5254.            comstat.fDsrHold << 1 |
  5255.            comstat.fRlsdHold << 2 |
  5256.            comstat.fXoffHold << 3 |
  5257.            comstat.fXoffSent << 4 |
  5258.            comstat.fEof << 5 |
  5259.            comstat.fTxim << 6 ;
  5260.     if ( Data ) {
  5261.         debug( F101,"ttoci: COM Status","",Data) ;
  5262.  
  5263.         if ( (flow == FLO_XONX &&
  5264.               comstat.fXoffHold) ||
  5265.              (flow == FLO_RTSC &&
  5266.                comstat.fCtsHold) )
  5267.             return(Data) ;
  5268.     }
  5269.     return ttoc(c) == 1 ? 0 : -1;
  5270. #else /* NT */
  5271.     x =
  5272.      DosDevIOCtl(&Data,sizeof(Data),0,0,ASYNC_GETCOMMSTATUS,IOCTL_ASYNC,ttyfd);
  5273.     if ( Data ) {
  5274.         debug( F101,"ttoci: Query COM Status","",Data) ;
  5275.         return(Data) ;
  5276.     }
  5277.     x = DosWrite(ttyfd,&c,1,(PVOID)&i) ;
  5278.     if (x) {
  5279.         debug(F101,"ttoci failure status","",x);
  5280.         return(x);
  5281.     } else return(0);
  5282. #endif /* NT */
  5283. }
  5284.  
  5285. #else /* NEWTTOCI */
  5286.  
  5287. int
  5288. ttoci(char c) {
  5289.     int x;
  5290.     if (ttyfd == -1
  5291. #ifdef CK_TAPI
  5292.          || (tttapi && ttyfd == -2)
  5293. #endif /* CK_TAPI */
  5294.          )
  5295.         return(-1);           /* Not open. */
  5296. #ifdef NETCONN
  5297.     if (network)
  5298.         return os2_nettoc(c);
  5299. #endif /* NETCONN */
  5300. #ifdef NT
  5301.     return TransmitCommChar( ttyfd, c ) ? 0 : -1 ;
  5302. #else /* NT */
  5303.     x =  DosDevIOCtl(NULL,0,&c,sizeof(c),ASYNC_TRANSMITIMM,IOCTL_ASYNC,ttyfd);
  5304. #endif /* NT */
  5305.     if (x) {
  5306.         debug(F101,"ttoci failure status","",x);
  5307.         return(x);
  5308.     } else return(0);
  5309. }
  5310. #endif /* NEWTTOCI */
  5311.  
  5312. static int inlret ;
  5313. static CHAR * inldest, inleol, inlstart ;
  5314. static int inlmax, inlturn ;
  5315.  
  5316. static int
  5317. ckcgetc(int dummy) {
  5318.     return ttinc(1);
  5319. }
  5320.  
  5321. #ifndef NOXFER
  5322. /*  T T I N L  --  Read a packet from the communication device.  */
  5323. /*
  5324.   blah blah
  5325. */
  5326. ttinl(CHAR *dest, int max, int timo, CHAR eol, CHAR start, int turn) {
  5327.     extern int xfrcan, xfrchr, xfrnum;  /* Defined in ckcmai.c */
  5328.     extern int priority;
  5329.     int x=0, c=0, ccn=0;
  5330.     /* register */ int i=0, j=0, m=0, n=0;      /* Local variables */
  5331.     int timespent = 0 ;
  5332.     int flag = 0;
  5333.     unsigned char ch;
  5334.     int pktlen = -1;
  5335.     int lplen = 0;
  5336.     int havelen = 0;
  5337.     extern int server, srvidl, rpsiz ;
  5338.     int srvtimer=0 ;
  5339.     int sopmask = 0xff;
  5340. #ifdef CKXXCHAR
  5341.     extern short dblt[];                /* Ignore-character table */
  5342.     extern int ignflag;
  5343. #endif /* CKXXCHAR */
  5344. #ifdef IKS_OPTION
  5345.     extern int stchr;
  5346. #endif /* IKS_OPTION */
  5347. #ifdef STREAMING
  5348.     extern int streaming;
  5349.     extern int sndtyp;
  5350. #endif /* STREAMING */
  5351.     extern int tcp_incoming, idletmo;
  5352.     int canread=0, haveread=0;
  5353. #define INXBUF_SIZE 10240
  5354.     static char inxbuf[INXBUF_SIZE];
  5355.     time_t start_time = time(NULL);
  5356.  
  5357.     if (ttyfd == -1
  5358. #ifdef CK_TAPI
  5359.          || (tttapi && ttyfd == -2)
  5360. #endif /* CK_TAPI */
  5361.          )
  5362.         return(-3);          /* Not open. */
  5363.  
  5364.     inlret = -1 ;                       /* Assume we are going to fail */
  5365.     inldest = dest ;
  5366.     inlmax = max ;
  5367.     inleol = eol ;
  5368.     inlstart = start ;
  5369.     inlturn = turn ;
  5370.  
  5371.     debug(F101,"ttinl max","",max);
  5372.     debug(F101,"ttinl timo","",timo);
  5373.     debug(F101,"ttinl network","",network);
  5374.     debug(F101,"ttinl ttnproto","",ttnproto);
  5375.  
  5376.    *dest = '\0';                       /* Clear destination buffer */
  5377.    if (timo < 0) timo = 0;              /* Safety */
  5378.  
  5379.     debug(F101,"ttinl start","",inlstart);
  5380.     flag = 0;                           /* Start of packet flag */
  5381.  
  5382.     ttpmsk = m = (ttprty) ? 0177 : 0377; /* Set parity stripping mask. */
  5383.     sopmask = needpchk ? 0177 : ttpmsk;  /* And SOP mask */
  5384.  
  5385. /* Now read into destination, stripping parity and looking for the */
  5386. /* the packet terminator, and also for two Ctrl-C's typed in a row. */
  5387.  
  5388.     i = 0;                              /* Destination index */
  5389.     debug(F101,"ttinl eol","",inleol);
  5390.  
  5391.     do
  5392.     {
  5393.         canread = ttchk();
  5394.         if ( canread > 0 ) {
  5395.             int blah=pktlen-i+5;
  5396.             int pleaseread;
  5397.  
  5398.             if ( !havelen || blah < 0 ) {
  5399. #ifdef COMMENT
  5400.                 /* causes us to read too much data when the peer as been issued */
  5401.                 /* a SET SEND PACKET-SIZE which is smaller than our SET RECEIVE */
  5402.                 /* PACKET-SIZE value.  */
  5403.                 blah = rpsiz < LOCAL_ECHO_BUFSIZE ? rpsiz : LOCAL_ECHO_BUFSIZE;
  5404. #else
  5405.                 /* Enough to get the size */
  5406.                 blah = 40;
  5407. #endif
  5408.             }
  5409.  
  5410.             debug(F111,"ttinl","blah",blah);
  5411.             debug(F111,"ttinl","rpsiz",rpsiz);
  5412.             debug(F111,"ttinl","canread",canread);
  5413.  
  5414.             if ( blah > 0 && blah < canread && blah < INXBUF_SIZE )
  5415.                 pleaseread = blah;
  5416.             else if ( canread < INXBUF_SIZE )
  5417.                 pleaseread = canread;
  5418.             else
  5419.                 pleaseread = INXBUF_SIZE;
  5420.  
  5421.             debug(F111,"ttinl","will attempt to read",pleaseread);
  5422.  
  5423.             haveread = ttxin( pleaseread,inxbuf);
  5424. #ifdef IKS_OPTION
  5425.             if (haveread >= 0) {
  5426.                 inlstart = stchr;
  5427.                 if (TELOPT_ME(TELOPT_KERMIT) &&
  5428.                      !TELOPT_SB(TELOPT_KERMIT).kermit.me_start &&
  5429.                      server)
  5430.                 {   /* I'm not in Server mode */
  5431.                     debug(F100,"ttinl TELOPT_ME_KERMIT && !me_start && server","",0);
  5432.                     if ( haveread ) {
  5433.                         debug(F111,"ttinl putting back chars","haveread",
  5434.                                haveread);
  5435.                         le_puts(inxbuf, haveread);
  5436.                     }
  5437.                     return(-2);         /* End server mode */
  5438.                 }
  5439. #ifdef IKSD
  5440.                 if (TELOPT_U(TELOPT_KERMIT) &&
  5441.                      TELOPT_SB(TELOPT_KERMIT).kermit.u_start &&
  5442.                      !inserver && server && !tcp_incoming)
  5443.                 {   /* Remote in Server mode */
  5444.                     if ( haveread ) {
  5445.                         debug(F111,"ttinl putting back chars","haveread",
  5446.                                haveread);
  5447.                         le_puts(inxbuf, haveread);
  5448.                     }
  5449.                     return(-2);         /* End server mode */
  5450.                 }
  5451. #endif /* IKSD */
  5452.             }
  5453. #endif /* IKS_OPTION */
  5454.         }
  5455.         else if ( canread == 0 ) {
  5456.             debug(F100,"ttinl canread == 0","",0);
  5457. #ifdef STREAMING
  5458.             if (streaming && sndtyp == 'D')
  5459.                 return(0);
  5460. #endif /* STREAMING */
  5461.  
  5462.             if (
  5463. #ifdef IKSD
  5464.                  !inserver &&
  5465. #endif /* IKSD */
  5466.                  conchk() > 0 ) {
  5467.                 debug(F100,"ttinl conchk() > 0","",0);
  5468.                 return(-1);         /* User pressed a key */
  5469.             }
  5470. #ifdef COMMENT
  5471. #ifdef STREAMING
  5472.             if (streaming && sndtyp == 'D')
  5473.                 return(-1);
  5474. #endif /* STREAMING */
  5475. #endif /* COMMENT */
  5476.             if ((c=ttinc((timo||srvidl)?1:0))<0) {
  5477.                 if ( c < -1 ) {
  5478.                     debug(F101,"ttinl ttinc() returned error","",c);
  5479.                     ttclos(0);
  5480.                     return(-3);
  5481.                 }
  5482.                 else {
  5483.                     debug(F101,"ttinl ttinc() returned timeout","",c);
  5484.                     timespent = time(NULL) - start_time;
  5485.                     if ( server && srvidl )
  5486.                     {
  5487.                         if ( timespent > srvidl )
  5488.                         {
  5489. #ifdef IKSD
  5490.                             if ( inserver ) {
  5491.                                 printf("\r\nIKS IDLE TIMEOUT: %d sec\r\n", srvidl);
  5492.                                 doexit(GOOD_EXIT,xitsta);
  5493.                             }
  5494. #endif /* IKSD */
  5495.                             idletmo = 1;
  5496.                             return(-2) ;
  5497.                         }
  5498.                     }
  5499.                     continue;
  5500.                 }
  5501.             } else if (c == IAC && (network && IS_TELNET()
  5502. #ifdef IKSD
  5503.                                       || inserver
  5504. #endif /* IKSD */
  5505.                                      )) {
  5506.                 int tx=0;
  5507.                 extern int duplex;
  5508.                 debug(F100,"ttinl got IAC","",0);
  5509.                 if ((tx = tn_doop((CHAR)(c & 0xff),duplex,ckcgetc)) == 0) {
  5510.                     continue;
  5511.                 }
  5512.                 else if (tx == -1) {    /* I/O error */
  5513.                     return(-3);
  5514.                 }
  5515.                 else if (tx == -2 || tx == -3) { /* Connection failed. */
  5516.                     ttclos(0) ;
  5517.                     return(-3);
  5518.                 }
  5519.                 else if (tx == 1) {     /* ECHO change */
  5520.                     duplex = 1; /* Get next char */
  5521.                     continue;
  5522.                 }
  5523.                 else if (tx == 2) {     /* ECHO change */
  5524.                     duplex = 0; /* Get next char */
  5525.                     continue;
  5526.                 }
  5527.                 else if (tx == 3) {     /* Quoted IAC */
  5528.                     c = 255;    /* proceeed with it. */
  5529.                 }
  5530. #ifdef IKS_OPTION
  5531.                 else if (tx == 4) {
  5532.                     if (TELOPT_SB(TELOPT_KERMIT).kermit.u_start &&
  5533.                          server
  5534.                          /* Remote in Server mode */
  5535. #ifdef IKSD
  5536.                         && !inserver
  5537. #endif /* IKSD */
  5538.                          ) {
  5539.                         debug(F100,"ttinl u_start && server && !inserver","",0);
  5540.                         return(-2);         /* End server mode */
  5541.                     }
  5542.                     if (!TELOPT_SB(TELOPT_KERMIT).kermit.me_start &&
  5543.                          server) {
  5544.                         debug(F100,"ttinl me_start && server","",0);
  5545.                         return(-2);
  5546.                     }
  5547.                 }
  5548.                 else if (tx == 5) {     /* IKS State Change */
  5549.                     extern int stchr;
  5550.                     inlstart = stchr;
  5551.                 }
  5552. #endif /* IKS_OPTION */
  5553.                 else if (tx == 6) {
  5554.                     /* Remote Logout */
  5555.                     ttclos(0);
  5556. #ifdef IKSD
  5557.                     if (inserver && !local)
  5558.                         doexit(GOOD_EXIT,0);
  5559.                     else
  5560. #endif /* IKSD */
  5561.                         return(-2);
  5562.                 }
  5563.                 else continue;  /* Unknown, get next char */
  5564.             }
  5565.             inxbuf[0] = (char) c;
  5566.             haveread = 1;
  5567.         }
  5568.         else /* canread < 0 == error */ {
  5569.             debug(F101,"ttinl ttchk() returned error","",n);
  5570.             ttclos(0);
  5571.             return (-3);         /* i/o error or no connection */
  5572.         }
  5573.  
  5574.         hexdump("ttinl() ttin?() returned",inxbuf,haveread);
  5575.         j = 0;
  5576.         while ( j < haveread )
  5577.         {
  5578.             n = inxbuf[j++];
  5579.             ch = n & 0xff;
  5580. #ifdef CKXXCHAR
  5581.             if (ignflag)
  5582.                 if (dblt[(unsigned) ch] & 1) /* Character to ignore? */
  5583.                     continue;
  5584. #endif /* CKXXCHAR */
  5585.  
  5586.             /* Check cancellation */
  5587.             if (xfrcan && ((ch & ttpmsk) == xfrchr)) {
  5588.                 if (++ccn >= xfrnum) {  /* If xfrnum in a row, bail out. */
  5589.                     if (xfrchr < 32)
  5590.                       printf("^%c...\r\n",(char)(xfrchr+64));
  5591.                     else
  5592.                       printf("Canceled...\r\n");
  5593.                     return(-2);
  5594.                 }
  5595.             } else ccn = 0;             /* No cancellation, reset counter, */
  5596.  
  5597.             if (flag == 0) {            /* Find the Start of Packet */
  5598.                 if ((n & sopmask) == inlstart) /* Got it! */
  5599.                     flag = 1;
  5600.                 else {                  /* Keep looking */
  5601.                     debug(F101,"ttinl skipping","",n);
  5602. #ifndef NOLOCAL
  5603. #ifdef BETATEST_X
  5604.                     cwrite(n);
  5605. #endif /* BETATEST */
  5606. #endif /* NOLOCAL */
  5607.                     continue;
  5608.                 }
  5609.             }
  5610.             inldest[i++] = n & ttpmsk;
  5611.  
  5612.             if (!havelen) {
  5613.                 /* Try to compute the packet length */
  5614.                 if (i == 2) {
  5615.                     pktlen = xunchar(inldest[1] & ttpmsk);
  5616.                     havelen = (pktlen > 1);
  5617.                     debug(F101,"ttinl length","",pktlen);
  5618.                 } else if (i == 5 && pktlen == 0) {
  5619.                     lplen = xunchar(inldest[4] & ttpmsk);
  5620.                 } else if (i == 6 && pktlen == 0) {
  5621.                     pktlen = lplen * 95 + xunchar(inldest[5] & ttpmsk) + 5;
  5622.                     havelen = 1;
  5623.                     debug(F101,"ttinl extended length","",pktlen);
  5624.                 }
  5625.  
  5626. /*
  5627.   Suppose we looked at the sequence number here and found it was out of
  5628.   range?  This would mean either (a) incoming packets had SOP unprefixed
  5629.   and we are out of sync, or (b) the packet is damaged.  Since (a) is bad
  5630.   practice, let's ignore it.  So what should we do here if we know the
  5631.   packet is damaged?
  5632.  
  5633.    1. Nothing -- keep trying to read the packet till we find what we think
  5634.       is the end, or we time out, and let the upper layer decide what to
  5635.       do.  But since either the packet is corrupt or we are out of sync,
  5636.       our criterion for finding the end does not apply and we are likely
  5637.       to time out (or swallow a piece of the next packet) if our assumed
  5638.       length is too long.  (This was the behavior prior to version 7.0.)
  5639.  
  5640.    2. set flag = 0 and continue?  This would force us to wait for the
  5641.       next packet to come in, and therefore (in the nonwindowing case),
  5642.       would force a timeout in the other Kermit.
  5643.  
  5644.    3. set flag = 0 and continue, but only if the window size is > 1 and
  5645.       the window is not blocked?  Talk about cheating!
  5646.  
  5647.    4. Return a failure code and let the upper layer decide what to do.
  5648.       This should be equivalent to 3, but without the cheating.  So let's
  5649.       do it that way...
  5650. */
  5651.                 if (i == 3) {                   /* Peek at sequence number */
  5652.                     x = xunchar(dest[2]);       /* If it's not in range... */
  5653.                     if (x < 0 || x > 63) {
  5654.                         debug(F111,"ttinl xunchar(dest[2])",dest,x);
  5655.                         return(-1);             /* return a nonfatal error */
  5656.                     }
  5657.                 }
  5658.             }
  5659.             else if ((i > pktlen+1) &&
  5660.                      (!inlturn || (inlturn && (n & ttpmsk) == inleol)) ) {
  5661.                 /* We have the end of the packet */
  5662.                 inldest[i] = '\0';              /* Terminate the string, */
  5663.  
  5664.                 if (deblog) {
  5665.                     if ((n & ttpmsk) != inleol) {
  5666.                         debug(F101,"ttinl EOP length","",pktlen);
  5667.                         debug(F101,"ttinl i","",i);
  5668.                     } else debug(F101,"ttinl got eol","",inleol);
  5669.  
  5670.                     debug(F101,"ttinl needpchk","",needpchk);
  5671.                     debug(F101,"ttinl ttprty","",ttprty);
  5672.                     debug(F101,"ttinl ttpmsk","",ttpmsk);
  5673.                 }
  5674.  
  5675.                 /* Parity checked yet? */
  5676.                 if ( needpchk ) {
  5677.                     if (ttprty == 0) {
  5678.                         if ((ttprty = parchk(inldest,inlstart,i)) > 0) { /* No */
  5679.                             int j;
  5680.                             debug(F101,"ttinl senses parity","",ttprty);
  5681.                             debug(F110,"ttinl packet before",inldest,0);
  5682.                             ttpmsk = 0x7f;
  5683.                             for (j = 0; j < i; j++)
  5684.                                 inldest[j] &= ttpmsk;   /* Strip parity from packet */
  5685.                             debug(F110,"ttinl packet after ",inldest,0);
  5686.                         } else ttprty = 0;      /* restore if parchk error */
  5687.                     }
  5688.                     sopmask = ttprty;
  5689.                     needpchk = 0;
  5690.                 }
  5691.                 hexdump("ttinl got",inldest,i);
  5692.                 inlret = i ;
  5693.                 srvtimer = 0 ;
  5694.  
  5695.                 /* if there is anything left in the buffer, we better save it */
  5696.                 /* But first, throw out chars that are before the start char  */
  5697.                 while (++j<haveread) {
  5698.                     if (inxbuf[j] == inlstart)
  5699.                         break;
  5700.                     debug(F101,"ttinl discarding","",inxbuf[j]);
  5701.                 }
  5702.                 if ( j < haveread ) {
  5703.                     debug(F111,"ttinl putting back chars","haveread - j",
  5704.                            haveread-j);
  5705.                     le_puts( &inxbuf[j], haveread-j );
  5706.                 }
  5707. #ifdef STREAMING
  5708.                 if (streaming && sndtyp == 'D') {
  5709.                     debug(F110,"ttinl quitting","streaming && sndtyp == 'D'",0);
  5710.                     return(-1);
  5711.                 }
  5712. #endif /* STREAMING */
  5713.  
  5714.                 return inlret;
  5715.             }
  5716.         }   /* end of while() */
  5717.     } while ((i < inlmax-1)  &&  (!timo || (timespent < timo)));
  5718.     /* end of while() */
  5719.  
  5720.     debug(F111,"ttinl timout","timespent",timespent); /* Get here on timout. */
  5721.     /* debug(F110," with",(char *) dest,0); */
  5722.     inlret = -1 ;
  5723.     debug(F101,"ttinl return inlret","",inlret);
  5724.     return inlret ;
  5725. }
  5726. #endif /* NOXFER */
  5727.  
  5728. /*  T T I N C --  Read a character from the communication line  */
  5729.  
  5730. /* The time should be in secs for consistency with the other modules in    */
  5731. /* kermit.  To retain the option of using times of less than 1s a negative */
  5732. /* parameter is interpreted as meaning multiples of 0.01s                  */
  5733. /* On failure, returns -1 or other negative myread error code,             */
  5734. /* or -2 if connection is broken or ttyfd < 0.                             */
  5735. /* or -3 if session limit has expired,                                     */
  5736. /* or -4 if something or other...                                          */
  5737.  
  5738. int rdch(int timo);
  5739. int
  5740. ttinc(int timo) {
  5741.     int m, i=0, j=0;
  5742.     char ch = 0;
  5743. #ifdef NT
  5744.     int tt, tr, interval;
  5745. #endif /* NT */
  5746.     int t ;
  5747. #ifdef SESLIMIT
  5748.     extern int seslimit;
  5749. #endif /* SESLIMIT */
  5750.  
  5751.     m = (ttprty) ? 0177 : 0377;         /* Parity stripping mask. */
  5752.  
  5753.     if ( ttpush >= 0 )
  5754.     {
  5755.         debug(F111,"ttinc","ttpush",ttpush);
  5756.         ch = ttpush;
  5757.         ttpush = -1;
  5758.         return(ch & m);
  5759.     }
  5760.  
  5761.     if ( LocalEchoData ) {
  5762.         if ( le_getchar(&ch) > 0 ) {
  5763.             debug(F111,"ttinc le_inbuf","ch",ch);
  5764.             return(ch & m);
  5765.         }
  5766.     }
  5767.  
  5768.     if (ttyfd == -1
  5769. #ifdef CK_TAPI
  5770.          || (tttapi && ttyfd == -2)
  5771. #endif /* CK_TAPI */
  5772.          ) return(-2);          /* Not open. */
  5773.  
  5774. #ifdef SESLIMIT
  5775.     /* Session Limits go here          */
  5776.     /* if time() - start_time > limit  */
  5777.     if ( seslimit ) {
  5778.         time_t t = time(NULL) - start_time;
  5779.         if ( t  > seslimit ) {
  5780.             debug(F111,"ttinc","Session Limit Exceeded",seslimit);
  5781.             return(-3);
  5782.         } 
  5783. #ifndef IKSDONLY
  5784.         else if ( downloaded && IsConnectMode() ) {
  5785.             if ( warn[0] ) {
  5786.                 popupdemo(VTERM,seslimit - t);
  5787.                 warn[0] = 0;
  5788.             } else if ( warn[1] && t > 300 ) {
  5789.                 popupdemo(VTERM,seslimit - t);
  5790.                 warn[1] = 0;
  5791.             } else if ( warn[2] && t > 600 ) {
  5792.                 popupdemo(VTERM,seslimit - t);
  5793.                 warn[2] = 0;
  5794.             } else if ( warn[3] && t > 840 ) {
  5795.                 popupdemo(VTERM,seslimit - t);
  5796.                 warn[3] = 0;
  5797.             }
  5798.         }
  5799. #endif /* IKSDONLY */
  5800.     }
  5801. #endif /* SESLIMIT */
  5802.  
  5803.     if ( tt_inpacing )
  5804.         msleep(tt_inpacing);
  5805.  
  5806. #ifdef NETCONN
  5807.     if (network) {
  5808.         extern int duplex;
  5809.         if ( !duplex
  5810. #ifdef IKSD
  5811.              || inserver
  5812. #endif /* IKSD */
  5813.              ) {
  5814.             i = os2_netinc(timo);
  5815.             return(i >= 0 ? i & m : i);
  5816.         }
  5817.         else {
  5818.             if ( timo < 0 ) {
  5819.                 j = -timo / 100;
  5820.             } else if ( timo > 0 )
  5821.                 j = timo * 10;
  5822.  
  5823.             do {
  5824.                 if ( LocalEchoData ) {
  5825.                     if ( le_getchar(&ch) > 0 ) {
  5826.                         debug(F111,"ttinc le_inbuf","ch",ch);
  5827.                         return(ch & m);
  5828.                     }
  5829.                 }
  5830.                 i = os2_netinc(-100);
  5831.             } while (timo ? (i==-1 && --j>0) : (i == -1));
  5832.             return(i >= 0 ? i & m : i);
  5833.         }
  5834.     }
  5835. #endif /* NETCONN */
  5836.  
  5837.     if (timo == 0) {                    /* Untimed read. */
  5838.         do {
  5839.             i = rdch(ck_sleepint);
  5840.             if ( i < 0 &&
  5841. #ifdef COMMENT
  5842.                  (ttcarr != CAR_OFF) && /* Carrier dropped */
  5843.                  ((ttgmdm() & BM_DCD) == 0)
  5844. #else /* COMMENT */
  5845.                  (ttchk() < 0)
  5846. #endif /* COMMENT */
  5847.                  )
  5848.                 DialerSend( OPT_KERMIT_HANGUP, 0 ) ;
  5849. #ifdef NTSIG
  5850.             ck_ih();
  5851. #endif /* NTSIG */
  5852.             if ( LocalEchoData ) {
  5853.                 if ( le_getchar(&ch) > 0 ) {
  5854.                     debug(F111,"ttinc le_inbuf","ch",ch);
  5855.                     return(ch & m);
  5856.                 }
  5857.             }
  5858.         } while (i == -1);              /* Wait for a character. */
  5859.         return(i >= 0 ? i & m : i);
  5860.     }
  5861.  
  5862. /* Timed read */
  5863.  
  5864.     if (timo < 0)                       /* Convert to milliseconds */
  5865.     {
  5866.        timo= -timo;
  5867.        t = 0 ;
  5868.     }
  5869.     else
  5870.     {
  5871.        t = timo ;
  5872.        timo = timo * 1000;
  5873.     }
  5874.  
  5875. #ifdef NT
  5876.     tt = timo / ck_sleepint;            /* Break up into chunks */
  5877.     tr = timo % ck_sleepint;            /* Break up into chunks */
  5878.    if ( tt )
  5879.       interval = ck_sleepint + tr / tt ;
  5880.    else
  5881.    {
  5882.       tt = 1 ;
  5883.       interval = tr ;
  5884.    }
  5885.     debug(F111,"ttinc","rdch interval",interval);
  5886.     debug(F111,"ttinc","rdch tries",tt);
  5887.  
  5888.     for (j = 0; j < tt; j++) {          /* to avoid being stuck */
  5889.        i = rdch(interval);              /* in a system call...  */
  5890. #ifdef NTSIG
  5891.        ck_ih();
  5892. #endif /* NTSIG */
  5893.         if (i >= 0)
  5894.             break;
  5895.         else if (i < -1)
  5896.            break;
  5897.         if ( LocalEchoData ) {
  5898.             if ( le_getchar(&ch) > 0 ) {
  5899.                 debug(F111,"ttinc le_inbuf","ch",ch);
  5900.                 return(ch & m);
  5901.             }
  5902.         }
  5903.     }
  5904. #else /* NT */
  5905.     i = rdch(timo);
  5906. #endif /* NT */
  5907.     return( (i < 0) ? i : (i & m) );
  5908. }
  5909.  
  5910. /*  RDCH -- Read characters from the serial port, maintaining an internal
  5911.             buffer of characters for the sake of efficiency.
  5912.             Timeout is specified in milliseconds.
  5913. */
  5914.  
  5915. /*
  5916.    The MustComplete section in this code is required because SIO.SYS at
  5917.    least versions up to 1.45 set the length to buffersize when a SIGINT
  5918.    occurs during the processing of this call.
  5919. */
  5920. #ifdef NEWRDCH
  5921. static int
  5922. rdch(int timo /* ms */) {
  5923.     ULONG Nesting;
  5924. #ifdef NT
  5925.     COMMTIMEOUTS timeouts ;
  5926.     static int OldReadPending = FALSE ;
  5927.     int rc=0;
  5928. #endif /* NT */
  5929.  
  5930.     if ( ttyfd == -1
  5931. #ifdef CK_TAPI
  5932.          || (tttapi && ttyfd == -2)
  5933. #endif /* CK_TAPI */
  5934.          )
  5935.         return -2;                      /* No connection */
  5936.  
  5937.     if (rdchbuf.index == rdchbuf.length) {
  5938.         rdchbuf.index = rdchbuf.length = 0;
  5939.  
  5940.         rmstimer();
  5941.  
  5942.         debug(F111,"NEWRDCH rdch","timo",timo);
  5943.         if ( timo == 0 ) {
  5944. #ifdef NT
  5945.             memset(&timeouts, 0, sizeof(COMMTIMEOUTS)) ;
  5946.             GetCommTimeouts( (HANDLE) ttyfd, &timeouts ) ;
  5947. /*
  5948.   These settings will wait until at least one character
  5949.   is available to be read.  at least in Win95
  5950. */
  5951.             timeouts.ReadIntervalTimeout = MAXDWORD ;
  5952.             timeouts.ReadTotalTimeoutMultiplier = MAXDWORD ;
  5953.             timeouts.ReadTotalTimeoutConstant = 10 ;
  5954.             debug(F111,"NEWRDCH rdch SetCommTimeouts","WriteTotalTimeoutMultiplier",
  5955.                    timeouts.WriteTotalTimeoutMultiplier);
  5956.             debug(F111,"NEWRDCH rdch SetCommTimeouts","WriteTotalTimeoutConstant",
  5957.                    timeouts.WriteTotalTimeoutConstant);
  5958.             SetCommTimeouts( (HANDLE) ttyfd, &timeouts ) ;
  5959. #else /* NT */
  5960.             if (ttydcb.usReadTimeout != 9) {
  5961.                 ttydcb.usReadTimeout = 9;       /* Test every  0.1s per call */
  5962.                 if (DosDevIOCtl(NULL,0,&ttydcb,sizeof(ttydcb),
  5963.                                 ASYNC_SETDCBINFO,1,ttyfd))
  5964.                   return(-1);
  5965.             }
  5966. #endif /* NT */
  5967.         } else {
  5968. #ifdef NT
  5969.             memset(&timeouts, 0, sizeof(COMMTIMEOUTS) ) ;
  5970.             GetCommTimeouts( (HANDLE) ttyfd, &timeouts ) ;
  5971.             timeouts.ReadIntervalTimeout = MAXDWORD ;
  5972.             timeouts.ReadTotalTimeoutMultiplier = MAXDWORD ;
  5973.             timeouts.ReadTotalTimeoutConstant = timo;
  5974.             debug(F111,"NEWRDCH rdch SetCommTimeouts","WriteTotalTimeoutMultiplier",
  5975.                    timeouts.WriteTotalTimeoutMultiplier);
  5976.             debug(F111,"NEWRDCH rdch SetCommTimeouts","WriteTotalTimeoutConstant",
  5977.                    timeouts.WriteTotalTimeoutConstant);
  5978.             SetCommTimeouts( (HANDLE) ttyfd, &timeouts ) ;
  5979. #else /* NT */
  5980.             if (ttydcb.usReadTimeout != timo) { /* Set timeout value */
  5981.                 ttydcb.usReadTimeout = (timo/10)-1; /* 0.01 sec units.  0 = 0.01 sec */
  5982.                 if (DosDevIOCtl(NULL,0,&ttydcb,sizeof(ttydcb),
  5983.                                 ASYNC_SETDCBINFO,IOCTL_ASYNC,ttyfd))
  5984.                   return(-1);
  5985.             }
  5986. #endif /* NT */
  5987.         }
  5988.  
  5989. #ifdef NT
  5990. #ifndef COMMENT
  5991.         rc = OverlappedRead( TRUE, rdchbuf.buffer, sizeof(rdchbuf.buffer), timo );
  5992.         if ( rc >= 0 )
  5993.             rdchbuf.length = rc;
  5994.         else
  5995.             return(rc);
  5996. #else /* COMMENT */
  5997.         if ( overlapped_read.hEvent == (HANDLE) -1 ) {
  5998.             overlapped_read.hEvent = CreateEvent(
  5999.                                             NULL,   /* no security */
  6000.                                             TRUE,   /* explicit reset req */
  6001.                                             FALSE,  /* initial event set */
  6002.                                             NULL    /* no name */
  6003.                                                 );
  6004.  
  6005.             if (overlapped_read.hEvent == (HANDLE) -1) {
  6006.                 debug(F101,"rdch CreateEvent error","",GetLastError() ) ;
  6007.             }
  6008.         }
  6009.  
  6010.         if ( !OldReadPending ) {
  6011.             overlapped_read.Offset = overlapped_read.OffsetHigh = 0 ;
  6012.             ResetEvent( overlapped_read.hEvent ) ;
  6013.         }
  6014.  
  6015.         if (OldReadPending ||
  6016.              !ReadFile((HANDLE) ttyfd,
  6017.                        rdchbuf.buffer,
  6018.                        sizeof(rdchbuf.buffer),
  6019.                        &nActuallyRead,
  6020.                          &overlapped_read)
  6021.             ) {
  6022.             DWORD error = GetLastError() ;
  6023.             if ( OldReadPending || error == ERROR_IO_PENDING ) {
  6024.                 int timedout=FALSE;
  6025. #ifndef COMMENT
  6026.                 debug(F100,"rdch ReadFile ERROR_IO_PENDING","",0);
  6027. #endif /* COMMENT */
  6028.                 while(!GetOverlappedResult( (HANDLE) ttyfd,
  6029.                                             &overlapped_read,
  6030.                                             &nActuallyRead,
  6031.                                             FALSE )
  6032.                        ) {
  6033.                     DWORD error = GetLastError() ;
  6034.                     if ( error == ERROR_IO_INCOMPLETE ) {
  6035.                         int rc=0;
  6036.                         debug(F100,"rdch ReadFile ERROR_IO_INCOMPLETE","",0);
  6037.                         if ( timedout ) {
  6038.                             debug(F110,"rdch ReadFile","timedout",0);
  6039.                             OldReadPending = TRUE;
  6040.                             return(-1);
  6041.                         }
  6042.                         rc = WaitForSingleObjectEx( overlapped_read.hEvent, timo, TRUE ) ;
  6043.                         debug(F111,"rdch WaitForSingleObjectEx","rc",rc);
  6044.                         if ( rc != WAIT_OBJECT_0 )
  6045.                             timedout = TRUE;
  6046.                         continue;
  6047.                     } else if ( error == ERROR_OPERATION_ABORTED ) {
  6048.                         debug(F100,"rdch ReadFile OPERATION ABORTED","",0);
  6049.                         ResetEvent( overlapped_read.hEvent ) ;
  6050.                         if (nActuallyRead > 0 )
  6051.                             rdchbuf.length = nActuallyRead ;
  6052.                         OldReadPending = FALSE;
  6053.                         return (-1); /* fdc */
  6054.                     } else {
  6055.                         DWORD errorflags ;
  6056.                         COMSTAT comstat ;
  6057.                         debug(F101,"rdch ReadFile Overlapped I/O Error",
  6058.                                "",error);
  6059.                         ClearCommError( (HANDLE) ttyfd,
  6060.                                         &errorflags,
  6061.                                         &comstat );
  6062.                         debug(F101,"rdch ClearCommError","",errorflags);
  6063.                         if ( errorflags && deblog )
  6064.                         {
  6065.                             if ( errorflags & CE_RXOVER )
  6066.                                 debug(F110,"ClearCommError","Receive Queue overflow",0);
  6067.                             if ( errorflags & CE_OVERRUN )
  6068.                                 debug(F110,"ClearCommError","Receive Overrun error",0);
  6069.                             if ( errorflags & CE_RXPARITY )
  6070.                                 debug(F110,"ClearCommError","Receive Parity error",0);
  6071.                             if ( errorflags & CE_FRAME )
  6072.                                 debug(F110,"ClearCommError","Receive Framing error",0);
  6073.                             if ( errorflags & CE_BREAK )
  6074.                                 debug(F110,"ClearCommError","Break detected",0);
  6075.                             if ( errorflags & CE_TXFULL )
  6076.                                 debug(F110,"ClearCommError","TX Queue is full",0);
  6077.                             if ( errorflags & CE_PTO )
  6078.                                 debug(F110,"ClearCommError","LPTx Timeout",0);
  6079.                             if ( errorflags & CE_IOE )
  6080.                                 debug(F110,"ClearCommError","LPTx I/O Error",0);
  6081.                             if ( errorflags & CE_DNS )
  6082.                                 debug(F110,"ClearCommError","LPTx Device Not Selected",0);
  6083.                             if ( errorflags & CE_OOP )
  6084.                                 debug(F110,"ClearCommError","LPTx Out Of Paper",0);
  6085.                         }
  6086.                         if ( deblog ) {
  6087.                             debug(F111,"ClearCommError","Cts Hold",comstat.fCtsHold);
  6088.                             debug(F111,"ClearCommError","Dsr Hold",comstat.fDsrHold);
  6089.                             debug(F111,"ClearCommError","Rlsd Hold",comstat.fRlsdHold);
  6090.                             debug(F111,"ClearCommError","Xoff Hold",comstat.fXoffHold);
  6091.                             debug(F111,"ClearCommError","Xoff Sent",comstat.fXoffSent);
  6092.                             debug(F111,"ClearCommError","Eof",comstat.fEof);
  6093.                             debug(F111,"ClearCommError","Tx Immed",comstat.fTxim);
  6094.                             debug(F111,"ClearCommError","In Que",comstat.cbInQue);
  6095.                             debug(F111,"ClearCommError","Out Que",comstat.cbOutQue);
  6096.                         }
  6097.                         ResetEvent( overlapped_read.hEvent ) ;
  6098.                         if (nActuallyRead > 0 )
  6099.                             rdchbuf.length = nActuallyRead ;
  6100.                         OldReadPending = FALSE;
  6101.                         return -1;
  6102.                     }
  6103.                 }
  6104.             } else {
  6105.                 DWORD errorflags ;
  6106.                 COMSTAT comstat ;
  6107.                 debug(F101,"rdch ReadFile - real error occurred","",error) ;
  6108.                 ClearCommError( (HANDLE) ttyfd,
  6109.                                 &errorflags,
  6110.                                 &comstat );
  6111.                 debug(F101,"rdch ClearCommError","",errorflags);
  6112.                 if ( errorflags && deblog )
  6113.                 {
  6114.                     if ( errorflags & CE_RXOVER )
  6115.                         debug(F110,"ClearCommError","Receive Queue overflow",0);
  6116.                     if ( errorflags & CE_OVERRUN )
  6117.                         debug(F110,"ClearCommError","Receive Overrun error",0);
  6118.                     if ( errorflags & CE_RXPARITY )
  6119.                         debug(F110,"ClearCommError","Receive Parity error",0);
  6120.                     if ( errorflags & CE_FRAME )
  6121.                         debug(F110,"ClearCommError","Receive Framing error",0);
  6122.                     if ( errorflags & CE_BREAK )
  6123.                         debug(F110,"ClearCommError","Break detected",0);
  6124.                     if ( errorflags & CE_TXFULL )
  6125.                         debug(F110,"ClearCommError","TX Queue is full",0);
  6126.                     if ( errorflags & CE_PTO )
  6127.                         debug(F110,"ClearCommError","LPTx Timeout",0);
  6128.                     if ( errorflags & CE_IOE )
  6129.                         debug(F110,"ClearCommError","LPTx I/O Error",0);
  6130.                     if ( errorflags & CE_DNS )
  6131.                         debug(F110,"ClearCommError","LPTx Device Not Selected",0);
  6132.                     if ( errorflags & CE_OOP )
  6133.                         debug(F110,"ClearCommError","LPTx Out Of Paper",0);
  6134.                 }
  6135.                 if ( deblog ) {
  6136.                     debug(F111,"ClearCommError","Cts Hold",comstat.fCtsHold);
  6137.                     debug(F111,"ClearCommError","Dsr Hold",comstat.fDsrHold);
  6138.                     debug(F111,"ClearCommError","Rlsd Hold",comstat.fRlsdHold);
  6139.                     debug(F111,"ClearCommError","Xoff Hold",comstat.fXoffHold);
  6140.                     debug(F111,"ClearCommError","Xoff Sent",comstat.fXoffSent);
  6141.                     debug(F111,"ClearCommError","Eof",comstat.fEof);
  6142.                     debug(F111,"ClearCommError","Tx Immed",comstat.fTxim);
  6143.                     debug(F111,"ClearCommError","In Que",comstat.cbInQue);
  6144.                     debug(F111,"ClearCommError","Out Que",comstat.cbOutQue);
  6145.                 }
  6146.                 ResetEvent( overlapped_read.hEvent ) ;
  6147.                 if (nActuallyRead > 0 )
  6148.                     rdchbuf.length = nActuallyRead ;
  6149.                 OldReadPending = FALSE;
  6150.                 return -2 ;
  6151.             }
  6152.         }
  6153.         ResetEvent( overlapped_read.hEvent ) ;
  6154. #ifndef COMMENT
  6155.         debug(F101,"rdch nActuallyRead","",nActuallyRead ) ;
  6156.         debug(F101,"rdch overlapped_read.Offset","",overlapped_read.Offset) ;
  6157. #endif /* COMMENT */
  6158.         rdchbuf.length = nActuallyRead ;
  6159. #endif /* COMMENT */
  6160. #else /* NT */
  6161.         DosEnterMustComplete( &Nesting ) ;
  6162.         if (DosRead(ttyfd,rdchbuf.buffer,sizeof(rdchbuf.buffer),
  6163.                     &rdchbuf.length)) {
  6164.             rdchbuf.length = 0;
  6165.             DosExitMustComplete( &Nesting );
  6166.             return(-1);
  6167.         }
  6168.         DosExitMustComplete( &Nesting );
  6169. #endif /* NT */
  6170.     }
  6171.  
  6172. #ifndef COMMENT
  6173.     debug(F101,"rdch() index","",rdchbuf.index);
  6174.     debug(F101,"rdch() length","",rdchbuf.length);
  6175. #endif /* COMMENT */
  6176.  
  6177. #ifdef NT
  6178.     OldReadPending = FALSE;
  6179. #endif /* NT */
  6180.     return((rdchbuf.index < rdchbuf.length) ?
  6181.             rdchbuf.buffer[rdchbuf.index++] :
  6182.             -1 );
  6183. }
  6184. #else /* NEWRDCH */
  6185. static int
  6186. rdch(int timo /* ms */) {
  6187.     ULONG Nesting;
  6188. #ifdef NT
  6189.     COMMTIMEOUTS timeouts ;
  6190.     static int OldReadPending = FALSE ;
  6191. #endif /* NT */
  6192.  
  6193.     if ( ttyfd == -1
  6194. #ifdef CK_TAPI
  6195.          || (tttapi && ttyfd == -2)
  6196. #endif /* CK_TAPI */
  6197.          )
  6198.         return -2;                      /* No connection */
  6199.  
  6200.     if (rdchbuf.index == rdchbuf.length) {
  6201.         rdchbuf.index = rdchbuf.length = 0;
  6202.  
  6203.         debug(F111,"OLD rdch","timo",timo);
  6204.         if ( timo == 0 ) {
  6205. #ifdef NT
  6206.             int change = 0;
  6207.             memset(&timeouts, 0, sizeof(COMMTIMEOUTS)) ;
  6208.             GetCommTimeouts( (HANDLE) ttyfd, &timeouts ) ;
  6209. /*
  6210.   These settings will wait until at least one character
  6211.   is available to be read.  at least in Win95
  6212. */              
  6213.             if ( timeouts.ReadIntervalTimeout != MAXDWORD ) {
  6214.                 timeouts.ReadIntervalTimeout = MAXDWORD ;
  6215.                 change++;
  6216.             }
  6217.             if ( timeouts.ReadTotalTimeoutMultiplier != MAXDWORD ) {
  6218.                 timeouts.ReadTotalTimeoutMultiplier = MAXDWORD ;
  6219.                 change++;
  6220.             }
  6221.             if ( timeouts.ReadTotalTimeoutConstant != 10 ) {
  6222.                 timeouts.ReadTotalTimeoutConstant = 10 ;
  6223.                 change++;
  6224.             }
  6225.             if ( change ) {
  6226.                 debug(F111,"OLD rdch SetCommTimeouts","WriteTotalTimeoutMultiplier",
  6227.                        timeouts.WriteTotalTimeoutMultiplier);
  6228.                 debug(F111,"OLD rdch SetCommTimeouts","WriteTotalTimeoutConstant",
  6229.                        timeouts.WriteTotalTimeoutConstant);
  6230.                 SetCommTimeouts( (HANDLE) ttyfd, &timeouts ) ;
  6231.             }
  6232. #else /* NT */
  6233.             if (ttydcb.usReadTimeout != 9) {
  6234.                 ttydcb.usReadTimeout = 9;       /* Test every  0.1s per call */
  6235.                 if (DosDevIOCtl(NULL,0,&ttydcb,sizeof(ttydcb),
  6236.                                 ASYNC_SETDCBINFO,1,ttyfd))
  6237.                   return(-1);
  6238.             }
  6239. #endif /* NT */
  6240.         } else {
  6241. #ifdef NT
  6242.             int change = 0;
  6243.             memset(&timeouts, 0, sizeof(COMMTIMEOUTS) ) ;
  6244.             GetCommTimeouts( (HANDLE) ttyfd, &timeouts ) ;
  6245.             if ( timeouts.ReadIntervalTimeout != MAXDWORD ) {
  6246.                 timeouts.ReadIntervalTimeout = MAXDWORD ;
  6247.                 change++;
  6248.             }
  6249.             if ( timeouts.ReadTotalTimeoutMultiplier != MAXDWORD ) {
  6250.                 timeouts.ReadTotalTimeoutMultiplier = MAXDWORD ;
  6251.                 change++;
  6252.             }
  6253.             if ( timeouts.ReadTotalTimeoutConstant != timo  ) {
  6254.                 timeouts.ReadTotalTimeoutConstant = timo ;
  6255.                 change++;
  6256.             }
  6257.             if ( change ) {
  6258.                 debug(F111,"OLD rdch SetCommTimeouts","WriteTotalTimeoutMultiplier",
  6259.                        timeouts.WriteTotalTimeoutMultiplier);
  6260.                 debug(F111,"OLD rdch SetCommTimeouts","WriteTotalTimeoutConstant",
  6261.                        timeouts.WriteTotalTimeoutConstant);
  6262.                 SetCommTimeouts( (HANDLE) ttyfd, &timeouts ) ;
  6263.             }
  6264. #else /* NT */
  6265.             if (ttydcb.usReadTimeout != timo) { /* Set timeout value */
  6266.                 ttydcb.usReadTimeout = (timo/10)-1; /* 0.01 sec units.  0 = 0.01 sec */
  6267.                 if (DosDevIOCtl(NULL,0,&ttydcb,sizeof(ttydcb),
  6268.                                 ASYNC_SETDCBINFO,IOCTL_ASYNC,ttyfd))
  6269.                   return(-1);
  6270.             }
  6271. #endif /* NT */
  6272.         }
  6273.  
  6274. #ifdef NT
  6275.         if ( overlapped_read[0].hEvent == (HANDLE) -1 ) {
  6276.             overlapped_read[0].hEvent = CreateEvent(
  6277.                                             NULL,   /* no security */
  6278.                                             TRUE,   /* explicit reset req */
  6279.                                             FALSE,  /* initial event set */
  6280.                                             NULL    /* no name */
  6281.                                                 );
  6282.  
  6283.             if (overlapped_read[0].hEvent == (HANDLE) -1) {
  6284.                 debug(F101,"rdch CreateEvent error","",GetLastError() ) ;
  6285.             }
  6286.         }
  6287.  
  6288.         if ( !OldReadPending ) {
  6289.             overlapped_read[0].Offset = overlapped_read[0].OffsetHigh = 0 ;
  6290.             ResetEvent( overlapped_read[0].hEvent ) ;
  6291.         }
  6292.  
  6293.         if (OldReadPending ||
  6294.              !ReadFile((HANDLE) ttyfd,
  6295.                        rdchbuf.buffer,
  6296.                        sizeof(rdchbuf.buffer),
  6297.                        &nActuallyRead,
  6298.                          &overlapped_read[0])
  6299.             ) {
  6300.             DWORD error = GetLastError() ;
  6301.             if ( OldReadPending || error == ERROR_IO_PENDING ) {
  6302.                 int timedout=FALSE;
  6303. #ifndef COMMENT
  6304.                 debug(F100,"rdch ReadFile ERROR_IO_PENDING","",0);
  6305. #endif /* COMMENT */
  6306.                 while(!GetOverlappedResult( (HANDLE) ttyfd,
  6307.                                             &overlapped_read[0],
  6308.                                             &nActuallyRead,
  6309.                                             FALSE )
  6310.                        ) {
  6311.                     DWORD error = GetLastError() ;
  6312.                     if ( error == ERROR_IO_INCOMPLETE ) {
  6313.                         int rc=0;
  6314.                         debug(F100,"rdch ReadFile ERROR_IO_INCOMPLETE","",0);
  6315.                         if ( timedout ) {
  6316.                             debug(F110,"rdch ReadFile","timedout",0);
  6317.                             OldReadPending = TRUE;
  6318.                             return(-1);
  6319.                         }
  6320.                         rc = WaitForSingleObjectEx( overlapped_read[0].hEvent, timo, TRUE ) ;
  6321.                         debug(F111,"rdch WaitForSingleObjectEx","rc",rc);
  6322.                         if ( rc != WAIT_OBJECT_0 )
  6323.                             timedout = TRUE;
  6324.                         continue;
  6325.                     } else if ( error == ERROR_OPERATION_ABORTED ) {
  6326.                         debug(F100,"rdch ReadFile OPERATION ABORTED","",0);
  6327.                         ResetEvent( overlapped_read[0].hEvent ) ;
  6328.                         if (nActuallyRead > 0 )
  6329.                             rdchbuf.length = nActuallyRead ;
  6330.                         OldReadPending = FALSE;
  6331.                         return (-1); /* fdc */
  6332.                     } else {
  6333.                         DWORD errorflags ;
  6334.                         COMSTAT comstat ;
  6335.                         debug(F101,"rdch ReadFile Overlapped I/O Error",
  6336.                                "",error);
  6337.                         ClearCommError( (HANDLE) ttyfd,
  6338.                                         &errorflags,
  6339.                                         &comstat );
  6340.                         debug(F101,"rdch ClearCommError","",errorflags);
  6341.                         if ( errorflags && deblog )
  6342.                         {
  6343.                             if ( errorflags & CE_RXOVER )
  6344.                                 debug(F110,"ClearCommError","Receive Queue overflow",0);
  6345.                             if ( errorflags & CE_OVERRUN )
  6346.                                 debug(F110,"ClearCommError","Receive Overrun error",0);
  6347.                             if ( errorflags & CE_RXPARITY )
  6348.                                 debug(F110,"ClearCommError","Receive Parity error",0);
  6349.                             if ( errorflags & CE_FRAME )
  6350.                                 debug(F110,"ClearCommError","Receive Framing error",0);
  6351.                             if ( errorflags & CE_BREAK )
  6352.                                 debug(F110,"ClearCommError","Break detected",0);
  6353.                             if ( errorflags & CE_TXFULL )
  6354.                                 debug(F110,"ClearCommError","TX Queue is full",0);
  6355.                             if ( errorflags & CE_PTO )
  6356.                                 debug(F110,"ClearCommError","LPTx Timeout",0);
  6357.                             if ( errorflags & CE_IOE )
  6358.                                 debug(F110,"ClearCommError","LPTx I/O Error",0);
  6359.                             if ( errorflags & CE_DNS )
  6360.                                 debug(F110,"ClearCommError","LPTx Device Not Selected",0);
  6361.                             if ( errorflags & CE_OOP )
  6362.                                 debug(F110,"ClearCommError","LPTx Out Of Paper",0);
  6363.                         }
  6364.                         if ( deblog ) {
  6365.                             debug(F111,"ClearCommError","Cts Hold",comstat.fCtsHold);
  6366.                             debug(F111,"ClearCommError","Dsr Hold",comstat.fDsrHold);
  6367.                             debug(F111,"ClearCommError","Rlsd Hold",comstat.fRlsdHold);
  6368.                             debug(F111,"ClearCommError","Xoff Hold",comstat.fXoffHold);
  6369.                             debug(F111,"ClearCommError","Xoff Sent",comstat.fXoffSent);
  6370.                             debug(F111,"ClearCommError","Eof",comstat.fEof);
  6371.                             debug(F111,"ClearCommError","Tx Immed",comstat.fTxim);
  6372.                             debug(F111,"ClearCommError","In Que",comstat.cbInQue);
  6373.                             debug(F111,"ClearCommError","Out Que",comstat.cbOutQue);
  6374.                         }
  6375.                         if ( deblog ) {
  6376.                             debug(F111,"ClearCommError","Cts Hold",comstat.fCtsHold);
  6377.                             debug(F111,"ClearCommError","Dsr Hold",comstat.fDsrHold);
  6378.                             debug(F111,"ClearCommError","Rlsd Hold",comstat.fRlsdHold);
  6379.                             debug(F111,"ClearCommError","Xoff Hold",comstat.fXoffHold);
  6380.                             debug(F111,"ClearCommError","Xoff Sent",comstat.fXoffSent);
  6381.                             debug(F111,"ClearCommError","Eof",comstat.fEof);
  6382.                             debug(F111,"ClearCommError","Tx Immed",comstat.fTxim);
  6383.                             debug(F111,"ClearCommError","In Que",comstat.cbInQue);
  6384.                             debug(F111,"ClearCommError","Out Que",comstat.cbOutQue);
  6385.                         }
  6386.                         ResetEvent( overlapped_read[0].hEvent ) ;
  6387.                         if (nActuallyRead > 0 )
  6388.                             rdchbuf.length = nActuallyRead ;
  6389.                         OldReadPending = FALSE;
  6390.                         return -1;
  6391.                     }
  6392.                 }
  6393.             } else {
  6394.                 DWORD errorflags ;
  6395.                 COMSTAT comstat ;
  6396.                 debug(F101,"rdch ReadFile - real error occurred","",error) ;
  6397.                 ClearCommError( (HANDLE) ttyfd,
  6398.                                 &errorflags,
  6399.                                 &comstat );
  6400.                 debug(F101,"rdch ClearCommError","",errorflags);
  6401.                 if ( errorflags && deblog )
  6402.                 {
  6403.                     if ( errorflags & CE_RXOVER )
  6404.                         debug(F110,"ClearCommError","Receive Queue overflow",0);
  6405.                     if ( errorflags & CE_OVERRUN )
  6406.                         debug(F110,"ClearCommError","Receive Overrun error",0);
  6407.                     if ( errorflags & CE_RXPARITY )
  6408.                         debug(F110,"ClearCommError","Receive Parity error",0);
  6409.                     if ( errorflags & CE_FRAME )
  6410.                         debug(F110,"ClearCommError","Receive Framing error",0);
  6411.                     if ( errorflags & CE_BREAK )
  6412.                         debug(F110,"ClearCommError","Break detected",0);
  6413.                     if ( errorflags & CE_TXFULL )
  6414.                         debug(F110,"ClearCommError","TX Queue is full",0);
  6415.                     if ( errorflags & CE_PTO )
  6416.                         debug(F110,"ClearCommError","LPTx Timeout",0);
  6417.                     if ( errorflags & CE_IOE )
  6418.                         debug(F110,"ClearCommError","LPTx I/O Error",0);
  6419.                     if ( errorflags & CE_DNS )
  6420.                         debug(F110,"ClearCommError","LPTx Device Not Selected",0);
  6421.                     if ( errorflags & CE_OOP )
  6422.                         debug(F110,"ClearCommError","LPTx Out Of Paper",0);
  6423.                 }
  6424.                 if ( deblog ) {
  6425.                     debug(F111,"ClearCommError","Cts Hold",comstat.fCtsHold);
  6426.                     debug(F111,"ClearCommError","Dsr Hold",comstat.fDsrHold);
  6427.                     debug(F111,"ClearCommError","Rlsd Hold",comstat.fRlsdHold);
  6428.                     debug(F111,"ClearCommError","Xoff Hold",comstat.fXoffHold);
  6429.                     debug(F111,"ClearCommError","Xoff Sent",comstat.fXoffSent);
  6430.                     debug(F111,"ClearCommError","Eof",comstat.fEof);
  6431.                     debug(F111,"ClearCommError","Tx Immed",comstat.fTxim);
  6432.                     debug(F111,"ClearCommError","In Que",comstat.cbInQue);
  6433.                     debug(F111,"ClearCommError","Out Que",comstat.cbOutQue);
  6434.                 }
  6435.                 ResetEvent( overlapped_read[0].hEvent ) ;
  6436.                 if (nActuallyRead > 0 )
  6437.                     rdchbuf.length = nActuallyRead ;
  6438.                 OldReadPending = FALSE;
  6439.                 return -2 ;
  6440.             }
  6441.         }
  6442.         ResetEvent( overlapped_read[0].hEvent ) ;
  6443. #ifndef COMMENT
  6444.         debug(F101,"rdch nActuallyRead","",nActuallyRead ) ;
  6445.         debug(F101,"rdch overlapped_read.Offset","",overlapped_read[0].Offset) ;
  6446. #endif /* COMMENT */
  6447.         rdchbuf.length = nActuallyRead ;
  6448. #else /* NT */
  6449.         DosEnterMustComplete( &Nesting ) ;
  6450.         if (DosRead(ttyfd,rdchbuf.buffer,sizeof(rdchbuf.buffer),
  6451.                     &rdchbuf.length)) {
  6452.             rdchbuf.length = 0;
  6453.             DosExitMustComplete( &Nesting );
  6454.             return(-1);
  6455.         }
  6456.         DosExitMustComplete( &Nesting );
  6457. #endif /* NT */
  6458.     }
  6459.  
  6460. #ifdef COMMENT
  6461.     debug(F101,"rdch() index","",rdchbuf.index);
  6462.     debug(F101,"rdch() length","",rdchbuf.length);
  6463. #endif /* COMMENT */
  6464.  
  6465. #ifdef NT
  6466.     OldReadPending = FALSE;
  6467. #endif /* NT */
  6468.     return((rdchbuf.index < rdchbuf.length) ?
  6469.             rdchbuf.buffer[rdchbuf.index++] :
  6470.             -1 );
  6471. }
  6472. #endif /* NEWRDCH */
  6473.  
  6474.  
  6475. /*  T T S C A R R  --  Set ttcarr variable, controlling carrier handling.
  6476.  *
  6477.  *  0 = Off: Always ignore carrier. E.g. you can connect without carrier.
  6478.  *  1 = On: Heed carrier, except during dialing. Carrier loss gives disconnect.
  6479.  *  2 = Auto: For "modem direct": The same as "Off".
  6480.  *            For real modem types: Heed carrier during connect, but ignore
  6481.  *                it anytime else.  Compatible with pre-5A Kermit versions.
  6482.  */
  6483.  
  6484. int
  6485. ttscarr(int carrier)
  6486. {
  6487.     ttcarr = carrier;
  6488.     debug(F101, "ttscarr","",ttcarr);
  6489.     return(ttcarr);
  6490. }
  6491.  
  6492. /*  T T G M D M  --  Get modem signals  */
  6493. /*
  6494.  Looks for the modem signals CTS, DSR, and CTS, and returns those that are
  6495.  on in as its return value, in a bit mask as described for ttwmdm.  Returns:
  6496.  -3 Not implemented
  6497.  -2 if the line does not have modem control
  6498.  -1 on error.
  6499.  >= 0 on success, with a bit mask containing the modem signals that are on.
  6500. */
  6501.  
  6502. int
  6503. ttgmdm() {
  6504. #ifdef NT
  6505.     DWORD ModemStat ;
  6506. #else /* NT */
  6507.     BYTE instat, outstat;
  6508. #endif /* NT */
  6509.     int modem = 0;
  6510.  
  6511.     if (ttyfd == -1
  6512. #ifdef CK_TAPI
  6513.          || (tttapi && ttyfd == -2)
  6514. #endif /* CK_TAPI */
  6515.          )
  6516.         return(-1);
  6517.  
  6518. #ifdef TN_COMPORT
  6519.     if (network)
  6520.         return(tngmdm());
  6521. #endif /* TN_COMPORT */
  6522.  
  6523. #ifdef NT
  6524. #ifdef CK_TAPI
  6525.     if ( tttapi && !tapipass )
  6526.     {
  6527.         HANDLE hModem = NULL;
  6528.  
  6529.         if (ttyfd == -2)
  6530.             return(-1);
  6531.  
  6532.         hModem = GetModemHandleFromLine( (HLINE) 0 );
  6533.         if ( hModem == NULL )
  6534.             return(-1);
  6535.  
  6536.         if (!GetCommModemStatus( hModem, &ModemStat )) {
  6537.             CloseHandle( hModem );
  6538.             return -1 ;
  6539.         }
  6540.         CloseHandle( hModem );
  6541.     }
  6542.     else
  6543. #endif /* CK_TAPI */
  6544.     if (!GetCommModemStatus( (HANDLE) ttyfd, &ModemStat ))
  6545.         return -1 ;
  6546.  
  6547.     if (ModemStat & MS_CTS_ON) modem |= BM_CTS ;
  6548.     if (ModemStat & MS_DSR_ON) modem |= BM_DSR ;
  6549.     if (ModemStat & MS_RING_ON) modem |= BM_RNG ;
  6550.     if (ModemStat & MS_RLSD_ON) modem |= BM_DCD ;
  6551.  
  6552. #else /* NT */
  6553.     if(DosDevIOCtl(&instat,sizeof(instat),NULL,0,
  6554.                    ASYNC_GETMODEMINPUT,IOCTL_ASYNC,ttyfd))
  6555.        return(-1);
  6556.     if(DosDevIOCtl(&outstat,sizeof(outstat),NULL,0,
  6557.                    ASYNC_GETMODEMOUTPUT,IOCTL_ASYNC,ttyfd))
  6558.        return(-1);
  6559.  
  6560.     /* Clear To Send */
  6561.     if (instat & CTS_ON) modem |= BM_CTS;
  6562.     /* Data Set Ready */
  6563.     if (instat & DSR_ON) modem |= BM_DSR;
  6564.     /* Carrier */
  6565.     if (instat & DCD_ON) modem |= BM_DCD;
  6566.     /* Ring Indicate */
  6567.     if (instat & RI_ON)  modem |= BM_RNG;
  6568.  
  6569.     /* Data Terminal Ready */
  6570.     if (outstat & DTR_ON) modem |= BM_DTR;
  6571.     /* Request To Send */
  6572.     if (outstat & RTS_ON) modem |= BM_RTS;
  6573. #endif /* NT */
  6574.     return(modem);
  6575. }
  6576.  
  6577. /*  T T S N D B  --  Send a BREAK signal  */
  6578. int
  6579. ttsndb() {
  6580. #ifdef OS2ONLY
  6581.     MODEMSTATUS ms;
  6582.     UINT data, i;
  6583. #endif /* OS2ONLY */
  6584. #ifdef NETCONN
  6585.     if (network) {
  6586. #ifdef TN_COMPORT
  6587.         if (istncomport()) {
  6588.             if (tnsndb(275L) >= 0)
  6589.                 return(0);
  6590.         }
  6591. #endif /* TN_COMPORT */
  6592.         return(os2_netbreak());
  6593.     }
  6594. #endif /* NETCONN */
  6595. #ifdef NT
  6596.     SetCommBreak( (HANDLE) ttyfd ) ;
  6597.     msleep(275L);
  6598.     ClearCommBreak( (HANDLE) ttyfd ) ;
  6599. #else /* NT */
  6600.     ms.fbModemOn = RTS_ON;
  6601.     ms.fbModemOff = 255;
  6602.     DosDevIOCtl(&data,sizeof(data),&ms,sizeof(ms),
  6603.                 ASYNC_SETMODEMCTRL,IOCTL_ASYNC,ttyfd);
  6604.  
  6605.     DosDevIOCtl(&i,sizeof(i),NULL,0,
  6606.                 ASYNC_SETBREAKON,IOCTL_ASYNC,ttyfd);    /* Break on */
  6607.     msleep(275L);                                       /* ZZZzzz */
  6608.     DosDevIOCtl(&i,sizeof(i),NULL,0,
  6609.                 ASYNC_SETBREAKOFF,IOCTL_ASYNC,ttyfd);   /* Break off */
  6610. #endif /* NT */
  6611.     return 0;
  6612. }
  6613.  
  6614. /*  T T S N D L B  --  Send a LONG BREAK signal  */
  6615. int
  6616. ttsndlb() {
  6617. #ifndef NT
  6618.     MODEMSTATUS ms;
  6619.     UINT data, i;
  6620. #endif /* NT */
  6621. #ifdef NETCONN
  6622.     if (network) {
  6623. #ifdef TN_COMPORT
  6624.         if (istncomport()) {
  6625.             if (tnsndb(1800L) >= 0)
  6626.                 return(0);
  6627.         }
  6628. #endif /* TN_COMPORT */
  6629.         return(os2_netbreak());
  6630.     }
  6631. #endif /* NETCONN */
  6632. #ifdef NT
  6633.     SetCommBreak( (HANDLE) ttyfd ) ;
  6634.     msleep(1800L);
  6635.     ClearCommBreak( (HANDLE) ttyfd ) ;
  6636.         #else /* NT */
  6637.     ms.fbModemOn = RTS_ON;
  6638.     ms.fbModemOff = 255;
  6639.     DosDevIOCtl(&data,sizeof(data),&ms,sizeof(ms),
  6640.                 ASYNC_SETMODEMCTRL,IOCTL_ASYNC,ttyfd);
  6641.  
  6642.     DosDevIOCtl(&i,sizeof(i),NULL,0,
  6643.                 ASYNC_SETBREAKON,IOCTL_ASYNC,ttyfd);    /* Break on */
  6644.     msleep(1800L);                                      /* ZZZzzz */
  6645.     DosDevIOCtl(&i,sizeof(i),NULL,0,
  6646.                 ASYNC_SETBREAKOFF,IOCTL_ASYNC,ttyfd);   /* Break off */
  6647. #endif /* NT*/
  6648.     return 0;
  6649. }
  6650.  
  6651. #ifndef __EMX__
  6652. /*  S L E E P  --  Emulate the Unix sleep function  */
  6653.  
  6654. /* MustComplete section required because of a bug in OS/2 that fails to
  6655.     allow us to reset the SIGINT signal after it has occurred during this
  6656.     call. */
  6657.  
  6658. unsigned
  6659. sleep(t) unsigned int t; {
  6660.     ULONG start_t, now_t, ms;
  6661.     int tt, tr, i;
  6662. #ifndef NT
  6663.     unsigned long p ;
  6664. #endif /* NT */
  6665. #ifdef NT
  6666.     start_t = GetTickCount();        /* msecs since Windows was started */
  6667. #else /* NT */
  6668.     DosQuerySysInfo(QSV_MS_COUNT,QSV_MS_COUNT,&start_t,4);
  6669. #endif /* NT */
  6670.  
  6671.     tt = (t * 1000L) / ck_sleepint;
  6672.     tr = (t * 1000L) % ck_sleepint;
  6673.  
  6674.     for (i = 0; i < tt; i++) {
  6675. #ifdef NT
  6676.         Sleep((long) ck_sleepint);
  6677. #else /* NT */
  6678.         DosEnterMustComplete(&p);
  6679.         DosSleep((long)ck_sleepint);
  6680.         DosExitMustComplete(&p);
  6681. #endif /* NT */
  6682. #ifdef NTSIG
  6683.         ck_ih();
  6684. #endif /* NTSIG */
  6685. #ifdef NT
  6686.         now_t = GetTickCount();
  6687. #else /* NT */
  6688.         DosQuerySysInfo(QSV_MS_COUNT,QSV_MS_COUNT,&now_t,4);
  6689. #endif /* NT */
  6690.  
  6691.         if ( now_t < start_t ) {
  6692.         /* we wrapped */
  6693. #ifdef NT
  6694.             ms = (MAXDWORD - start_t + now_t);
  6695. #else /* NT */
  6696.             ms = (ULONG_MAX - start_t + now_t);
  6697. #endif /* NT */
  6698.         }
  6699.         else {
  6700.             ms = (now_t - start_t);
  6701.         }
  6702.         if ( ms >= (t * 1000L) )
  6703.             return(0);
  6704.     }
  6705.     if ( tr )
  6706.     {
  6707. #ifdef NT
  6708.         Sleep((long) tr);
  6709. #else /* NT */
  6710.         DosEnterMustComplete(&p);
  6711.         DosSleep((long)tr);
  6712.         DosExitMustComplete(&p);
  6713. #endif /* NT */
  6714. #ifdef NTSIG
  6715.         ck_ih();
  6716. #endif /* NTSIG */
  6717.     }
  6718.     return(0);
  6719. }
  6720. #endif /* __EMX__ */
  6721.  
  6722. /*  M S L E E P  --  Millisecond version of sleep().  */
  6723.  
  6724. /* Intended only for small intervals.  For big ones, just use sleep(). */
  6725.  
  6726. /*
  6727.   MustComplete section required because of a bug in OS/2 that fails to allow
  6728.   us to reset the SIGINT signal after it has occurred during this call.
  6729. */
  6730. int
  6731. msleep(int m) {
  6732.     ULONG start_t, now_t, ms;
  6733.     int tt, tr, ti, i;
  6734. #ifndef NT
  6735.    unsigned long p ;
  6736. #endif
  6737. #ifdef NT
  6738.     start_t = GetTickCount();        /* msecs since Windows was started */
  6739. #else /* NT */
  6740.     DosQuerySysInfo(QSV_MS_COUNT,QSV_MS_COUNT,&start_t,4);
  6741. #endif /* NT */
  6742.  
  6743.     if ( m <= 500 ) {
  6744. #ifdef NT
  6745.         Sleep((long) m);
  6746. #else /* NT */
  6747.         DosEnterMustComplete(&p);
  6748.         DosSleep((long)m);
  6749.         DosExitMustComplete(&p);
  6750. #endif /* NT */
  6751. #ifdef NTSIG
  6752.         ck_ih();
  6753. #endif /* NTSIG */
  6754.         return(0);
  6755.     }
  6756.  
  6757.     tt = m / ck_sleepint;
  6758.     tr = m % ck_sleepint;
  6759.     ti = ck_sleepint;
  6760.  
  6761.     for (i = 0; i < tt; i++) {
  6762. #ifdef NT
  6763.         Sleep((long) ti);
  6764. #else /* NT */
  6765.         DosEnterMustComplete(&p);
  6766.         DosSleep((long)ti);
  6767.         DosExitMustComplete(&p);
  6768. #endif /* NT */
  6769. #ifdef NTSIG
  6770.         ck_ih();
  6771. #endif /* NTSIG */
  6772.  
  6773. #ifdef NT
  6774.         now_t = GetTickCount();
  6775. #else /* NT */
  6776.         DosQuerySysInfo(QSV_MS_COUNT,QSV_MS_COUNT,&now_t,4);
  6777. #endif /* NT */
  6778.  
  6779.         if ( now_t < start_t ) {
  6780.         /* we wrapped */
  6781. #ifdef NT
  6782.             ms = (MAXDWORD - start_t + now_t);
  6783. #else /* NT */
  6784.             ms = (ULONG_MAX - start_t + now_t);
  6785. #endif /* NT */
  6786.         }
  6787.         else {
  6788.             ms = (now_t - start_t);
  6789.         }
  6790.         if ( ms >= m )
  6791.             return(0);
  6792.     }
  6793.     if ( tr ) {
  6794. #ifdef NT
  6795.         Sleep((long) tr);
  6796. #else /* NT */
  6797.         DosEnterMustComplete(&p);
  6798.         DosSleep((long)tr);
  6799.         DosExitMustComplete(&p);
  6800. #endif /* NT */
  6801. #ifdef NTSIG
  6802.         ck_ih();
  6803. #endif /* NTSIG */
  6804.     }
  6805.     return (0);
  6806. }
  6807.  
  6808. /*  R T I M E R --  Reset elapsed time counter  */
  6809.  
  6810. void
  6811. rtimer() {
  6812. #ifdef NT
  6813.     tcount = GetTickCount();        /* msecs since Windows was started */
  6814. #else /* NT */
  6815.     DosQuerySysInfo(QSV_MS_COUNT,QSV_MS_COUNT,&tcount,4);
  6816. #endif /* NT */
  6817.     debug(F101,"rtimer tick_count","",tcount);
  6818. }
  6819.  
  6820. /*  G T I M E R --  Get current value of elapsed time counter in seconds  */
  6821.  
  6822. int
  6823. gtimer(void) {
  6824. #ifdef NT
  6825.     DWORD tick_now=0L;
  6826. #else /* NT */
  6827.     ULONG tick_now=0L;
  6828. #endif /* NT */
  6829.     int s=0;
  6830.  
  6831. #ifdef NT
  6832.     tick_now = GetTickCount();
  6833. #else /* NT */
  6834.     DosQuerySysInfo(QSV_MS_COUNT,QSV_MS_COUNT,&tick_now,4);
  6835. #endif /* NT */
  6836.  
  6837.     if ( tick_now < tcount ) {
  6838.         /* we wrapped */
  6839. #ifdef NT
  6840.         s = (MAXDWORD - tcount + tick_now) / 1000;
  6841. #else /* NT */
  6842.         s = (ULONG_MAX - tcount + tick_now) / 1000;
  6843. #endif /* NT */
  6844.     }
  6845.     else {
  6846.         s = (tick_now - tcount) / 1000;
  6847.     }
  6848.  
  6849.     if (s < 0) s=0;
  6850.     return(s);
  6851. }
  6852.  
  6853. #ifdef GFTIMER
  6854. #ifdef NT
  6855. DWORD tick_count=0L;
  6856. DWORD tick_count2=0L;
  6857. #else /* NT */
  6858. ULONG tick_count=0L;
  6859. ULONG tick_count2=0L;
  6860. #endif /* NT */
  6861.  
  6862. VOID
  6863. rftimer() {
  6864. #ifdef NT
  6865.     tick_count = GetTickCount();        /* msecs since Windows was started */
  6866.                                         /* wraps at 49.7 days */
  6867. #else /* NT */
  6868.     DosQuerySysInfo(QSV_MS_COUNT,QSV_MS_COUNT,&tick_count,4);
  6869. #endif /* NT */
  6870.     debug(F101,"rftimer tick_count","",tick_count);
  6871. }
  6872.  
  6873. CKFLOAT
  6874. gftimer() {
  6875. #ifdef NT
  6876.     DWORD tick_now=0L;
  6877. #else /* NT */
  6878.     ULONG tick_now=0L;
  6879. #endif /* NT */
  6880.     double s=0.0;
  6881. #ifdef DEBUG
  6882.     char fpbuf[64];
  6883. #endif /* DEBUG */
  6884.  
  6885. #ifdef NT
  6886.     tick_now = GetTickCount();
  6887. #else /* NT */
  6888.     DosQuerySysInfo(QSV_MS_COUNT,QSV_MS_COUNT,&tick_now,4);
  6889. #endif /* NT */
  6890.  
  6891.     if ( tick_now < tick_count ) {
  6892.         /* we wrapped */
  6893. #ifdef NT
  6894.         s = (double) (MAXDWORD - tick_count + tick_now) / 1000;
  6895. #else /* NT */
  6896.         s = (double) (ULONG_MAX - tick_count + tick_now) / 1000;
  6897. #endif /* NT */
  6898.     }
  6899.     else {
  6900.         s = (double) (tick_now - tick_count) / 1000;
  6901.     }
  6902.  
  6903.     if (s == 0.0) s = 0.000001;
  6904. #ifdef DEBUG
  6905.     if (deblog) {
  6906.         sprintf(fpbuf,"%f",s);
  6907.         debug(F111,"gftimer",fpbuf,tick_now);
  6908.     }
  6909. #endif /* DEBUG */
  6910.     return((CKFLOAT)s);
  6911. }
  6912.  
  6913. VOID
  6914. rmstimer() {
  6915. #ifdef NT
  6916.     tick_count2 = GetTickCount();        /* msecs since Windows was started */
  6917.                                         /* wraps at 49.7 days */
  6918. #else /* NT */
  6919.     DosQuerySysInfo(QSV_MS_COUNT,QSV_MS_COUNT,&tick_count2,4);
  6920. #endif /* NT */
  6921.     debug(F101,"rmstimer tick_count2","",tick_count2);
  6922. }
  6923.  
  6924. ULONG
  6925. gmstimer() {
  6926. #ifdef NT
  6927.     DWORD tick_now=0L;
  6928. #else /* NT */
  6929.     ULONG tick_now=0L;
  6930. #endif /* NT */
  6931.     ULONG s;
  6932. #ifdef DEBUG
  6933.     char fpbuf[64];
  6934. #endif /* DEBUG */
  6935.  
  6936. #ifdef NT
  6937.     tick_now = GetTickCount();
  6938. #else /* NT */
  6939.     DosQuerySysInfo(QSV_MS_COUNT,QSV_MS_COUNT,&tick_now,4);
  6940. #endif /* NT */
  6941.  
  6942.     if ( tick_now < tick_count2 ) {
  6943.         /* we wrapped */
  6944. #ifdef NT
  6945.         s = (MAXDWORD - tick_count2 + tick_now);
  6946. #else /* NT */
  6947.         s = (ULONG_MAX - tick_count2 + tick_now);
  6948. #endif /* NT */
  6949.     }
  6950.     else {
  6951.         s = (tick_now - tick_count2);
  6952.     }
  6953.  
  6954. #ifdef DEBUG
  6955.     if (deblog) {
  6956.         sprintf(fpbuf,"%d",s);
  6957.         debug(F111,"gmstimer",fpbuf,tick_now);
  6958.     }
  6959. #endif /* DEBUG */
  6960.     return(s);
  6961. }
  6962. #endif /* GFTIMER */
  6963.  
  6964. /*  Z T I M E  --  Return date/time string  */
  6965.  
  6966. void
  6967. ztime(char **s) {
  6968.     time_t clock_storage;
  6969.  
  6970.     clock_storage = time( (long *) 0 );
  6971.     *s = ctime( &clock_storage );
  6972. }
  6973.  
  6974. void
  6975. loadtod( int hh, int mm )
  6976. {
  6977. #ifdef NT
  6978.     SYSTEMTIME systime ;
  6979.     GetLocalTime( &systime ) ;
  6980.     systime.wHour = hh ;
  6981.     systime.wMinute = mm ;
  6982.     systime.wSecond = 0 ;
  6983.     systime.wMilliseconds = 0 ;
  6984.     SetLocalTime( &systime ) ;
  6985. #else /* NT */
  6986.     DATETIME   DateTime = {0};       /* Structure to hold date/time info.   */
  6987.     APIRET     rc       = NO_ERROR;  /* Return code                         */
  6988.  
  6989.     /* Retrieve the current date and time  */
  6990.     if ( DosGetDateTime(&DateTime) == NO_ERROR ) {
  6991.  
  6992.         DateTime.hours = (UCHAR) hh;
  6993.         DateTime.minutes = (UCHAR) mm;
  6994.         DateTime.seconds = 0 ;
  6995.         DateTime.hundredths = 0 ;
  6996.  
  6997.         rc = DosSetDateTime(&DateTime);  /* Update the date and time            */
  6998.     }
  6999. #endif /* NT */
  7000. }
  7001.  
  7002. /*  C O N O C  --  Output a character to the console terminal  */
  7003.  
  7004. int
  7005. conoc(char c) {
  7006.     extern unsigned char colorcmd;
  7007.     extern int wherex[];    /* Screen column, 1-based */
  7008.     extern int wherey[];        /* Screen row, 1-based */
  7009.  
  7010. #ifdef IKSD
  7011.     if ( inserver ) {
  7012.         debug(F100,"conoc inserver","",0);
  7013.         ttoc(c);
  7014.     }
  7015.  
  7016. #endif /* IKSD */
  7017. #ifndef NOLOCAL
  7018.     if ( k95stdout )
  7019.         fwrite(&c,1,1,stdout);
  7020.     else {
  7021.         VscrnWrtCharStrAtt( VCMD, &c, 1, wherey[VCMD], wherex[VCMD],
  7022.                             &colorcmd ) ;
  7023.     }
  7024. #endif /* NOLOCAL */
  7025.     return 1;
  7026. }
  7027.  
  7028.  
  7029. /*  C O N X O  --  Write x characters to the console terminal  */
  7030.  
  7031. int
  7032. conxo(int x, char *s) {
  7033.     int i, rc;
  7034.  
  7035.     if ( s == NULL )
  7036.         return(-1);
  7037.  
  7038. #ifdef IKSD
  7039.     if ( inserver ) {
  7040.         debug(F100,"conxo inserver","",0);
  7041.         return(ttol(s,x));
  7042.     }
  7043. #endif /* IKSD */
  7044.  
  7045.     for ( i=0 ; i<x ; i++ )
  7046.       conoc(s[i]);
  7047.     return(x);
  7048. }
  7049.  
  7050.  
  7051. /*  C O N O L  --  Write a line to the console terminal  */
  7052.  
  7053. int
  7054. conol(char *s) {
  7055.     extern unsigned char colorcmd ;
  7056.  
  7057.     if ( s == NULL )
  7058.         return(-1);
  7059.  
  7060. #ifdef IKSD
  7061.     if ( inserver ) {
  7062.         debug(F100,"conol inserver","",0);
  7063.         ttol(s,strlen(s));
  7064.     }
  7065. #endif /* IKSD */
  7066. #ifndef NOLOCAL
  7067.     if ( k95stdout )
  7068.         fwrite(s,1,strlen(s),stdout);
  7069.     else
  7070.         VscrnWrtCharStrAtt( VCMD, s, strlen(s),
  7071.                             VscrnGetCurPos(VCMD)->y+1,
  7072.                             VscrnGetCurPos(VCMD)->x+1,
  7073.                             &colorcmd
  7074.                             ) ;
  7075. #endif /* NOLOCAL */
  7076.     return 0;
  7077. }
  7078.  
  7079.  
  7080. /*  C O N O L A  --  Write an array of lines to the console terminal */
  7081. int
  7082. conola(s) char *s[]; {
  7083.     int i;
  7084.     if ( s == NULL )
  7085.         return(-1);
  7086.     for (i=0 ; *s[i] ; i++)
  7087.         conol(s[i]);
  7088.     return 0 ;
  7089. }
  7090.  
  7091.  
  7092. /*  C O N O L L  --  Output a string followed by CRLF  */
  7093. int
  7094. conoll(s) char *s; {
  7095.     if ( s == NULL )
  7096.         return(-1);
  7097.     conol(s);
  7098.     conol("\r\n");
  7099.     return 0 ;
  7100. }
  7101.  
  7102.  
  7103. /*  C O N C H K  --  Return how many characters available at console  */
  7104.  
  7105. int
  7106. conchk() {
  7107. #ifdef IKSD
  7108.     if ( inserver ) {
  7109.         return(ttchk());
  7110.     } else
  7111. #endif /* IKSD */
  7112.     return charinbuf(VCMD) ;
  7113. }
  7114.  
  7115.  
  7116. /*  C O N I N C  --  Get a character from the console  */
  7117. /*
  7118.   Call with timo > 0 to do a timed read, timo == 0 to do an untimed blocking
  7119.   read.  Upon success, returns the character.  Upon failure, returns -1.
  7120.   A timed read that does not complete within the timeout period returns -2.
  7121. */
  7122.  
  7123. int
  7124. coninc(timo) int timo; {
  7125.     int c, rc = -1, cm;
  7126.     extern int what;
  7127. #ifndef NOTERM
  7128.     extern enum markmodes markmodeflag[VNUM];
  7129. #endif /* NOTERM */
  7130.     time_t t;
  7131.  
  7132.     debug(F111,"coninc","timo",timo);
  7133. #ifdef IKSD
  7134.     if ( inserver ) {
  7135.         debug(F100,"coninc inserver","",0);
  7136.         c = ttinc(timo);
  7137.         if ( c == -1 )
  7138.             return(-2);
  7139.         else if ( c < 0 )
  7140.             return(-1);
  7141.         else
  7142.             return(c & 0xFF);
  7143.     }
  7144. #endif /* IKSD */
  7145.  
  7146.     t = time(NULL) ;
  7147.     do {
  7148.         c = congks(timo) ;
  7149.         switch ( c ) {
  7150.         case KEY_SCAN | BS:     /* The Backspace Key */
  7151.         case DEL:
  7152.         case XEM:
  7153. #ifndef NOKVERBS
  7154.         case F_KVERB | K_WYBS:
  7155.         case F_KVERB | K_WYSBS:
  7156.         case F_KVERB | K_TVIBS:
  7157.         case F_KVERB | K_TVISBS:
  7158.         case F_KVERB | K_DGBS:
  7159. #endif /* NOKVERBS */
  7160.             debug(F111,"coninc","BS conversion",c);
  7161.             c = BS ;
  7162.             break;
  7163.         case KEY_SCAN | HT:
  7164. #ifndef NOKVERBS
  7165.         case F_KVERB | K_WYTAB:
  7166.         case F_KVERB | K_TVITAB:
  7167.         case F_KVERB | K_SNI_TAB:
  7168.         case F_KVERB | K_SNI_S_TAB:
  7169.         case F_KVERB | K_SNI_C_TAB:
  7170. #endif /* NOKVERBS */
  7171.             debug(F111,"coninc","TAB conversion",c);
  7172.             c = HT;
  7173.             break;
  7174.         case KEY_SCAN | ESC:
  7175. #ifndef NOKVERBS
  7176.         case F_KVERB | K_WYESC:
  7177.         case F_KVERB | K_TVIESC:
  7178. #endif /* NOKVERBS */
  7179.             debug(F111,"coninc","ESC conversion",c);
  7180.             c = ESC ;
  7181.             break;
  7182.         case KEY_SCAN | CR:
  7183. #ifndef NOKVERBS
  7184.         case F_KVERB | K_KPENTER:
  7185.         case F_KVERB | K_WYENTER:
  7186.         case F_KVERB | K_WYRETURN:
  7187.         case F_KVERB | K_TVIENTER:
  7188.         case F_KVERB | K_TVIRETURN:
  7189.         case F_KVERB | K_HPENTER:
  7190.         case F_KVERB | K_HPRETURN:
  7191. #endif /* NOKVERBS */
  7192.             debug(F111,"coninc","ENTER conversion",c);
  7193.             c = CR ;
  7194.             break;
  7195. #ifndef NOKVERBS
  7196.         case F_KVERB | K_KPMINUS:
  7197.             debug(F111,"coninc","MINUS conversion",c);
  7198.             c = '-';
  7199.             break;
  7200.         case F_KVERB | K_KPCOMA:
  7201.             debug(F111,"coninc","COMA conversion",c);
  7202.             c = ',';
  7203.             break;
  7204.         case F_KVERB | K_KPDOT:
  7205.             debug(F111,"coninc","PERIOD conversion",c);
  7206.             c = '.';
  7207.             break;
  7208.         case F_KVERB | K_KP0:
  7209.             debug(F111,"coninc","0 conversion",c);
  7210.             c = '0' ;
  7211.             break;
  7212.         case F_KVERB | K_KP1:
  7213.             debug(F111,"coninc","1 conversion",c);
  7214.             c = '1' ;
  7215.             break;
  7216.         case F_KVERB | K_KP2:
  7217.             debug(F111,"coninc","2 conversion",c);
  7218.             c = '2' ;
  7219.             break;
  7220.         case F_KVERB | K_KP3:
  7221.             debug(F111,"coninc","3 conversion",c);
  7222.             c = '3' ;
  7223.             break;
  7224.         case F_KVERB | K_KP4:
  7225.             debug(F111,"coninc","4 conversion",c);
  7226.             c = '4' ;
  7227.             break;
  7228.         case F_KVERB | K_KP5:
  7229.             debug(F111,"coninc","5 conversion",c);
  7230.             c = '5' ;
  7231.             break;
  7232.         case F_KVERB | K_KP6:
  7233.             debug(F111,"coninc","6 conversion",c);
  7234.             c = '6' ;
  7235.             break;
  7236.         case F_KVERB | K_KP7:
  7237.             debug(F111,"coninc","7 conversion",c);
  7238.             c = '7' ;
  7239.             break;
  7240.         case F_KVERB | K_KP8:
  7241.             debug(F111,"coninc","8 conversion",c);
  7242.             c = '8' ;
  7243.             break;
  7244.         case F_KVERB | K_KP9:
  7245.             debug(F111,"coninc","9 conversion",c);
  7246.             c = '9' ;
  7247.             break;
  7248. #endif /* NOKVERBS */
  7249.         case KEY_SCAN | KEY_CTRL | 66: /* Ctrl-B */
  7250.         case KEY_SCAN | 38:
  7251.         case KEY_SCAN | KEY_ENHANCED | 38:
  7252. #ifndef NOKVERBS
  7253.         case F_KVERB | K_UPARR:
  7254.         case F_KVERB | K_ANSIF50:
  7255. #endif /* NOKVERBS */
  7256. #ifndef NOTERM
  7257.             if ( markmodeflag[VCMD] != notmarking )
  7258.                 break;
  7259.             if (!IsConnectMode()) { /* Up arrow = Ctrl-B */
  7260.                 debug(F111,"coninc","Ctrl-B conversion",c);
  7261.                 c = 2;
  7262.             }
  7263. #endif /* NOTERM */
  7264.             break;
  7265.         case KEY_SCAN | KEY_CTRL | 78:
  7266.         case KEY_SCAN | 40:
  7267.         case KEY_SCAN | KEY_ENHANCED | 40:
  7268. #ifndef NOKVERBS
  7269.         case F_KVERB | K_DNARR:
  7270.         case F_KVERB | K_ANSIF58:
  7271. #endif /* NOKVERBS */
  7272. #ifndef NOTERM
  7273.             if ( markmodeflag[VCMD] != notmarking )
  7274.                 break;
  7275.             if (!IsConnectMode()) { /* Down arrow = Ctrl-N */
  7276.                 debug(F111,"coninc","Ctrl-N conversion",c);
  7277.                 c = 14;
  7278.             }
  7279. #endif /* NOTERM */
  7280.             break;
  7281.         default: ;
  7282.         }
  7283.         if ( c == CR )
  7284.             c = NL;
  7285. #ifndef NOKVERBS
  7286.         if (c >= 0) {
  7287.             debug(F111,"coninc","c >= 0",c);
  7288.             if ( IS_KVERB(c) ) {
  7289.                 dokverb(VCMD,c);
  7290.             }
  7291.             /* Here we could handle F_CSI, F_ESC, ... */
  7292.         }
  7293. #endif /* NOKVERBS */
  7294.         if ( timo && (time( NULL ) - t >= timo) )
  7295.         {
  7296.             c = -1 ; /* timeout */
  7297.             break;
  7298.         }
  7299.     } while ( c >= 0x100 ) ;
  7300.  
  7301.     if ( c == -1 )
  7302.         return(-2);
  7303.     else if ( c == -2 )
  7304.         return(-3);
  7305.     else if ( c < 0 )
  7306.         return(-1);
  7307.     else
  7308.         return(c & 0xFF);
  7309. }
  7310.  
  7311. con_event
  7312. congev( int vmode, int timo ) {
  7313.     APIRET rc ;
  7314.     ULONG timeout = 0;
  7315.     con_event evt ;
  7316.     int tt,tr,interval,i ;
  7317.  
  7318. #ifdef IKSD
  7319.     if ( inserver ) {
  7320.         int ch;
  7321.         debug(F100,"congev inserver","",0);
  7322.         ch = ttinc(timo);
  7323.         if (ch >= 0) {
  7324.             evt.type = key;
  7325.             evt.key.scancode = ch;
  7326.         } else {
  7327.             evt.type = error;
  7328.         }
  7329.         return evt;
  7330.     }
  7331. #endif /* IKSD */
  7332.  
  7333. #ifdef NT
  7334.     if ( timo == 0 )
  7335.     {
  7336.        interval = ck_sleepint ;
  7337.        tt = 1 ;
  7338.        timeout = 0;
  7339.     }
  7340.     else if ( timo == -1 )
  7341.     {
  7342.        interval = -1 ;
  7343.        tt = 1 ;
  7344.        timeout = 0;
  7345.     }
  7346.     else
  7347.     {
  7348.        if ( timo < -1 )
  7349.           timeout = -timo ;
  7350.        else /* ( timo > 0 ) */
  7351.           timeout = timo * 1000 ;
  7352.  
  7353.        tt = timeout / ck_sleepint ;
  7354.        tr = timeout % ck_sleepint ;
  7355.        if ( tt )
  7356.           interval = ck_sleepint + tr / tt ;
  7357.        else
  7358.        {
  7359.           tt = 1 ;
  7360.           interval = tr ;
  7361.        }
  7362.     }
  7363.     for ( i = 0 ; (timeout && (i < tt)) || !timeout ; i++ )
  7364.     {
  7365.         rc = WaitEventAvailSem( vmode, interval ) ;
  7366. #ifdef NTSIG
  7367.         ck_ih() ;
  7368. #endif /* NTSIG */
  7369.         switch ( rc ) {
  7370.         case NO_ERROR:
  7371.             if ( getevent( vmode, &evt ) )
  7372.                 return(evt);
  7373.             break;
  7374.         default:
  7375.             if ( interval == -1 ) {
  7376.                 evt.type = error;
  7377.                 return(evt);
  7378.             }
  7379.         }
  7380.     }
  7381. #else /* NT */
  7382.     if ( timo < -1 )
  7383.       timeout = -timo ;
  7384.     if ( timo == -1 || timo == 0 )
  7385.       timeout = SEM_INDEFINITE_WAIT ;
  7386.     if ( timo > 0 )
  7387.       timeout = timo * 1000 ;
  7388.  
  7389.    rc = WaitEventAvailSem( vmode, timeout ) ;
  7390.    if ( rc == NO_ERROR )
  7391.        if ( getevent( vmode, &evt ) )
  7392.            return evt ;
  7393. #endif /* NT */
  7394.    evt.type=error;
  7395.    return evt ;
  7396. }
  7397.  
  7398.  
  7399. int
  7400. congks(int timo) {
  7401.     APIRET rc ;
  7402.     ULONG timeout = 0 ;
  7403.     con_event evt ;
  7404.     int tt, i, ch ;
  7405.     static char * macrostr = NULL, * s = NULL;
  7406.  
  7407.     debug(F111,"congks","timo",timo);
  7408.  
  7409.     if ( macrostr && s ) {
  7410.         debug(F100,"congks macrostr","",0);
  7411.         if ( *s == NUL ) {
  7412.             free(macrostr);
  7413.             macrostr = NULL ;
  7414.             s = NULL;
  7415.             ch = CR;
  7416.         }
  7417.         else {
  7418.             ch = *s++;
  7419.         }
  7420.         return(ch);
  7421.     }
  7422.  
  7423. #ifdef IKSD
  7424.     if ( inserver ) {
  7425.         debug(F100,"congks inserver","",0);
  7426.         return(ttinc(timo));
  7427.     }
  7428. #endif /* IKSD */
  7429.  
  7430.    if ( timo < -1 )
  7431.       timeout = -timo ;
  7432.    else if ( timo == -1 || timo == 0 )
  7433.       timeout = SEM_INDEFINITE_WAIT ;
  7434.    else /* ( timo > 0 ) */
  7435.       timeout = timo * 1000;
  7436.  
  7437.     debug(F111,"congks","timeout",timeout);
  7438.  
  7439. #ifdef NT
  7440.    tt = timeout / ck_sleepint ;
  7441.    for ( i = 0 ; i <= tt ; )
  7442.    {
  7443.       rc = WaitEventAvailSem( VCMD, ck_sleepint ) ;
  7444.        debug(F111,"congks","WaitEventAvailSem()",rc);
  7445. #ifdef NTSIG
  7446.       ck_ih() ;
  7447. #endif /* NTSIG */
  7448.       switch ( rc )
  7449.       {
  7450.       case NO_ERROR:
  7451.          if ( getevent( (BYTE)VCMD, &evt ) )
  7452.          {
  7453.             switch ( evt.type )
  7454.             {
  7455.             case key:
  7456.                 debug(F111,"congks","evt.key.scancode",evt.key.scancode);
  7457.                 return evt.key.scancode;
  7458.             case macro:
  7459.                 macrostr = evt.macro.string ;
  7460.                 s = macrostr ;
  7461.                 ch = *s++;
  7462.                 if ( !*s ) {
  7463.                     free(macrostr);
  7464.                     macrostr = NULL ;
  7465.                     s = NULL;
  7466.                 }
  7467.                 debug(F111,"congks","evt.macro.string ch",ch);
  7468.                 return(ch);
  7469.             case literal:
  7470.                 macrostr = evt.literal.string ;
  7471.                 s = macrostr ;
  7472.                 ch = *s++;
  7473.                 if ( !*s ) {
  7474.                     free(macrostr);
  7475.                     macrostr = NULL ;
  7476.                     s = NULL;
  7477.                 }
  7478.                 debug(F111,"congks","evt.literal.string ch",ch);
  7479.                 return(ch);
  7480. #ifndef NOKVERBS
  7481.             case kverb:
  7482.                 debug(F111,"congks","evt.kverb.id",evt.kverb.id);
  7483.                 return F_KVERB | evt.kverb.id;
  7484. #endif /* NOKVERBS */
  7485.             case csi:
  7486.                 debug(F111,"congks","evt.csi.key",evt.csi.key);
  7487.                 return F_CSI | evt.csi.key;
  7488.             case esc:
  7489.                 debug(F111,"congks","evt.esc.key",evt.esc.key);
  7490.                 return F_ESC | evt.esc.key ;
  7491.             case error:
  7492.                 return(-2);
  7493.             default:
  7494.                 debug(F110,"congks","default",0);
  7495.                break;
  7496.             }
  7497.          }
  7498.          else break ;
  7499.       default:
  7500.          break ;
  7501.       }
  7502.       if (timeout != (ULONG) SEM_INDEFINITE_WAIT )
  7503.          i++ ;
  7504.    }
  7505. #else /* NT */
  7506.    while ( 1 )
  7507.    {
  7508.       rc = WaitEventAvailSem( VCMD, timeout ) ;
  7509.       if ( rc == NO_ERROR )
  7510.          if ( getevent( VCMD, &evt ) )
  7511.          {
  7512.             switch ( evt.type )
  7513.             {
  7514.             case key:
  7515.                return evt.key.scancode;
  7516.             case macro:
  7517.                 macrostr = evt.macro.string ;
  7518.                 s = macrostr ;
  7519.                 ch = *s++;
  7520.                 if ( !*s ) {
  7521.                     free(macrostr);
  7522.                     macrostr = NULL ;
  7523.                     s = NULL;
  7524.                 }
  7525.                 return(ch);
  7526.             case literal:
  7527.                 macrostr = evt.literal.string ;
  7528.                 s = macrostr ;
  7529.                 ch = *s++;
  7530.                 if ( !*s ) {
  7531.                     free(macrostr);
  7532.                     macrostr = NULL ;
  7533.                     s = NULL;
  7534.                 }
  7535.                 return(ch);
  7536. #ifndef NOKVERBS
  7537.             case kverb:
  7538.                 return F_KVERB | evt.kverb.id;
  7539. #endif /* NOKVERBS */
  7540.             case csi:
  7541.                 return F_CSI | evt.csi.key;
  7542.             case esc:
  7543.                 return F_ESC | evt.esc.key ;
  7544.             case error:
  7545.                 return(-2);
  7546.             default:
  7547.                break;
  7548.             }
  7549.          }
  7550.          else break ;
  7551.    }
  7552. #endif /* NT */
  7553.    return -1;
  7554. }
  7555.  
  7556. int
  7557. conraw() {
  7558. #ifdef NT
  7559.    DWORD mode ;
  7560.    extern int mouseon ;
  7561. #ifndef KUI
  7562. #ifdef COMMENT
  7563.    /* Don't call this directly - It's fatal in Windows 95 */
  7564.    SetConsoleCtrlHandler( NULL, TRUE ) ;
  7565. #endif /* COMMENT */
  7566.    GetConsoleMode( KbdHandle, &mode ) ;
  7567.    mode &= ~(ENABLE_LINE_INPUT | ENABLE_WINDOW_INPUT |
  7568.               ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT | 0x40 );
  7569. #ifdef OS2MOUSE
  7570.     if ( mouseon )
  7571.       mode |= ENABLE_MOUSE_INPUT;
  7572. #endif /* OS2MOUSE */
  7573.    SetConsoleMode( KbdHandle, mode ) ;
  7574. #endif /* KUI */
  7575.     ckconraw = 1 ;
  7576. #else /* NT */
  7577.     KBDINFO k;
  7578.  
  7579.     memset( &k, 0, sizeof(k) ) ;
  7580.  
  7581.     if (!islocal) return(0);
  7582.     conmode = 1;
  7583.     k.cb = sizeof(k);
  7584.     KbdGetStatus(&k,KbdHandle);
  7585.     k.fsMask &= ~(KEYBOARD_ECHO_ON |
  7586.                   KEYBOARD_ASCII_MODE);
  7587.     k.fsMask |=  (KEYBOARD_ECHO_OFF
  7588.                 | KEYBOARD_BINARY_MODE
  7589.       | KEYBOARD_SHIFT_REPORT);  /* Generates excessive key reports */
  7590.     return(KbdSetStatus(&k,KbdHandle));  /* But lets us see ScrollLock, Ctrl, Alt */
  7591. #endif /* NT */
  7592.     return(0);
  7593. }
  7594.  
  7595. int
  7596. concooked() {
  7597. #ifdef NT
  7598. #ifndef KUI
  7599.     DWORD mode ;
  7600.     extern int mouseon ;
  7601. #ifdef COMMENT
  7602.     /* Don't call this directly - It's fatal in Windows 95 */
  7603.     SetConsoleCtrlHandler( NULL, FALSE ) ;
  7604. #endif /* COMMENT */
  7605.     GetConsoleMode( KbdHandle, &mode ) ;
  7606.     mode &= ~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT |
  7607.                ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT | 0x40);
  7608.     mode |= ENABLE_PROCESSED_INPUT ;
  7609. #ifdef OS2MOUSE
  7610.     if ( mouseon )
  7611.         mode |= ENABLE_MOUSE_INPUT;
  7612. #endif /* OS2MOUSE */
  7613.     SetConsoleMode( KbdHandle, mode ) ;
  7614. #endif /* KUI */
  7615.     ckconraw = 0 ;
  7616.     return(0);
  7617. #else /* NT */
  7618.     KBDINFO k;
  7619.  
  7620.     memset( &k, 0, sizeof(k) ) ;
  7621.  
  7622.     if (!islocal) return(0);
  7623.     conmode = 0;
  7624.     k.cb = sizeof(k);
  7625.     KbdGetStatus(&k,KbdHandle);
  7626.     k.fsMask &= ~(KEYBOARD_ECHO_OFF |
  7627.                   KEYBOARD_BINARY_MODE |
  7628.                   KEYBOARD_SHIFT_REPORT);
  7629.     k.fsMask |=  (KEYBOARD_ECHO_ON |
  7630.                   KEYBOARD_ASCII_MODE);
  7631.     return(KbdSetStatus(&k,KbdHandle));
  7632. #endif /* NT */
  7633. }
  7634.  
  7635. /*  C O N B I N  --  Put console in binary mode  */
  7636.  
  7637. /*  Returns 0 if ok, -1 if not  */
  7638.  
  7639. conbin(char esc) {
  7640.     if (!islocal) return(0);          /* only for real ttys */
  7641. #ifndef NOLOCAL
  7642.     if ( IsConnectMode() )
  7643. #endif /* NOLOCAL */
  7644.         conraw();
  7645.     return 0;
  7646. }
  7647.  
  7648. /*  C O N C B  -- Put console into single char mode with no echo. */
  7649.  
  7650. concb(char esc) {
  7651.     if (!islocal)
  7652.         return(0);          /* only for real ttys */
  7653. #ifndef NOLOCAL
  7654.     if (!IsConnectMode())
  7655. #endif /* NOLOCAL */
  7656.         concooked();
  7657.     return 0 ;
  7658. }
  7659.  
  7660.  
  7661. /*  C O N G M  -- Get console terminal mode. */
  7662.  
  7663. congm() { return 0 ; }
  7664.  
  7665. /*  C O N R E S -- Restore console to congm mode. */
  7666.  
  7667. conres() { return 0 ; }
  7668.  
  7669.  
  7670. /*  C O N I N T -- Enable console terminal interrupts. */
  7671.  
  7672. void
  7673. conint(f, s) SIGTYP (*f)(int), (*s)(int); {
  7674.     if ( signal(SIGINT, f) == SIG_ERR )
  7675.         debug(F101,"conint() could not set SIGINT","",f);
  7676.  
  7677.     if ( !quitonbreak )
  7678.         if ( signal(SIGBREAK, f) == SIG_ERR )
  7679.             debug(F101,"conint() could not set SIGBREAK","",f);
  7680. }
  7681.  
  7682.  
  7683. /*  C O N N O I -- No console interrupts. */
  7684.  
  7685. void connoi() {
  7686.     signal(SIGINT, SIG_IGN);
  7687.     if ( !quitonbreak )
  7688.         signal(SIGBREAK, SIG_IGN);
  7689. }
  7690.  
  7691.  
  7692. /* privilege dummy */
  7693.  
  7694. int priv_chk() {return 0;}
  7695.  
  7696.  
  7697. #ifndef __EMX__
  7698.  
  7699. /* alarm() implementation for all others, emx/gcc already has it built-in */
  7700. #define STACK
  7701. static BOOL alrm, running, isalarm;
  7702. static UINT delay;
  7703.  
  7704. #ifdef  WIN95_IN_AN_EMERGENCY
  7705. /* we are not using this code and should never need to */
  7706. alarm_thread(VOID *args) {
  7707. #ifdef NT
  7708.     setint();
  7709. #endif /* NT */
  7710.     SetThreadPrty(XYP_REG,15);
  7711.  
  7712.     while (1) {
  7713.        sleep(1) ;
  7714.        RequestAlarmMutex( SEM_INDEFINITE_WAIT ) ;
  7715.        if ( alrm )
  7716.           if ( --delay == 0 )
  7717.           {
  7718.              debug( F100, "alarm() triggered", "", 0 ) ;
  7719.              alrm = FALSE;
  7720.              isalarm = TRUE;
  7721.              isinterrupted = 1 ;
  7722.              PostAlarmSigSem() ;
  7723.           }
  7724.           else
  7725.           {
  7726.              debug( F101, "alarm() delay","",delay ) ;
  7727.           }
  7728.        ReleaseAlarmMutex() ;
  7729.     }
  7730.  
  7731.     running = FALSE;
  7732.     ckThreadEnd(args);
  7733. }
  7734.  
  7735. unsigned
  7736. alarm(unsigned sec) {
  7737.     unsigned old;
  7738.     APIRET rc = 0 ;
  7739.     ULONG TimeInterval = sec * 1000 ;
  7740.  
  7741.     RequestAlarmMutex( SEM_INDEFINITE_WAIT ) ;
  7742.     if ( delay ) {
  7743.        debug(F101,"alarm(0) StopAlarmTimer","",rc) ;
  7744.     }
  7745.     old = delay;
  7746.     delay = sec;
  7747.  
  7748.     if ( alrm = (delay > 0) ) {
  7749.        debug(F101,"alarm(t) StartAlarmTimer: t","",TimeInterval) ;
  7750.     } else
  7751.        debug(F100,"alarm() reset","",0);
  7752.     ReleaseAlarmMutex() ;
  7753.  
  7754.     if ( !running ) {
  7755.        running = TRUE;
  7756.        tidAlarm = (TID) ckThreadBegin( &alarm_thread,THRDSTKSIZ,0,FALSE,0);
  7757.     }
  7758.     return old;
  7759. }
  7760. #else /* not WIN95_IN_AN_EMERGENCY */
  7761. static VOID
  7762. alarm_thread(VOID *args) {
  7763. #ifdef NT
  7764.     setint();
  7765. #endif /* NT */
  7766.  
  7767.     SetThreadPrty(XYP_REG,15);
  7768.  
  7769.     while (1) {
  7770.  
  7771.         WaitAlarmSem( SEM_INDEFINITE_WAIT ) ;
  7772.         RequestAlarmMutex( SEM_INDEFINITE_WAIT ) ;
  7773.         ResetAlarmSem() ;
  7774.         if ( alrm ) {
  7775.             debug( F100, "alarm() triggered", "", 0 ) ;
  7776.             alrm = FALSE;
  7777.             isalarm = TRUE;
  7778. #ifdef NT
  7779. #ifdef NTSIG
  7780.             isinterrupted = 1 ;
  7781.             PostAlarmSigSem() ;
  7782. #else /* NTSIG */
  7783.             raise(SIGALRM) ;
  7784. #endif /* NTSIG */
  7785. #else /* NT */
  7786.  
  7787.             KillProcess(pid) ;
  7788. #endif /* NT */
  7789.         }
  7790.         ReleaseAlarmMutex() ;
  7791.     }
  7792.  
  7793.    /* this will never execute */
  7794.    running = FALSE;
  7795.    ckThreadEnd(args);
  7796. }
  7797.  
  7798. static void
  7799. alarm_signal(int sig) {
  7800.     debug(F101,"alarm_signal handler","",sig) ;
  7801.     signal(SIGTERM, term_signal);
  7802.     if (isalarm) {
  7803.         isalarm = FALSE;
  7804.         raise(SIGALRM);
  7805.     } else {
  7806.         KillProcess(pid);
  7807.     }
  7808. }
  7809.  
  7810. unsigned
  7811. alarm(unsigned sec) {
  7812.     unsigned old;
  7813.     APIRET rc = 0 ;
  7814.     ULONG TimeInterval = sec * 1000 ;
  7815.  
  7816.     RequestAlarmMutex( SEM_INDEFINITE_WAIT ) ;
  7817.     if ( delay ) {
  7818.         rc = StopAlarmTimer() ;
  7819.         debug(F111,"alarm(0) StopAlarmTimer","rc",rc) ;
  7820.     }
  7821.     old = delay;
  7822.     delay = sec;
  7823.  
  7824.     if ( alrm = (delay > 0) ) {
  7825. #ifndef NTSIG
  7826.         signal(SIGTERM, alarm_signal);
  7827. #endif /* NTSIG */
  7828.         rc = StartAlarmTimer( TimeInterval ) ;
  7829.         debug(F111,"alarm() StartAlarmTimer","TimeInterval",TimeInterval) ;
  7830.         debug(F111,"alarm() StartAlarmTimer","rc",rc) ;
  7831.     } else
  7832.       debug(F100,"alarm() reset","",0);
  7833.  
  7834.     ReleaseAlarmMutex() ;
  7835.  
  7836.     if ( !running ) {
  7837.         running = TRUE;
  7838.         tidAlarm = (TID) ckThreadBegin( &alarm_thread,THRDSTKSIZ,0,FALSE,0);
  7839.     }
  7840.     return old;
  7841. }
  7842. #endif /* WIN95_IN_AN_EMERGENCY */
  7843.  
  7844. /*
  7845.  *  A public domain implementation of BSD directory routines for
  7846.  *  MS-DOS.  Written by Michael Rendell ({uunet,utai}michael@garfield),
  7847.  *  August 1897
  7848.  *  Ported to OS/2 by Kai Uwe Rommel
  7849.  *  December 1989, February 1990
  7850.  *  Change for HPFS support, October 1990
  7851.  */
  7852.  
  7853. int attributes = A_DIR | A_HIDDEN | A_RONLY | A_SYSTEM | A_ARCHIVE ;
  7854.  
  7855. static char *getdirent(char *);
  7856. static void free_dircontents(struct _dircontents *);
  7857.  
  7858. static HDIR hdir;
  7859. static U_INT count;
  7860. #ifdef NT
  7861. static WIN32_FIND_DATA find;
  7862. #else /* NT */
  7863. static FILEFINDBUF find;
  7864. #endif /* NT */
  7865.  
  7866. int IsFileSystemFAT(char *dir)
  7867. {
  7868.    USHORT nResult;
  7869. #ifdef NT
  7870.    char rootpath[4] ;
  7871.    char filesys[20];
  7872.    DWORD namemax = 0;
  7873.  
  7874.     if ( isalpha(dir[0]) && (dir[1] == ':') )
  7875.     {
  7876.         rootpath[0] = dir[0] ;
  7877.         rootpath[1] = dir[1] ;
  7878.         rootpath[2] = '\\' ;
  7879.         rootpath[3] = '\0' ;
  7880.         GetVolumeInformation( rootpath, NULL, 0, &namemax, NULL, NULL, filesys, 20 ) ;
  7881.     }
  7882.     else
  7883.     {
  7884.         GetVolumeInformation( NULL, NULL, 0, &namemax, NULL, NULL, filesys, 20 ) ;
  7885.     }
  7886.     debug(F111,"File system max name length",filesys,namemax) ;
  7887. #ifdef COMMENT
  7888.     nResult = !strcmp(filesys, "FAT");
  7889. #else
  7890.     nResult = ( namemax == 11 ) ;
  7891. #endif
  7892. #else /* NT */
  7893.     static USHORT nLastDrive = -1;
  7894.     ULONG lMap;
  7895.     BYTE bData[64], bName[3];
  7896.     U_INT nDrive, cbData;
  7897.     FSQBUFFER *pData = (FSQBUFFER *) bData;
  7898.  
  7899.     /* We separate FAT and HPFS file systems here. */
  7900.  
  7901.     if ( isalpha(dir[0]) && (dir[1] == ':') )
  7902.         nDrive = toupper(dir[0]) - '@';
  7903.     else
  7904.         DosQueryCurrentDisk(&nDrive, &lMap);
  7905.  
  7906.     if ( nDrive == nLastDrive )
  7907.         return nResult;
  7908.  
  7909.     bName[0] = (char) (nDrive + '@');
  7910.     bName[1] = ':';
  7911.     bName[2] = 0;
  7912.  
  7913.     nLastDrive = nDrive;
  7914.     cbData = sizeof(bData);
  7915.  
  7916.     if ( !DosQueryFSAttach(bName, 0, FSAIL_QUERYNAME, (PVOID) pData, &cbData) )
  7917.         nResult = !strcmp(pData -> szFSDName + pData -> cbName, "FAT");
  7918.     else
  7919.         nResult = FALSE;
  7920.  
  7921. #endif /* NT */
  7922.     return nResult;
  7923. }
  7924.  
  7925. DIR *
  7926. opendir(char *name)
  7927. {
  7928. #ifdef NT
  7929.     struct _stat statb;
  7930. #else /* NT */
  7931.     struct stat statb;
  7932. #endif /* NT */
  7933.     DIR *dirp;
  7934.     char c;
  7935.     char *s;
  7936.     struct _dircontents *dp;
  7937.     char nbuf[MAXPATHLEN + 1];
  7938.     int len;
  7939.  
  7940.     ckstrncpy(nbuf, name, MAXPATHLEN+1);
  7941.     if ((len = strlen(nbuf)) == 0)
  7942.         return NULL;
  7943.  
  7944.     if ( ((c = nbuf[len - 1]) == '\\' || c == '/') && (len > 1) )
  7945.     {
  7946.         nbuf[len - 1] = 0;
  7947.         --len;
  7948.  
  7949.         if ( nbuf[len - 1] == ':' )
  7950.         {
  7951.             ckstrncpy(nbuf + len, "\\.",MAXPATHLEN+1-len);
  7952.             len += 2;
  7953.         }
  7954.     }
  7955.     else
  7956.         if ( nbuf[len - 1] == ':' )
  7957.         {
  7958.             ckstrncpy(nbuf+len, ".",MAXPATHLEN+1-len);
  7959.             ++len;
  7960.         }
  7961.  
  7962. #ifdef NT
  7963.     if (_stat(nbuf, &statb) < 0 || (statb.st_mode & _S_IFMT) != _S_IFDIR)
  7964. #else /* NT */
  7965.     if (stat(nbuf, &statb) < 0 || (statb.st_mode & _S_IFMT) != _S_IFDIR)
  7966. #endif /* NT */
  7967.         return NULL;
  7968.  
  7969.     if ( (dirp = malloc(sizeof(DIR))) == NULL )
  7970.         return NULL;
  7971.  
  7972.     if ( nbuf[len - 1] == '.' && (len == 1 || nbuf[len - 2] != '.') )
  7973.         ckstrncpy(nbuf + len - 1, "*",MAXPATHLEN+1-len);
  7974.     else
  7975.         if ( ((c = nbuf[len - 1]) == '\\' || c == '/') && (len == 1) )
  7976.             ckstrncpy(nbuf + len, "*",MAXPATHLEN+1-len);
  7977.         else
  7978.             ckstrncpy(nbuf + len, "/*",MAXPATHLEN+1-len);
  7979.  
  7980.     dirp -> dd_loc = 0;
  7981.     dirp -> dd_contents = dirp -> dd_cp = NULL;
  7982.  
  7983.     if ((s = getdirent(nbuf)) == NULL)
  7984.         return dirp;
  7985.  
  7986.     do
  7987.     {
  7988.         if (((dp = malloc(sizeof(struct _dircontents))) == NULL) ||
  7989.              ((dp -> _d_entry = malloc(strlen(s) + 1)) == NULL)      )
  7990.         {
  7991.             if (dp)
  7992.                 free(dp);
  7993.             free_dircontents(dirp -> dd_contents);
  7994.  
  7995.             return NULL;
  7996.         }
  7997.  
  7998.         if (dirp -> dd_contents)
  7999.         {
  8000.             dirp -> dd_cp -> _d_next = dp;
  8001.             dirp -> dd_cp = dirp -> dd_cp -> _d_next;
  8002.         }
  8003.         else
  8004.             dirp -> dd_contents = dirp -> dd_cp = dp;
  8005.  
  8006.         strcpy(dp -> _d_entry, s);
  8007.         dp -> _d_next = NULL;
  8008.  
  8009. #ifdef NT
  8010.         /* I am not going to worry about this data because it is never
  8011.         used anywhere within Kermit */
  8012.         dp->_d_size = 0 ;
  8013.         dp->_d_mode = 0 ;
  8014.         dp->_d_time = 0 ;
  8015.         dp->_d_date = 0 ;
  8016. #else /* NT */
  8017.         dp -> _d_size = find.cbFile;
  8018.         dp -> _d_mode = find.attrFile;
  8019.         dp -> _d_time = *(unsigned *) &(find.ftimeLastWrite);
  8020.         dp -> _d_date = *(unsigned *) &(find.fdateLastWrite);
  8021. #endif /* NT */
  8022.     }
  8023.     while ((s = getdirent(NULL)) != NULL);
  8024.  
  8025.     dirp -> dd_cp = dirp -> dd_contents;
  8026.  
  8027.     return dirp;
  8028. }
  8029.  
  8030.  
  8031. void
  8032. closedir(DIR * dirp)
  8033. {
  8034.   free_dircontents(dirp -> dd_contents);
  8035.   free(dirp);
  8036. }
  8037.  
  8038.  
  8039. struct dirent *
  8040. readdir(DIR * dirp)
  8041. {
  8042.     static struct dirent dp;
  8043.  
  8044.     if (dirp -> dd_cp == NULL)
  8045.         return NULL;
  8046.  
  8047.     dp.d_namlen = dp.d_reclen =
  8048.         strlen(strcpy(dp.d_name, dirp -> dd_cp -> _d_entry));
  8049.  
  8050.     dp.d_ino = 1;
  8051.  
  8052.     dp.d_size = dirp -> dd_cp -> _d_size;
  8053.     dp.d_mode = dirp -> dd_cp -> _d_mode;
  8054.     dp.d_time = dirp -> dd_cp -> _d_time;
  8055.     dp.d_date = dirp -> dd_cp -> _d_date;
  8056.  
  8057.     dirp -> dd_cp = dirp -> dd_cp -> _d_next;
  8058.     dirp -> dd_loc++;
  8059.  
  8060.     return &dp;
  8061. }
  8062.  
  8063.  
  8064. void
  8065. seekdir(DIR * dirp, long off)
  8066. {
  8067.     long i = off;
  8068.     struct _dircontents *dp;
  8069.  
  8070.     if (off >= 0)
  8071.     {
  8072.         for (dp = dirp -> dd_contents; --i >= 0 && dp; dp = dp -> _d_next);
  8073.  
  8074.         dirp -> dd_loc = off - (i + 1);
  8075.         dirp -> dd_cp = dp;
  8076.     }
  8077. }
  8078.  
  8079.  
  8080. long
  8081. telldir(DIR * dirp)
  8082. {
  8083.   return dirp -> dd_loc;
  8084. }
  8085.  
  8086.  
  8087. static void
  8088. free_dircontents(struct _dircontents * dp)
  8089. {
  8090.   struct _dircontents *odp;
  8091.  
  8092.   while (dp)
  8093.   {
  8094.     if (dp -> _d_entry)
  8095.       free(dp -> _d_entry);
  8096.  
  8097.     dp = (odp = dp) -> _d_next;
  8098.     free(odp);
  8099.   }
  8100. }
  8101.  
  8102.  
  8103. char *
  8104. getdirent(char *dir)
  8105. {
  8106.     int done;
  8107.     static int lower = TRUE;
  8108.  
  8109.     if (dir != NULL)
  8110.     {                                  /* get first entry */
  8111.         lower = IsFileSystemFAT(dir);
  8112.  
  8113.         count = 1;
  8114. #ifdef NT
  8115.         hdir = FindFirstFile( dir, &find ) ;
  8116.         done = (hdir == INVALID_HANDLE_VALUE) ;
  8117. #else /* NT */
  8118.         hdir = HDIR_CREATE;
  8119.         done = DosFindFirst(dir, &hdir, attributes, &find, sizeof(find), &count);
  8120. #endif /* NT */
  8121.     }
  8122.     else                                       /* get next entry */
  8123. #ifdef NT
  8124.       done = !FindNextFile( hdir, &find ) ;
  8125.     count++ ;
  8126. #else /* NT */
  8127.     done = DosFindNext(hdir, &find, sizeof(find), &count);
  8128. #endif /* NT */
  8129.  
  8130.     if (done == 0)
  8131.     {
  8132.         if ( lower )
  8133. #ifdef NT
  8134.           _strlwr(find.cFileName) ;
  8135.         return find.cFileName;
  8136. #else /* NT */
  8137.         strlwr(find.achName);
  8138.         return find.achName;
  8139. #endif /* NT */
  8140.     }
  8141.     else
  8142.     {
  8143. #ifdef NT
  8144.         FindClose(hdir) ;
  8145. #else /* NT */
  8146.         DosFindClose(hdir);
  8147. #endif /* NT */
  8148.         return NULL;
  8149.     }
  8150. }
  8151.  
  8152. #endif /* __EMX__ */
  8153.  
  8154. #ifdef COMMENT
  8155. #ifdef NT
  8156. /* This code was used to allow external commands to be executed on Win95 */
  8157. /* by redirecting output to a file and then reading from the file        */
  8158.  
  8159. #define POPENMAX 4
  8160. static struct {
  8161.     char filename[MAX_PATH+1];
  8162.     int  read ;
  8163.     char *cmd ;
  8164.     FILE *file;
  8165. } win95p[POPENMAX] =
  8166. {
  8167.     "",0,NULL,NULL,
  8168.     "",0,NULL,NULL,
  8169.     "",0,NULL,NULL,
  8170.     "",0,NULL,NULL
  8171. };
  8172. FILE *
  8173. win95popen(char *cmd, char *mode) {
  8174.     /* Another Windows 95 bug ... */
  8175.     char popenpathname[MAX_PATH+1];
  8176.     char fullcmd[MAX_PATH*2];
  8177.     HFILE end1, end2, std, old1, old2, temp;
  8178.     char fail[256], cmd_line[256], *cmd_exe, *args, *p;
  8179.     int rc,i,n;
  8180.     extern char * tempdir ;
  8181.  
  8182.     for ( i=0; i<POPENMAX; i++ )
  8183.     {
  8184.         if ( !win95p[i].file )
  8185.           break;
  8186.     }
  8187.     if ( i == POPENMAX )
  8188.       return ((FILE *) NULL);
  8189.  
  8190.     /* Get TEMP or TMP area, if any */
  8191.  
  8192.     if (tempdir) {
  8193.         ckstrncpy(popenpathname,tempdir,MAX_PATH+1);
  8194.     } else {
  8195.         p = getenv("K95TMP");           /* ifdef NT */
  8196.         if (!p)
  8197.           p = getenv("TEMP");
  8198.         if (!p)
  8199.           p = getenv("TMP");
  8200.         if (p)
  8201.         {
  8202.             ckstrncpy(popenpathname,p,MAX_PATH+1);
  8203.         }
  8204.         else
  8205.         {
  8206.             /* None, then use K95's */
  8207.             /* own TMP directory. */
  8208.             n = ckstrncpy(popenpathname,exedir,MAX_PATH+1);
  8209.             ckstrncpy(&popenpathname[n],"TMP",MAX_PATH+1-n);
  8210.             if (!isdir(popenpathname))        /* If none, */
  8211.                 if (_mkdir(popenpathname) < 0)  /* make one. */
  8212.                     return((FILE *) NULL);
  8213.         }
  8214.     }
  8215.  
  8216.     /* Get temporary file name */
  8217.     if (!GetTempFileName(popenpathname,"K95",0,(LPTSTR) win95p[i].filename))
  8218.         return((FILE *) NULL);
  8219.  
  8220.     switch ( mode[0] ) {
  8221.     case 'r':
  8222.         win95p[i].read = 1 ;
  8223.         sprintf(fullcmd, "%s > %s", cmd, win95p[i].filename); /* Command */
  8224.         system(fullcmd);
  8225.         return (win95p[i].file = fopen(win95p[i].filename,"r"));
  8226.     case 'w':
  8227.         win95p[i].read = 0 ;
  8228.         win95p[i].cmd = strdup(cmd);
  8229.         return (win95p[i].file = fopen(win95p[i].filename,"w"));
  8230.     default:
  8231.         return ((FILE *) NULL);
  8232.     }
  8233. }
  8234.  
  8235. int
  8236. win95pclose(FILE *pipe) {
  8237.     int i;
  8238.  
  8239.     for ( i=0; i<POPENMAX ; i++)
  8240.     {
  8241.        if ( win95p[i].file == pipe )
  8242.          break;
  8243.     }
  8244.     if ( i == POPENMAX )
  8245.       return 1;
  8246.  
  8247.     fclose(pipe);
  8248.  
  8249.     if ( !win95p[i].read && win95p[i].cmd )
  8250.     {
  8251.         char fullcmd[MAX_PATH*2];
  8252.         sprintf(fullcmd, "%s < %s", win95p[i].cmd, win95p[i].filename); /* Command */
  8253.         system(fullcmd);
  8254.         free(win95p[i].cmd);
  8255.         win95p[i].cmd = NULL ;
  8256.     }
  8257.  
  8258.     zdelet(win95p[i].filename);
  8259.     win95p[i].filename[0] = '\0';
  8260.     win95p[i].file = NULL ;
  8261.     return(0);
  8262. }
  8263. #endif /* NT */
  8264. #endif /* COMMENT */
  8265.  
  8266. #ifdef NT
  8267. #ifdef COMMENT
  8268. /* This code was originally used when we did not think that there was a */
  8269. /* popen()/pclose() combination in the C Run Time Library               */
  8270. HANDLE pids[64];
  8271.  
  8272. FILE *
  8273. win95popen(char *cmd, char *mode) {
  8274.     HANDLE end1, end2;
  8275.     FILE *file;
  8276.     int  ofile;
  8277.     char fail[256], cmd_line[256], *cmd_exe, *args, *p;
  8278.     int rc, n;
  8279.     STARTUPINFO si;
  8280.     SECURITY_ATTRIBUTES sa;
  8281.     PROCESS_INFORMATION pi;
  8282.  
  8283.     debug(F110,"popen",cmd,0);
  8284.  
  8285.     memset( &sa, 0, sizeof(SECURITY_ATTRIBUTES) );     //  Initialize struct
  8286.     sa.nLength=sizeof(SECURITY_ATTRIBUTES);
  8287.     sa.lpSecurityDescriptor=NULL;
  8288.     sa.bInheritHandle=1;
  8289.  
  8290.     if (!CreatePipe(&end1, &end2, &sa, 4096))
  8291.         return NULL;
  8292.  
  8293.     cmd_exe = getenv("SHELL");
  8294.     if ( !cmd_exe )
  8295.         cmd_exe = getenv("COMSPEC");
  8296.     if ( !cmd_exe )
  8297.         cmd_exe = "cmd.exe";
  8298.  
  8299.     args = cmd_line + ckstrncpy(cmd_line, cmd_exe,256); /* do not skip zero */
  8300.  
  8301.     /* Look for MKS Shell, if found use -c instead of /c */
  8302. #ifdef NT
  8303.     _strlwr(cmd_exe);
  8304. #else
  8305.     strlwr(cmd_exe);
  8306. #endif /* NT */
  8307.     p = strstr(cmd_exe,"sh.exe");
  8308.     if ( !p )
  8309.         p = strstr(cmd_exe,"bash.exe");
  8310.     if ( !p )
  8311.         p = strstr(cmd_exe,"ash.exe");
  8312.     if ( p && (p == cmd_exe || *(p-1) == '\\' || *(p-1) == '/')) {
  8313.         sprintf(args, " -c \"%s\"",cmd);
  8314.     }
  8315.     else {
  8316.         n = ckstrncpy(args, " /c ", 256);
  8317.         ckstrncpy(args, cmd, 256-n);
  8318.     }
  8319.  
  8320.     memset( &si, 0, sizeof(STARTUPINFO) );     //  Initialize struct
  8321.     si.cb          = sizeof(STARTUPINFO);
  8322.     si.dwFlags     = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
  8323.     si.wShowWindow = 0;        //  Don't show the console window (DOS box)
  8324.  
  8325.     if ( *mode == 'r' )
  8326.         si.hStdOutput  = end2;     //  Redirect command line
  8327.     si.hStdError   = NULL;
  8328.     if ( *mode == 'w' )
  8329.         si.hStdInput   = end1;
  8330.  
  8331.     if ( !CreateProcess ( NULL,
  8332.                           cmd_line,
  8333.                           NULL,
  8334.                           NULL,
  8335.                           TRUE, // bInheritHandler
  8336.                           0,
  8337.                           NULL,
  8338.                           NULL,
  8339.                           &si,
  8340.                           &pi) )
  8341.     {
  8342.         rc = GetLastError();
  8343.         debug(F111,"popen CreateProcess failed","GetLastError",rc);
  8344.         CloseHandle(end1);
  8345.         CloseHandle(end2);
  8346.         return NULL;
  8347.     }
  8348.  
  8349.     CloseHandle(pi.hProcess);
  8350.     CloseHandle(pi.hThread);
  8351.  
  8352.     if ( *mode == 'w' )
  8353.     {
  8354.         CloseHandle(end1);
  8355.         ofile = _open_osfhandle( (long) end2, _O_APPEND );
  8356.         if ( ofile == -1 )
  8357.         {
  8358.             debug(F111,"popen _open_osfhandle failed","error",error);
  8359.             CloseHandle(end2);
  8360.             return NULL;
  8361.         }
  8362.         file = _fdopen( ofile, mode );
  8363.         pids[ofile] = pi.hProcess;
  8364.     }
  8365.     else
  8366.     {
  8367.         CloseHandle(end2);
  8368.         ofile = _open_osfhandle( (long) end1, _O_RDONLY );
  8369.         if ( ofile == -1 )
  8370.         {
  8371.             debug(F111,"popen _open_osfhandle failed","error",error);
  8372.             CloseHandle(end1);
  8373.             return NULL;
  8374.         }
  8375.         file = _fdopen( ofile, mode );
  8376.         pids[ofile] = pi.hProcess;
  8377.     }
  8378.     debug(F111,"popen","PID",pi.hProcess);
  8379.     debug(F111,"popen","FILE*",file);
  8380.     return file;
  8381. }
  8382.  
  8383. int
  8384. win95pclose(FILE *pipe) {
  8385.     int    fileno = _fileno(pipe);
  8386.     DWORD  exitcode=0;
  8387.     HANDLE handle = (HANDLE) _get_osfhandle(_fileno(pipe));
  8388.  
  8389.     debug(F111,"pclose","FILE*",pipe);
  8390.     fclose(pipe);
  8391.     if (pids[fileno]) {
  8392.         WaitForSingleObject ((HANDLE) pids[(int)fileno], INFINITE);
  8393.         if (!GetExitCodeProcess((HANDLE) pids[(int)fileno], &exitcode)) {
  8394.             exitcode = 128;
  8395.         }
  8396.         pids[fileno] = 0;
  8397.     }
  8398.  
  8399.     return (exitcode == 128 ? -1 : exitcode<<8);
  8400. }
  8401. #endif /* COMMENT */
  8402. #else /* NT */
  8403. #ifdef __IBMC__
  8404.  
  8405. /* quick hack because IBM C lacks popen() and pclose() */
  8406.  
  8407. int pids[64];
  8408.  
  8409. FILE *
  8410. popen(char *cmd, char *mode) {
  8411.   HFILE end1, end2, std, old1, old2, temp;
  8412.   FILE *file;
  8413.   char fail[256], cmd_line[256], *cmd_exe, *args, *p;
  8414.   RESULTCODES res;
  8415.   int rc, n;
  8416.  
  8417.     debug(F110,"popen",cmd,0);
  8418.     if (DosCreatePipe(&end1, &end2, 4096))
  8419.         return NULL;
  8420.  
  8421.     std = (*mode == 'w') ? 0 /* stdin */ : 1 /* stdout */;
  8422.     if (std == 0) {
  8423.         temp = end1; end1 = end2; end2 = temp;
  8424.     }
  8425.  
  8426.     old1 = -1; /* save stdin or stdout */
  8427.     DosDupHandle(std, &old1);
  8428.     DosSetFHState(old1, OPEN_FLAGS_NOINHERIT);
  8429.     temp = std; /* redirect stdin or stdout */
  8430.     DosDupHandle(end2, &temp);
  8431.  
  8432.     if ( std == 1 ) {
  8433.         old2 = -1; /* save stderr */
  8434.         DosDupHandle(2, &old2);
  8435.         DosSetFHState(old2, OPEN_FLAGS_NOINHERIT);
  8436.         temp = 2;   /* redirect stderr */
  8437.         DosDupHandle(end2, &temp);
  8438.     }
  8439.  
  8440.     DosClose(end2);
  8441.     DosSetFHState(end1, OPEN_FLAGS_NOINHERIT);
  8442.  
  8443.     cmd_exe = getenv("SHELL");
  8444.     if ( !cmd_exe )
  8445.         cmd_exe = getenv("COMSPEC");
  8446.     if ( !cmd_exe )
  8447.         cmd_exe = "cmd.exe";
  8448.  
  8449.     debug(F110,"popen cmd_exe",cmd_exe,0);
  8450.     n = ckstrncpy(cmd_line, cmd_exe, 256);
  8451.     args = cmd_line + n + 1; /* skip zero */
  8452.  
  8453.     /* Look for MKS Shell, if found use -c instead of /c */
  8454.     strlwr(cmd_exe);
  8455.     p = strstr(cmd_exe,"sh.exe");
  8456.     if ( !p )
  8457.         p = strstr(cmd_exe,"bash.exe");
  8458.     if ( !p )
  8459.         p = strstr(cmd_exe,"ash.exe");
  8460.     if ( p && (p == cmd_exe || *(p-1) == '\\' || *(p-1) == '/')) {
  8461.         sprintf(args, "-c%c%s%c",' ',cmd,0);
  8462.     }
  8463.     else {
  8464.         sprintf(args, "/c%c%s%c",' ',cmd,0);
  8465.     }
  8466.     hexdump("popen cmd_line",cmd_line,256);
  8467.  
  8468.     rc = DosExecPgm(fail, sizeof(fail), EXEC_ASYNCRESULT,
  8469.                   cmd_line, 0, &res, cmd_exe);
  8470.  
  8471.     temp = std; /* restore stdin or stdout */
  8472.     DosDupHandle(old1, &temp);
  8473.     DosClose(old1);
  8474.  
  8475.     if ( std == 1 ) {
  8476.         temp = 2;   /* restore stderr */
  8477.         DosDupHandle(old2, &temp);
  8478.         DosClose(old2);
  8479.     }
  8480.  
  8481.     if (rc) {
  8482.         debug(F111,"popen failed",fail,rc);
  8483.         DosClose(end1);
  8484.         return NULL;
  8485.     }
  8486.  
  8487.     file = fdopen(end1, mode);
  8488.     pids[end1] = res.codeTerminate;
  8489.     debug(F111,"popen","PID",res.codeTerminate);
  8490.     debug(F111,"popen","FILE*",file);
  8491.     return file;
  8492. }
  8493.  
  8494. int
  8495. pclose(FILE *pipe) {
  8496.     RESULTCODES rc;
  8497.     PID pid;
  8498.     int handle = fileno(pipe);
  8499.  
  8500.     debug(F111,"pclose","FILE*",pipe);
  8501.     fclose(pipe);
  8502.     if (pids[handle]) {
  8503.         DosWaitChild(DCWA_PROCESSTREE, DCWW_WAIT, &rc, &pid, pids[handle]);
  8504.         pids[handle] = 0;
  8505.         debug(F111,"pclose","rc.codeResult",rc.codeResult);
  8506.     }
  8507.     return rc.codeTerminate == 0 ? (rc.codeResult<<8) : -1;
  8508. }
  8509. #endif /* IBMC */
  8510. #endif /* NT */
  8511.  
  8512. #ifdef CK_REDIR
  8513. #ifdef NT
  8514. static DWORD exitcode;
  8515.  
  8516. void
  8517. ttruncmd2( HANDLE pipe )
  8518. {
  8519.     int success = 1;
  8520.     CHAR outc;
  8521.     DWORD io;
  8522.  
  8523.     while ( success && exitcode == STILL_ACTIVE ) {
  8524.         if ( success = ReadFile( pipe, &outc, 1, &io, NULL ) )
  8525.         {
  8526.             ttoc(outc) ;
  8527.         }
  8528.     }
  8529.     exitcode = 0;
  8530. }
  8531.  
  8532. int
  8533. ttruncmd(char * cmd)
  8534. { /* Return: 0 = failure, 1 = success */
  8535.     extern int pexitstat;
  8536.     int rc = 0, n;
  8537.  
  8538.     if (!cmd) return(0);
  8539.     if (!cmd[0]) return(0);
  8540.  
  8541. #ifdef COMMENT
  8542.     if ( 0 && isWin95() )
  8543.     {
  8544.         char buf[512] ;
  8545.         int n ;
  8546.         FILE * fd = win95popen(cmd,"rb");
  8547.         if ( fd )
  8548.         {
  8549.             while ( !feof(fd) )
  8550.             {
  8551.                 n = fread( buf, sizeof(char), (size_t) 512, fd ) ;
  8552.                 if ( n )
  8553.                     ttol( buf, n ) ;
  8554.             }
  8555.             pexitstat = win95pclose(fd);
  8556.             if ( pexitstat & 0xff )
  8557.                 pexitstat >>= 8 ;
  8558.             else
  8559.                 pexitstat = -4;
  8560.             return 1;
  8561.         }
  8562.         else {
  8563.             pexitstat = -4;
  8564.             return 0;
  8565.         }
  8566.     }
  8567.     else
  8568. #endif /* COMMENT */
  8569.     {
  8570.         HANDLE hSaveStdIn, hSaveStdOut, hSaveStdErr;
  8571.         HANDLE hChildStdinRd, hChildStdinWr, hChildStdinWrDup,
  8572.         hChildStdoutRd, hChildStdoutWr, hChildStdoutRdDup,
  8573.         hInputFile, hSaveStdin, hSaveStdout;
  8574.         SECURITY_ATTRIBUTES saAttr;
  8575.         BOOL fSuccess;
  8576.         PROCESS_INFORMATION procinfo ;
  8577.         STARTUPINFO         startinfo ;
  8578.         char cmd_line[256], *cmd_exe, *args, *p;
  8579.  
  8580.         pexitstat = -4;
  8581.         if (ttyfd == -1
  8582. #ifdef CK_TAPI
  8583.              || (tttapi && ttyfd == -2)
  8584. #endif /* CK_TAPI */
  8585.              ) {
  8586.             printf("?Sorry, device is not open\n");
  8587.             return 0;
  8588.         }
  8589.  
  8590.         hSaveStdOut = GetStdHandle( STD_OUTPUT_HANDLE ) ;
  8591.         hSaveStdIn  = GetStdHandle( STD_INPUT_HANDLE ) ;
  8592.         hSaveStdErr = GetStdHandle( STD_ERROR_HANDLE ) ;
  8593.  
  8594.         /* Set the bInheritHandle flag so pipe handles are inherited. */
  8595.  
  8596.         saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
  8597.         saAttr.bInheritHandle = TRUE;
  8598.         saAttr.lpSecurityDescriptor = NULL;
  8599.  
  8600.         /*
  8601.         * The steps for redirecting child's STDOUT:
  8602.         *     1.  Save current STDOUT, to be restored later.
  8603.         *     2.  Create anonymous pipe to be STDOUT for child.
  8604.         *     3.  Set STDOUT of parent to be write handle of pipe, so
  8605.         *         it is inherited by child.
  8606.         */
  8607.  
  8608.         /* Create a pipe for the child's STDOUT. */
  8609.  
  8610.         if (! CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0))
  8611.             debug(F100,"Stdout pipe creation failed\n","",0);
  8612.  
  8613.         /* Set a write handle to the pipe to be STDOUT. */
  8614.  
  8615.         if (! SetStdHandle(STD_OUTPUT_HANDLE, hChildStdoutWr) ||
  8616.              ! SetStdHandle(STD_ERROR_HANDLE, hChildStdoutWr) )
  8617.             debug(F100,"Redirecting STDOUT/STDERR failed","",0);
  8618.  
  8619.         /*
  8620.         * The steps for redirecting child's STDIN:
  8621.         *     1.  Save current STDIN, to be restored later.
  8622.         *     2.  Create anonymous pipe to be STDIN for child.
  8623.         *     3.  Set STDIN of parent to be read handle of pipe, so
  8624.         *         it is inherited by child.
  8625.         *     4.  Create a noninheritable duplicate of write handle,
  8626.         *         and close the inheritable write handle.
  8627.         */
  8628.  
  8629.         /* Create a pipe for the child's STDIN. */
  8630.  
  8631.         if (! CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0))
  8632.             debug(F100,"Stdin pipe creation failed\n","",0);
  8633.  
  8634.         /* Set a read handle to the pipe to be STDIN. */
  8635.  
  8636.         if (! SetStdHandle(STD_INPUT_HANDLE, hChildStdinRd))
  8637.             debug(F100,"Redirecting Stdin failed","",0);
  8638.  
  8639.         /* Duplicate the write handle to the pipe so it is not inherited. */
  8640.  
  8641.         fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdinWr,
  8642.                                   GetCurrentProcess(), &hChildStdinWrDup, 0,
  8643.                                   FALSE,       /* not inherited */
  8644.                                   DUPLICATE_SAME_ACCESS);
  8645.         if (! fSuccess) {
  8646.             debug(F100,"DuplicateHandle failed","",0);
  8647.  
  8648.             SetStdHandle( STD_OUTPUT_HANDLE, hSaveStdOut );
  8649.             SetStdHandle( STD_INPUT_HANDLE, hSaveStdIn );
  8650.             SetStdHandle( STD_ERROR_HANDLE, hSaveStdErr );
  8651.  
  8652.             CloseHandle(hChildStdoutRd);  hChildStdoutRd = NULL;
  8653.             CloseHandle(hChildStdoutWr);  hChildStdoutWr = NULL;
  8654.             CloseHandle(hChildStdinRd);  hChildStdinRd = NULL;
  8655.             CloseHandle(hChildStdinWr);  hChildStdinWr = NULL;
  8656.             return(0);
  8657.         }
  8658.  
  8659.         fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdoutRd,
  8660.                                     GetCurrentProcess(), &hChildStdoutRdDup, 0,
  8661.                                     FALSE,       /* not inherited */
  8662.                                     DUPLICATE_SAME_ACCESS);
  8663.         if (! fSuccess) {
  8664.             debug(F100,"DuplicateHandle failed","",0);
  8665.  
  8666.             SetStdHandle( STD_OUTPUT_HANDLE, hSaveStdOut );
  8667.             SetStdHandle( STD_INPUT_HANDLE, hSaveStdIn );
  8668.             SetStdHandle( STD_ERROR_HANDLE, hSaveStdErr );
  8669.  
  8670.             CloseHandle(hChildStdoutRd);  hChildStdoutRd = NULL;
  8671.             CloseHandle(hChildStdoutWr);  hChildStdoutWr = NULL;
  8672.             CloseHandle(hChildStdinRd);  hChildStdinRd = NULL;
  8673.             CloseHandle(hChildStdinWr);  hChildStdinWr = NULL;
  8674.             return(0);
  8675.         }
  8676.  
  8677.       CloseHandle(hChildStdinWr);
  8678.         hChildStdinWr = NULL;
  8679.  
  8680.       cmd_line[0] = '\0' ;
  8681.       /* Now create the child process. */
  8682.  
  8683.  
  8684.         cmd_exe = getenv("SHELL");
  8685.         if ( !cmd_exe )
  8686.             cmd_exe = getenv("COMSPEC");
  8687.         if ( !cmd_exe )
  8688.             cmd_exe = "cmd.exe";
  8689.  
  8690.       n = ckstrncpy(cmd_line, cmd_exe, 256);
  8691.       args = cmd_line + n; /* don't skip zero */
  8692.  
  8693.         /* Look for MKS Shell, if found use -c instead of /c */
  8694.         _strlwr(cmd_exe);
  8695.         p = strstr(cmd_exe,"sh.exe");
  8696.         if ( !p )
  8697.             p = strstr(cmd_exe,"bash.exe");
  8698.         if ( !p )
  8699.             p = strstr(cmd_exe,"ash.exe");
  8700.         if ( p && (p == cmd_exe || *(p-1) == '\\' || *(p-1) == '/')) {
  8701.             sprintf(args, " -c \"%s\"",cmd);
  8702.         }
  8703.         else {
  8704.             int m;
  8705.             m = ckstrncpy(args, " /c ", 256 - n);
  8706.             ckstrncpy(&args[m], cmd, 256 - n - m);
  8707.         }
  8708.  
  8709.       memset( &startinfo, 0, sizeof(STARTUPINFO) ) ;
  8710.       startinfo.cb = sizeof(STARTUPINFO) ;
  8711.  
  8712.       fSuccess = CreateProcess( NULL,       /* application name */
  8713.                      cmd_line,              /* command line */
  8714.                      NULL,                  /* process security attributes */
  8715.                      NULL,                  /* primary thread security attrs */
  8716.                      TRUE,                  /* inherit handles */
  8717.                      NORMAL_PRIORITY_CLASS, /* creation flags */
  8718.                      NULL,                  /* use parent's environment */
  8719.                      NULL,                  /* use parent's current directory */
  8720.                      &startinfo,            /* startup info */
  8721.                      &procinfo ) ;          /* proc info returned */
  8722.  
  8723.         if ( !SetStdHandle( STD_OUTPUT_HANDLE, hSaveStdOut ) ||
  8724.              !SetStdHandle( STD_INPUT_HANDLE, hSaveStdIn ) ||
  8725.              !SetStdHandle( STD_ERROR_HANDLE, hSaveStdErr ) )
  8726.         {
  8727.             debug( F101,"ttruncmd Unable to restore standard handles","",GetLastError() ) ;
  8728.             CloseHandle(hChildStdoutRd);  hChildStdoutRd = NULL;
  8729.             CloseHandle(hChildStdoutWr);  hChildStdoutWr = NULL;
  8730.             CloseHandle(hChildStdinRd);  hChildStdinRd = NULL;
  8731.             CloseHandle(hChildStdinWrDup);  hChildStdinWrDup = NULL;
  8732.         }
  8733.  
  8734.         if ( !fSuccess ) {
  8735.             CloseHandle(hChildStdoutRd);  hChildStdoutRd = NULL;
  8736.             CloseHandle(hChildStdoutWr);  hChildStdoutWr = NULL;
  8737.             CloseHandle(hChildStdinRd);  hChildStdinRd = NULL;
  8738.             CloseHandle(hChildStdinWrDup);  hChildStdinWrDup = NULL;
  8739.             return(0);
  8740.         }
  8741.  
  8742.         CloseHandle(procinfo.hProcess);
  8743.         CloseHandle(procinfo.hThread);
  8744.  
  8745.         exitcode = STILL_ACTIVE;
  8746.         _beginthread( ttruncmd2, 65536, hChildStdoutRd );
  8747.         do {
  8748.             DWORD io ;
  8749.             int  inc ;
  8750.             unsigned char outc ;
  8751.  
  8752.             inc = ttinc( 1 ) ;
  8753.             if ( inc < -1 )
  8754.                 break ;
  8755.             else if ( inc >= 0 )
  8756.             {
  8757.                 if ( !WriteFile( hChildStdinWrDup, &inc, 1, &io, NULL ) )
  8758.                 {
  8759.                     debug(F101,"ttruncmd unable to write to child","",GetLastError());
  8760.                     break;
  8761.                 }
  8762.                 continue;
  8763.             }
  8764.             // Give the process time to execute and finish
  8765.             if (WaitForSingleObject(procinfo.hProcess, 0L) == WAIT_OBJECT_0) {
  8766.                 GetExitCodeProcess(procinfo.hProcess, &exitcode);
  8767.             }
  8768.         } while ( exitcode == STILL_ACTIVE );
  8769.         debug(F111, "ttruncmd","exitcode",exitcode);
  8770.  
  8771.         if ( exitcode == STILL_ACTIVE )
  8772.             exitcode = 128;
  8773.  
  8774.         /* Close the pipe handle so the child stops reading. */
  8775.         CloseHandle(hChildStdoutRd);    hChildStdoutRd = NULL;
  8776.         CloseHandle(hChildStdoutWr);    hChildStdoutWr = NULL;
  8777.         CloseHandle(hChildStdinRd);     hChildStdinRd = NULL;
  8778.         CloseHandle(hChildStdinWrDup);  hChildStdinWrDup = NULL;
  8779.  
  8780.         CloseHandle( procinfo.hProcess ) ;
  8781.         CloseHandle( procinfo.hThread ) ;
  8782.  
  8783.         pexitstat = exitcode;
  8784.         return (exitcode>=0 ? 1 : 0);
  8785.     }
  8786.     return 0;   /* Should never be reached */
  8787. }
  8788. #else /* not NT */
  8789. #define STILL_ACTIVE -1L
  8790. static ULONG exitcode = 0;
  8791. void
  8792. ttruncmd2( HFILE pipe )
  8793. {
  8794.     int success = 1;
  8795.     CHAR outc;
  8796.     ULONG io;
  8797.  
  8798.     while ( success && exitcode == STILL_ACTIVE ) {
  8799.         if ( success = !DosRead( pipe, &outc, 1, &io ) )
  8800.         {
  8801.             ttoc(outc) ;
  8802.         }
  8803.     }
  8804.     exitcode = 0;
  8805. }
  8806.  
  8807. int
  8808. ttruncmd(cmd) char *cmd; { /* Return: 0 = failure, 1 = success */
  8809.   extern int pexitstat;
  8810.     HFILE hSaveStdOut=-1, hSaveStdIn=-1, hSaveStdErr=-1;
  8811.     HFILE hChildStdoutRd, hChildStdoutWr, hChildStdinRd, hChildStdinWr;
  8812.     HFILE temp;
  8813.     FILE *file;
  8814.     char fail[256], cmd_line[256], *cmd_exe, *args, *p;
  8815.     RESULTCODES res;
  8816.     PID pid, pid2;
  8817.     int n, rc;
  8818.  
  8819.     debug(F110,"ttruncmd",cmd,0);
  8820.  
  8821.     /* Save existing handles */
  8822.     DosDupHandle(0,&hSaveStdIn);
  8823.     DosSetFHState(hSaveStdIn, OPEN_FLAGS_NOINHERIT);
  8824.     DosDupHandle(1,&hSaveStdOut);
  8825.     DosSetFHState(hSaveStdOut, OPEN_FLAGS_NOINHERIT);
  8826.     DosDupHandle(2,&hSaveStdErr);
  8827.     DosSetFHState(hSaveStdErr, OPEN_FLAGS_NOINHERIT);
  8828.  
  8829.     /* Create a pipe for the child's STDOUT */
  8830.     if (DosCreatePipe(&hChildStdoutRd, &hChildStdoutWr, 4096))
  8831.         debug(F100,"Stdout pipe creation failed\n","",0);
  8832.  
  8833.     /* Set a write handle to the pipe to be STDOUT */
  8834.     temp = 1;   /* stdout */
  8835.     DosDupHandle(hChildStdoutWr, &temp);
  8836.     temp = 2;   /* stderr */
  8837.     DosDupHandle(hChildStdoutWr, &temp);
  8838.  
  8839.     /* Create a pipe for the child's STDOUT */
  8840.     if (DosCreatePipe(&hChildStdinRd, &hChildStdinWr, 4096))
  8841.         debug(F100,"Stdout pipe creation failed\n","",0);
  8842.  
  8843.     /* Set a write handle to the pipe to be STDOUT */
  8844.     temp = 0;   /* stdin */
  8845.     DosDupHandle(hChildStdinRd, &temp);
  8846.  
  8847.     DosSetFHState(hChildStdoutRd, OPEN_FLAGS_NOINHERIT);
  8848.     DosSetFHState(hChildStdinWr, OPEN_FLAGS_NOINHERIT);
  8849.  
  8850.     cmd_exe = getenv("SHELL");
  8851.     if ( !cmd_exe )
  8852.         cmd_exe = getenv("COMSPEC");
  8853.     if ( !cmd_exe )
  8854.         cmd_exe = "cmd.exe";
  8855.  
  8856.     n = ckstrncpy(cmd_line, cmd_exe, 256);
  8857.     args = cmd_line + n + 1; /* skip zero */
  8858.  
  8859.     /* Look for MKS Shell, if found use -c instead of /c */
  8860.     strlwr(cmd_exe);
  8861.     p = strstr(cmd_exe,"sh.exe");
  8862.     if ( !p )
  8863.         p = strstr(cmd_exe,"bash.exe");
  8864.     if ( !p )
  8865.         p = strstr(cmd_exe,"ash.exe");
  8866.     if ( p && (p == cmd_exe || *(p-1) == '\\' || *(p-1) == '/')) {
  8867.         sprintf(args, "-c%c%s%c",0,cmd,0);
  8868.     }
  8869.     else {
  8870.         sprintf(args, "/c%c%s%c",0,cmd,0);
  8871.     }
  8872.     rc = DosExecPgm(fail, sizeof(fail), EXEC_ASYNCRESULT,
  8873.                     args, 0, &res, cmd_exe);
  8874.  
  8875.     /* Restore Standard Handles for this process */
  8876.     temp = 0;
  8877.     DosDupHandle(hSaveStdIn,&temp);
  8878.     temp = 1;
  8879.     DosDupHandle(hSaveStdOut,&temp);
  8880.     temp = 2;
  8881.     DosDupHandle(hSaveStdErr,&temp);
  8882.  
  8883.     if (rc) {
  8884.         debug(F111,"ttruncmd failed",fail,rc);
  8885.         DosClose(hChildStdinRd);
  8886.         DosClose(hChildStdinWr);
  8887.         DosClose(hChildStdoutRd);
  8888.         DosClose(hChildStdoutWr);
  8889.         return 1;
  8890.     }
  8891.  
  8892.     pid = res.codeTerminate;
  8893.     debug(F111,"ttruncmd","PID",pid);
  8894.  
  8895.     exitcode = STILL_ACTIVE;
  8896.     _beginthread( ttruncmd2, 0, 65536, hChildStdoutRd );
  8897.     do {
  8898.         ULONG io ;
  8899.         int inc ;
  8900.         CHAR outc ;
  8901.  
  8902.         inc = ttinc( 1 ) ;
  8903.         if ( inc < -1 )
  8904.             break ;
  8905.         else if ( inc >= 0 )
  8906.         {
  8907.             if ( rc = DosWrite( hChildStdinWr, &inc, 1, &io ) )
  8908.             {
  8909.                 debug(F101,"ttruncmd unable to write to child","",rc);
  8910.                 break;
  8911.             }
  8912.             continue;
  8913.         }
  8914.         res.codeTerminate = 99;
  8915.         rc = DosWaitChild(DCWA_PROCESSTREE, DCWW_NOWAIT, &res, &pid2, pid);
  8916.         if ( (rc==0) && (res.codeTerminate != 99) ) {
  8917.             exitcode = res.codeResult;
  8918.         }
  8919.  
  8920.     } while ( exitcode == STILL_ACTIVE );
  8921.     if ( exitcode == STILL_ACTIVE && pid )
  8922.     {
  8923.         exitcode = 128;
  8924.         if (!DosWaitChild(DCWA_PROCESSTREE, DCWW_WAIT, &res, &pid2, pid))
  8925.             exitcode = res.codeResult;
  8926.         debug(F111,"ttruncmd","res.codeResult",res.codeResult);
  8927.  
  8928.     }
  8929.  
  8930.     DosClose(hChildStdinRd);
  8931.     DosClose(hChildStdinWr);
  8932.     DosClose(hChildStdoutRd);
  8933.     DosClose(hChildStdoutWr);
  8934.  
  8935.     pexitstat = exitcode;
  8936.     return (exitcode>=0 ? 1 : 0);
  8937. }
  8938. #endif /* NT */
  8939. #endif /* CK_REDIR */
  8940.  
  8941. /*
  8942.   Keyboard                        Hardware ID
  8943.   PC AT* Standard Keyboard        0001H
  8944.   101 Key Enhanced Keyboard and   AB41H
  8945.   102 Key Enhanced Keyboard
  8946.    88 Key Enhanced Keyboard and   AB54H
  8947.    89 Key Enhanced Keyboard
  8948.   122 Key Mainframe Interactive   AB86H
  8949.       (MFI) Keyboard
  8950. */
  8951. static char os2kbt[20];
  8952. char *
  8953. conkbg(void) {
  8954.     int x=0;
  8955.     char * p=os2kbt;
  8956. #ifdef NT
  8957.     os2kbt[0] = '\0' ;
  8958.     switch (GetKeyboardType(0))  /* Get Keyboard subtype */
  8959.     {
  8960.     case 1:
  8961.         x=83;
  8962.         break;
  8963.     case 2:
  8964.     case 4:
  8965.         x=102;
  8966.         break;
  8967.     case 3:
  8968.         x = 84 ;
  8969.         break;
  8970.     case 5:
  8971.         x=1050;
  8972.         break;
  8973.     case 6:
  8974.         x=9140;
  8975.         break;
  8976.     default:
  8977.         x=0 ;
  8978.     }
  8979.  
  8980.     if (x)                              /* If it's known model */
  8981.         sprintf(p,"%d",x);              /* use its "name" */
  8982.     else                                /* otherwise */
  8983.         sprintf(p,"unknown"); /* unknown */
  8984. #else /* NT */
  8985.     KBDHWID kbID        ;
  8986.     int rc=0;
  8987.  
  8988.     *p = '\0';
  8989.  
  8990.     memset( &kbID, 0, sizeof(kbID) ) ;
  8991.  
  8992.     kbID.cb = sizeof(kbID);
  8993.     KbdGetHWID(&kbID, KbdHandle);
  8994.     debug(F101,"conkbg","",kbID.idKbd);
  8995.     switch (kbID.idKbd) {
  8996.     case 0x0001:                        /* PC/AT keyboard */
  8997.     case 0xab54:                        /* PC or PC/XT 88 or 89 key */
  8998.         x = 88;
  8999.         break;
  9000.     case 0xab41:                        /* 101 or 102 enhanced keyboard */
  9001.     case 0xab83:
  9002.         x = 101;
  9003.         break;
  9004.     case 0xab86:                        /* 122-key "mainframe interactive" */
  9005.         x = 122;
  9006.         break;
  9007.     default:
  9008.         x = 0; break;   /* Something else... */
  9009.     }
  9010.     if (x)                              /* If it's known model */
  9011.         sprintf(p,"%d",x);              /* use its "name" */
  9012.     else                                /* otherwise */
  9013.         sprintf(p,"%04X",(int) kbID.idKbd); /* use the hex code */
  9014. #endif /* NT */
  9015.  
  9016.     return(p);                          /* Return string pointer */
  9017. };
  9018.  
  9019.  
  9020. #ifdef CK_LABELED
  9021. static CHAR os2version[50] ;
  9022.  
  9023. char *
  9024. get_os2_vers() {
  9025.     APIRET rc ;
  9026. #ifdef NT
  9027.     OSVERSIONINFO verinfo ;
  9028.     verinfo.dwOSVersionInfoSize=sizeof(OSVERSIONINFO);
  9029.  
  9030.     rc = !GetVersionEx( &verinfo ) ;
  9031.     if ( rc ) {
  9032.         os2version[0] = '\0';
  9033.     } else {
  9034.         sprintf(os2version,"%s %02d.%02d.%02d",
  9035.                 verinfo.dwPlatformId == VER_PLATFORM_WIN32_NT ? "WinNT" :
  9036.                 verinfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS ?
  9037.                  (verinfo.dwMinorVersion == 0 ? "Win95" : "Win98")  :
  9038.                 verinfo.dwPlatformId == VER_PLATFORM_WIN32_WIN32S ? "Win32s" :
  9039.                 "unknown",
  9040.                 verinfo.dwMajorVersion,
  9041.                 verinfo.dwMinorVersion,
  9042.                 verinfo.dwBuildNumber );
  9043.     }
  9044. #else /* NT */
  9045.     ULONG StartIndex = QSV_VERSION_MAJOR ; /* Major Version Number */
  9046.     ULONG EndIndex   = QSV_VERSION_REVISION ; /* Revision Letter      */
  9047.     ULONG DataBuf[3] ;
  9048.     ULONG DataBufLen = 3 * sizeof(ULONG) ;
  9049.  
  9050.     rc = DosQuerySysInfo( StartIndex,
  9051.                           EndIndex,
  9052.                           DataBuf,
  9053.                           DataBufLen );
  9054.  
  9055.     if (rc)
  9056.       os2version[0] = '\0' ;
  9057.     else
  9058.       sprintf(os2version,"%02d.%02d%c",DataBuf[0],DataBuf[1],DataBuf[2]) ;
  9059. #endif /* NT */
  9060.     return os2version ;
  9061. }
  9062. #endif /* CK_LABELED */
  9063.  
  9064. #ifdef CK_REXX
  9065. extern char * mrval[] ;
  9066. extern int maclvl ;
  9067.  
  9068. /* This is the CkCommand/CKermit function handler.  It is an undocumented  */
  9069. /* Kermit feature.  Do not remove this code.                             */
  9070.  
  9071. ULONG APIENTRY
  9072. os2rexxckcmd(
  9073.     PUCHAR Name,
  9074.     ULONG Argc,
  9075.     PRXSTRING Argv,
  9076.     PSZ Queuename,
  9077.     PRXSTRING Retstr) {
  9078.     int rc = 0 ;
  9079.     int i ;
  9080.  
  9081.     for ( i = 0 ; i < Argc ; i++ ) {
  9082.         rc = domac("_rexx_commands",RXSTRPTR(Argv[i]),CF_REXX);
  9083.         debug(F111,"os2rexxckcmd",RXSTRPTR(Argv[i]),rc);
  9084.         delmac("_rexx_commands",0);
  9085.         if (rc < 0) break ;
  9086.     }
  9087.     if ( mrval[maclvl+1] ) {
  9088.        MAKERXSTRING(*Retstr,
  9089.                     strdup(mrval[maclvl+1]),
  9090.                     strlen(mrval[maclvl+1])
  9091.                     ) ;
  9092.     } else
  9093.        MAKERXSTRING( *Retstr, strdup(""), 0 ) ;
  9094.  
  9095.     return (rc < 0 ? rc : 0 ) ;
  9096. }
  9097.  
  9098. ULONG APIENTRY
  9099. os2rexxsubcom(
  9100.     PRXSTRING Command,
  9101.     PUSHORT pFlags,
  9102.     PRXSTRING Retstr)
  9103. {
  9104.    int rc = 0 ;
  9105.  
  9106.    rc = domac("_rexx_commands",RXSTRPTR(Command[0]),CF_REXX);
  9107.    debug(F111,"os2rexxsubcom",RXSTRPTR(Command[0]),rc);
  9108.    delmac("_rexx_commands",0);
  9109.  
  9110.    *pFlags = rc < 0 ? RXSUBCOM_ERROR : RXSUBCOM_OK;
  9111.  
  9112.    if ( mrval[maclvl+1] ) {
  9113.       MAKERXSTRING(*Retstr,
  9114.       strdup(mrval[maclvl+1]),
  9115.       strlen(mrval[maclvl+1])) ;
  9116.    } else
  9117.       MAKERXSTRING( *Retstr, strdup(""), 0 ) ;
  9118.    return 0;
  9119. }
  9120.  
  9121. int
  9122. os2rexx( char * rexxcmd, char * rexxbuf, int rexxbuflen ) {
  9123.     long return_code  ;  /* rexx interpreter return code */
  9124.     short     rc      ;  /* converted return code   */
  9125.     char      return_buffer[256] ; /*returned buffer*/
  9126.     RXSTRING  Instore[2] ; /* Instorage rexx procedure */
  9127.     RXSTRING  retstr  ;  /* program return value    */
  9128.     int       retval  ;  /* os2rexx return value    */
  9129.  
  9130.     MAKERXSTRING( Instore[0], rexxcmd, strlen(rexxcmd) ) ;
  9131.     MAKERXSTRING( Instore[1], 0, 0 ) ;
  9132.     MAKERXSTRING( retstr, return_buffer, sizeof(return_buffer) ) ;
  9133.  
  9134.     debug(F110,"os2rexx: procedure",rexxcmd,0);
  9135.     return_code = RexxStart( 0,   /* no program arguments */
  9136.                              0,   /* null argument list   */
  9137.                             "Kermit for OS/2 REXX Command",
  9138.                                                /* default program name */
  9139.                             Instore, /* rexx procedure to interpret */
  9140.                             "CKermit",         /* default address name */
  9141.                             RXFUNCTION,         /* calling as a function */
  9142.                             0,                  /* no exits used */
  9143.                             &rc,                /* converted return code */
  9144.                             &retstr);           /* returned result */
  9145.  
  9146.     debug(F111,"os2rexx: returns",RXSTRPTR(retstr),return_code);
  9147.     if ( !return_code && RXSTRLEN( retstr ) < rexxbuflen ) {
  9148.         ckstrncpy( rexxbuf, RXSTRPTR(retstr), RXSTRLEN( retstr ) );
  9149.         retval = 0 ;                    /* Success */
  9150.     } else {
  9151.         rexxbuf[0] = '\0' ;
  9152.         retval = 1 ;                    /* Failure */
  9153.     }
  9154.     if (RXSTRPTR(retstr) != return_buffer)
  9155.       DosFreeMem(RXSTRPTR(retstr));
  9156.  
  9157.     return retval ;
  9158. }
  9159. int
  9160. os2rexxinit()
  9161. {
  9162.    /* this next line installs the CkCommand statement into the Rexx    */
  9163.    /* interpretter environment.  We have replaced it with a subcommand */
  9164.    /* handler instead.  Both mechanisms can co-exist, so we leave in   */
  9165.    /* the CkCommand/CKermit as an undocumented function.               */
  9166.  
  9167.    RexxRegisterFunctionExe("CKermit",(PFN)os2rexxckcmd) ;
  9168.    RexxRegisterFunctionExe("CKCommand",(PFN)os2rexxckcmd) ;
  9169.    RexxRegisterSubcomExe("CKermit",(PFN)os2rexxsubcom, NULL);
  9170.     return 0 ;
  9171. }
  9172.  
  9173. #endif /* CK_REXX */
  9174.  
  9175. int
  9176. os2settitle(char *newtitle, int newpriv ) {
  9177. #ifndef NOLOCAL
  9178.     extern int StartedFromDialer ;
  9179.     extern LONG KermitDialerID ;
  9180. #ifndef NT
  9181.     HSWITCH hSwitch;
  9182.     SWCNTRL swctl;
  9183. #endif /* NT */
  9184.     static char title[80]="not yet set";
  9185.     static int  private = 1;
  9186.     char titlebuf[128] ;
  9187.     extern enum markmodes markmodeflag[];
  9188.     extern bool scrollflag[] ;
  9189.     extern int vmode;
  9190.     extern int inserver;
  9191.     char * videomode = "";
  9192.  
  9193.     switch ( markmodeflag[vmode] ) {
  9194.     case notmarking:
  9195.         if ( scrollflag[vmode] )
  9196.             videomode = " [Scrollback]";
  9197.         break;
  9198.     case inmarkmode:
  9199.         videomode = " [Mark Mode]";
  9200.         break;
  9201.     case marking:
  9202.         videomode = " [Marking]";
  9203.         break;
  9204.     }
  9205.  
  9206.     if ( newtitle ) {
  9207.         ckstrncpy(title,newtitle,80);
  9208.         private = newpriv;
  9209.     }
  9210.  
  9211.     if ( usertitle[0] ) {
  9212.         if ( StartedFromDialer ) {
  9213.             sprintf( titlebuf, "%d::%s%s%s",KermitDialerID,usertitle,
  9214.                  private ? (inserver ? " - IKS" : " - K-95") : "", 
  9215.                      videomode
  9216.                  );
  9217.         }
  9218.         else {
  9219.             sprintf( titlebuf, "%s%s%s",usertitle,
  9220.                  private ? (inserver ? " - IKS" : " - K-95") : "", videomode
  9221.                  );
  9222.         }
  9223.     }
  9224.     else if ( StartedFromDialer ) {
  9225.         sprintf( titlebuf, "%d::%s%s%s%s",KermitDialerID,title,(*title&&private)?" - ":"",
  9226.                  private ? (inserver ? "IKS" : "K-95") :  "", videomode
  9227.                  );
  9228.     }
  9229.     else {
  9230.         sprintf( titlebuf, "%s%s%s%s",title,(*title&&private)?" - ":"",
  9231.                  private ? (inserver ? "IKS" : "K-95") : "" , videomode
  9232.                  );
  9233.     }
  9234.  
  9235. #ifdef NT
  9236. #ifdef KUI
  9237.     KuiSetProperty(KUI_TITLE,(long)titlebuf,(long)0) ;
  9238.     return 1;
  9239. #else /* KUI */
  9240.     return !SetConsoleTitle(titlebuf);
  9241. #endif /* KUI */
  9242. #else /* NT */
  9243.     /* This changes the text in the task list. */
  9244.     /* That the window handle (first parameter) in the WinQuerySwitchHandle */
  9245.     /* call can be NULL is fully documented in the API description. */
  9246.  
  9247.     hSwitch = WinQuerySwitchHandle((HWND) NULL, pid);
  9248.     WinQuerySwitchEntry(hSwitch, &swctl);
  9249.     strcpy(swctl.szSwtitle, titlebuf);
  9250.     WinChangeSwitchEntry(hSwitch, &swctl);
  9251. #ifdef CK_SETTITLE
  9252.     {
  9253.         /* and this undocumented call changes the session title */
  9254.         extern APIRET16 APIENTRY16 Win16SetTitle(HWND hwnd, PSZ szTitle);
  9255.         extern APIRET16 APIENTRY16 Win16SetTitleAndIcon(HWND hwnd, PSZ szTitle,
  9256.         PSZ szIconFile );
  9257.         Win16SetTitle( 0, titlebuf ) ;
  9258. /*     Win16SetTitleAndIcon( 0, title, "ckermit.ico" ) ; */
  9259.     }
  9260. #else /* CK_SETTITLE */
  9261.     zsyscmd( "exit" ) ;
  9262. #endif /* CK_SETTITLE */
  9263.     return 0;
  9264. #endif /* NT */
  9265. #else /* NOLOCAL */
  9266.     return(0);
  9267. #endif /* NOLOCAL */
  9268. }
  9269.  
  9270. int
  9271. os2gettitle(char *buffer, int size) {
  9272. #ifndef NOLOCAL
  9273.     extern enum markmodes markmodeflag[];
  9274.     extern bool scrollflag[] ;
  9275.     extern int vmode;
  9276.     int len;
  9277. #ifdef OS2ONLY
  9278.     HSWITCH hSwitch;
  9279.     SWCNTRL swctl;
  9280. #endif /* OS2ONLY */
  9281.  
  9282.     if ( buffer == NULL )
  9283.         return(-1);
  9284.     buffer[0] = '\0';
  9285.  
  9286. #ifdef NT
  9287.     if ( GetConsoleTitle(buffer, size) ) {
  9288.         len = strlen(buffer);
  9289.  
  9290.         switch ( markmodeflag[vmode] ) {
  9291.         case notmarking:
  9292.             if ( scrollflag[vmode] && len >= 13)
  9293.                 buffer[len-13] = '\0';
  9294.             break;
  9295.         case inmarkmode:
  9296.             if ( len >= 12 )
  9297.                 buffer[len-12] = '\0';
  9298.             break;
  9299.         case marking:
  9300.             if ( len >= 10 )
  9301.                 buffer[len-10] = '\0';
  9302.             break;
  9303.         }
  9304.         return(0);
  9305.     }
  9306.     else return GetLastError();
  9307. #else /* NT */
  9308.  
  9309.     /* Query the text in the task list */
  9310.  
  9311.     hSwitch = WinQuerySwitchHandle( (HWND) NULL, pid);
  9312.     WinQuerySwitchEntry(hSwitch, &swctl);
  9313.     ckstrncpy(buffer, swctl.szSwtitle, size);
  9314.  
  9315. #ifdef OS2PM
  9316.     /* Only documented for PM applications */
  9317.     WinQuerySessionTitle(hab, 0, buffer, size);
  9318. #endif /* OS2PM */
  9319.  
  9320.     len = strlen(buffer);
  9321.  
  9322.     switch ( markmodeflag[vmode] ) {
  9323.     case notmarking:
  9324.         if ( scrollflag[vmode] && len >= 13)
  9325.             buffer[len-13] = '\0';
  9326.         break;
  9327.     case inmarkmode:
  9328.         if ( len >= 12 )
  9329.             buffer[len-12] = '\0';
  9330.         break;
  9331.     case marking:
  9332.         if ( len >= 10 )
  9333.             buffer[len-10] = '\0';
  9334.         break;
  9335.     }
  9336.     return 0;
  9337. #endif /* NT */
  9338. #else /* NOLOCAL */
  9339.     return(-1);
  9340. #endif /* NOLOCAL */
  9341. }
  9342.  
  9343.  
  9344. #ifndef NT
  9345. HFILE ReadPipe = (HFILE) 0;
  9346. APIRET
  9347. ConnectToPM( void ) {
  9348.     APIRET rc = 0 ;
  9349.     UCHAR PipeName[256] = {""};
  9350.     ULONG ulOpenMode = NP_ACCESS_INBOUND | NP_NOINHERIT,
  9351.     ulPipeMode = NP_WMESG | NP_RMESG | NP_NOWAIT | 0x01,
  9352.     ulOutBufSize = 1024,
  9353.     ulInpBufSize = 1024,
  9354.     ulTimeout = 2000L,
  9355.     ulBytesDone = 0 ;
  9356.  
  9357.  
  9358.     if ( StartedFromDialer ) {
  9359.         sprintf( PipeName, "\\PIPE\\K2DIAL\\%d",KermitDialerID );
  9360.         rc = DosCreateNPipe(PipeName, &ReadPipe, ulOpenMode, ulPipeMode,
  9361.                              ulOutBufSize, ulInpBufSize, ulTimeout);
  9362.         debug(F111,"DosCreateNPipe",PipeName,rc);
  9363.         if ( !rc ) {
  9364.             rc = DosConnectNPipe( ReadPipe );
  9365.             debug(F111,"DosConnectNPipe",PipeName,rc);
  9366.             DialerSend( OPT_KERMIT_HWND, (ULONG) 0 ) ;
  9367.         }
  9368.  
  9369.     }
  9370.     return rc;
  9371. }
  9372.  
  9373. APIRET
  9374. ReadFromPM( char * Buf, ULONG len, ULONG * BytesRead ) {
  9375.     APIRET rc ;
  9376.     AVAILDATA availdata = {0,0};
  9377.     ULONG  State = 0;
  9378.     static query = 0 ;
  9379.  
  9380.     if ( !StartedFromDialer || !ReadPipe || !Buf || !len || !BytesRead )
  9381.         return -1 ;
  9382.  
  9383.     query = (query + 1)%20 ;    /* Only check once per second or there abouts */
  9384.     if ( query )
  9385.         return -1;
  9386.  
  9387.     rc = DosPeekNPipe( ReadPipe, Buf, 1, BytesRead,
  9388.                        &availdata, &State ) ;
  9389.     switch ( rc ) {
  9390.     case ERROR_BAD_PIPE:
  9391.         StartedFromDialer = 0 ;
  9392.         DisconnectFromPM() ;
  9393.         return -1;
  9394.     case NO_ERROR:
  9395.         if ( State == NP_STATE_CONNECTED && availdata.cbmessage )
  9396.             break;
  9397.     default:
  9398.         return -1;
  9399.     }
  9400.  
  9401.     *Buf = '\0' ;
  9402.     *BytesRead = 0 ;
  9403.     rc = DosRead ( ReadPipe, Buf, len, BytesRead ) ;
  9404.     debug(F111,"ReadFromPM",Buf,rc);
  9405.     return rc;
  9406. }
  9407.  
  9408. APIRET
  9409. DisconnectFromPM( void ) {
  9410.     APIRET rc = 0 ;
  9411.  
  9412.     if ( StartedFromDialer ) {
  9413.         rc = DosDisConnectNPipe( ReadPipe ) ;
  9414.         rc = DosClose( ReadPipe );
  9415.         ReadPipe = 0L ;
  9416.     }
  9417.     return rc;
  9418. }
  9419. #endif /* OS2PM */
  9420.  
  9421. void
  9422. demoscrn(int vmode)
  9423. {
  9424. #ifndef NOLOCAL
  9425. #ifdef SESLIMIT
  9426.     extern int seslimit;
  9427.  
  9428.     if ( !(downloaded && expired) )
  9429.         return;
  9430.  
  9431.     popupdemo(vmode, seslimit - (time(NULL) - start_time));
  9432. #endif /* NOLOCAL */
  9433. #endif /* SESLIMIT */
  9434. }
  9435.  
  9436. int
  9437. chkexp( void )
  9438. {
  9439. #ifndef NOLOCAL
  9440.     extern unsigned char colorcmd ;
  9441.     extern int expmon, expday, expyear ;
  9442.     time_t ltime, etime ;
  9443.     struct tm expires;
  9444.     int i;
  9445.     int    dsn ;  /* decoded serial number */
  9446. #ifdef SESLIMIT
  9447.     extern int seslimit;            /* Session Time Limit */
  9448. #endif /* SESLIMIT */
  9449.  
  9450.     memset( &expires, 0, sizeof(struct tm) ) ;
  9451.     expires.tm_mday = expday ;
  9452.     expires.tm_mon = expmon ;
  9453.     expires.tm_year = expyear ;
  9454.     etime = mktime( &expires ) + 24 * 60 * 60;
  9455.     ltime = time(NULL);
  9456.  
  9457.     colorcmd ^= 0x8 ;
  9458.     dsn = isregistered(NULL) ;
  9459.  
  9460. #ifdef BETATEST
  9461.     bleep( BP_WARN ) ;
  9462.     if ( !quiet ) {
  9463.     printf("\n NOTICE:\n");
  9464.     printf(
  9465. "   This software is pre-release and is to be used for testing\n");
  9466.         printf(
  9467. "   purposes only.  Pre-release versions of Kermit-95 are updated\n");
  9468.         printf(
  9469. "   on a very frequent basis (several times a week.)  If you find\n");
  9470.         printf(
  9471. "   a bug and more than a week has transpired since the date listed\n");
  9472.         printf(
  9473. "   above, please look for an updated version before reporting it.\n\n");
  9474.         printf(
  9475. "   UNDER NO CIRCUMSTANCES IS THIS PRE-RELEASE SOFTWARE TO BE\n");
  9476.         printf(
  9477. "   UPLOADED FOR DISTRIBUTION TO ANY SITE OTHER THAN:\n");
  9478.         printf(
  9479. "        ftp://ftp.kermit-project.org/\n\n");
  9480.     }
  9481. #endif /* BETATEST */
  9482.  
  9483.     downloaded = (dsn == 98);
  9484.  
  9485.     if ( !dsn || dsn < 100 ) {
  9486.         unsigned long now_t = time(NULL);
  9487.  
  9488. #ifdef COMMENT
  9489.         if ( downloaded ) {
  9490.             etime = regtime(NULL) + 60*60*24*21;
  9491.             memcpy(&expires,localtime(&etime),sizeof(struct tm));
  9492.             expday = expires.tm_mday;
  9493.             expmon = expires.tm_mon;
  9494.             expyear = expires.tm_year;
  9495.             expired = (now_t < regtime(NULL) ||
  9496.                         now_t > etime);
  9497.         }
  9498. #endif /* COMMENT */
  9499.  
  9500.         if (!quiet)
  9501.             printf(
  9502. "   This copy will expire on %d/%d/%d.\n\n",expmon+1,expday,1900+expyear);
  9503.         if ( !downloaded && ltime > etime ) {
  9504. #ifdef BETADEBUG
  9505.             if ( !quiet ) {
  9506.                 printf(
  9507. "   This Beta Test release copy has expired.\n");
  9508.                 printf(
  9509. "   Please retrieve a newer release from ftp://kermit.columbia.edu.\n\n");
  9510.             }
  9511. #else /* BETADEBUG */
  9512.             if ( dsn ) {
  9513.                 if ( !quiet ) {
  9514.                     printf(
  9515. "   This DEMO copy of Kermit has expired.\n");
  9516.                     printf(
  9517. "   Please contact Kermit Orders at kermit-orders@columbia.edu or read the\n");
  9518.                     printf(
  9519. "   Kermit 95 Web Page at http://www.columbia.edu/kermit/k95.html\n");
  9520.                     printf(
  9521. "   to continue use of program.\n");
  9522.                 }
  9523.             } else {
  9524.                 if ( !quiet )
  9525.                     printf( 
  9526. "   This copy of Kermit 95 must be registered to continue use.\n\n");
  9527.             }
  9528. #endif /* BETADEBUG */
  9529.             for ( i=0;i<3;i++ ) {
  9530.                 bleep(BP_FAIL);
  9531.                 sleep(2);
  9532.             }
  9533.             doexit(BAD_EXIT,-1);
  9534.         } else if ( downloaded ) {
  9535.             if ( !quiet ) {
  9536.                 printf(
  9537. "   This is a DEMO of version of Kermit 95 designed to allow you to\n");
  9538.                 printf(
  9539. "   experience the full feature set of the program.  This DEMO has a per\n");
  9540.                 printf(
  9541. "   session time limit of 15 minutes.  This provides enough time to test\n");
  9542.                 printf(
  9543. "   the capabilities of the program and ensure compatibility with your\n");
  9544.                 printf(
  9545. "   existing systems.  To purchase a full release of Kermit 95 please\n");
  9546.                 printf(
  9547. "   contact Kermit Orders at kermit-orders@columbia.edu or read the\n");
  9548.                 printf(
  9549. "   Kermit 95 Web Page at http://www.columbia.edu/kermit/k95.html\n");
  9550.                 printf("\n\n");
  9551.             }
  9552. #ifdef SESLIMIT
  9553.             seslimit = 60 * 15;
  9554. #endif /* SESLIMIT */
  9555.         }
  9556.     }
  9557.     colorcmd ^= 0x8 ;
  9558. #endif /* NOLOCAL */
  9559.     return(1);
  9560. }
  9561.  
  9562. int
  9563. shoreg( void )
  9564. {
  9565. #ifndef NOLOCAL
  9566.     int    dsn ;  /* decoded serial number */
  9567.     extern unsigned char colorcmd ;
  9568.  
  9569.     colorcmd ^= 0x8 ;
  9570.     dsn = isregistered(NULL) ;
  9571.     /* add K95-00001123108-1.1 to the list below. */
  9572.  
  9573.     if ( dsn == 91340 || dsn == 23567 || dsn == 12496 ) {
  9574.         if ( !quiet )
  9575.             printf(" THIS COPY OF KERMIT SOFTWARE HAS BEEN PIRATED.\n");
  9576.         for ( ;; ) {
  9577.             bleep( BP_WARN ) ;
  9578.             sleep(1);
  9579.         }
  9580.     }
  9581.     else if ( dsn == 99 || dsn == 98        /* Demo */
  9582.          || dsn >= 100 && dsn < 10000       /* Academic Site License */
  9583.          || dsn >= 10000 && dsn < 10000000  /* Retail Package */
  9584.          || dsn >= 10000000                 /* Commercial Site License */
  9585.          )
  9586.     {
  9587.         char * p;
  9588.         if ( !quiet ) {
  9589.             printf("Registered to:\n\n");
  9590.             p = get_reg_name();
  9591.             if ( *p )
  9592.                 printf("  %s\n",p);
  9593.             p = get_reg_corp();
  9594.             if ( *p )
  9595.                 printf("  %s\n",p);
  9596.             p = get_reg_sn();
  9597.             printf("\n  Serial number: %s\n",p);
  9598.  
  9599.             if ( dsn == 99 )
  9600.             {
  9601.                 /* Demo copy */
  9602.                 printf("\n  For evaluation purposes only.\n");
  9603.                 printf("\n  DO NOT DISTRIBUTE.\n");
  9604.             }
  9605.             else if ( dsn >= 100 && dsn < 10000 )
  9606.             {
  9607.                 /* Academic Site License */
  9608.                 printf("\n  For use only by current students, faculty, and staff\n") ;
  9609.                 printf("  of %s.\n", get_reg_name() ) ;
  9610.             }
  9611.             else if ( dsn >= 10000000 )
  9612.             {
  9613.                 /* Commercial Site License */
  9614.                 if ( get_reg_count() )
  9615.                     printf("  licensed for %d users\n", get_reg_count() ) ;
  9616.             }
  9617.             printf("\n");
  9618.         }
  9619.     } else {
  9620.         bleep( BP_WARN ) ;
  9621.         if ( !quiet ) {
  9622.             printf(" THIS COPY OF KERMIT SOFTWARE IS NOT REGISTERED.\n");
  9623.             printf(
  9624. " This software must be installed from the original diskettes using the SETUP\n");
  9625.             printf(
  9626. " procedure provided.  It may not be downloaded or redistributed without a\n");
  9627.             printf(
  9628. " license from Columbia University.  For further information send e-mail to\n");
  9629.             printf(
  9630. " kermit-orders@columbia.edu or call +1 (212) 854-3703.\n\n");
  9631.         }
  9632. #ifdef COMMENT
  9633.         doexit( BAD_EXIT, 0 ) ;
  9634. #else /* COMMENT */
  9635.         sleep(5) ;
  9636.         bleep( BP_WARN ) ;
  9637. #endif /* COMMENT */
  9638.     }
  9639.     colorcmd ^= 0x8 ;
  9640. #endif /* NOLOCAL */
  9641.     return 0;
  9642. }
  9643.  
  9644.  
  9645. long
  9646. getmsec( void ) {
  9647. #ifdef NT
  9648.     SYSTEMTIME LocalTime ;
  9649.  
  9650.     GetLocalTime(&LocalTime);
  9651.     return (LocalTime.wMilliseconds +
  9652.         1000 * (LocalTime.wSecond +
  9653.                  (60 * LocalTime.wMinute +
  9654.                    (60 * LocalTime.wHour +
  9655.                      (24 * LocalTime.wDay)))));
  9656. #else
  9657.     return 0;
  9658. #endif
  9659. }
  9660.  
  9661. #ifdef NT
  9662. void
  9663. DisplayCommProperties(HANDLE h)
  9664. {
  9665.     COMMPROP *     lpCommProp = NULL;
  9666.     LPMODEMDEVCAPS lpModemDevCaps = NULL;
  9667.     int rc=0;
  9668.  
  9669.     /* leave enough room for provider specific information */
  9670.     lpCommProp = (COMMPROP *) malloc( 1024 );
  9671.     if ( lpCommProp == NULL )
  9672.         return;
  9673.     memset( lpCommProp, 0, 1024 );
  9674.     lpCommProp->wPacketLength = 1024;
  9675.     lpCommProp->dwProvSpec1 = COMMPROP_INITIALIZED;
  9676.  
  9677.     rc = GetCommProperties( h, lpCommProp );
  9678.     if ( !rc ) {
  9679.         debug(F111,"GetCommProperties","GetLastError",GetLastError());
  9680.         free(lpCommProp);
  9681.         return ;
  9682.     }
  9683.  
  9684.     printf("GetCommProperties:\n");
  9685.     printf("  PacketLength       = %d (bytes)\n",lpCommProp->wPacketLength);
  9686.     printf("  PacketVersion      = %x\n",lpCommProp->wPacketVersion);
  9687.     printf("  Services Implemented:\n");
  9688.     if ( lpCommProp->dwServiceMask & SP_SERIALCOMM )
  9689.         printf("    Serial Communication\n");
  9690.     if ( lpCommProp->dwServiceMask & SP_PARITY )
  9691.         printf("    Parity\n");
  9692.     if ( lpCommProp->dwServiceMask & SP_BAUD )
  9693.         printf("    Baud\n");
  9694.     if ( lpCommProp->dwServiceMask & SP_DATABITS )
  9695.         printf("    DataBits\n");
  9696.     if ( lpCommProp->dwServiceMask & SP_STOPBITS )
  9697.         printf("    StopBits\n");
  9698.     if ( lpCommProp->dwServiceMask & SP_HANDSHAKING )
  9699.         printf("    Handshaking\n");
  9700.     if ( lpCommProp->dwServiceMask & SP_PARITY_CHECK )
  9701.         printf("    Parity Check\n");
  9702.     if ( lpCommProp->dwServiceMask & SP_RLSD )
  9703.         printf("    Carrier Detect\n");
  9704.     printf("  Max Tx Queue       = %d (bytes) [0 - unlimited]\n",lpCommProp->dwMaxTxQueue);
  9705.     printf("  Max Rx Queue       = %d (bytes) [0 - unlimited]\n",lpCommProp->dwMaxRxQueue);
  9706.     printf("  Max Baud Rate      = ");
  9707.     switch ( lpCommProp->dwMaxBaud ) {
  9708.     case BAUD_075:   printf("75 bps    \n"); break;
  9709.     case BAUD_110:   printf("110 bps   \n"); break;
  9710.     case BAUD_134_5: printf("134.5 bps \n"); break;
  9711.     case BAUD_150:   printf("150 bps   \n"); break;
  9712.     case BAUD_300:   printf("300 bps   \n"); break;
  9713.     case BAUD_600:   printf("600 bps   \n"); break;
  9714.     case BAUD_1200:  printf("1200 bps  \n"); break;
  9715.     case BAUD_1800:  printf("1800 bps  \n"); break;
  9716.     case BAUD_2400:  printf("2400 bps  \n"); break;
  9717.     case BAUD_4800:  printf("4800 bps  \n"); break;
  9718.     case BAUD_7200:  printf("7200 bps  \n"); break;
  9719.     case BAUD_9600:  printf("9600 bps  \n"); break;
  9720.     case BAUD_14400: printf("14400 bps \n"); break;
  9721.     case BAUD_19200: printf("19200 bps \n"); break;
  9722.     case BAUD_38400: printf("38400 bps \n"); break;
  9723.     case BAUD_56K:   printf("56K bps   \n"); break;
  9724.     case BAUD_57600: printf("57600 bps \n"); break;
  9725.     case BAUD_115200:printf("115200 bps\n"); break;
  9726.     case BAUD_128K:  printf("128K bps  \n"); break;
  9727.     case BAUD_USER:  printf("Programmable baud rates available\n"); break;
  9728.     default:         printf("(unknown)\n"); break;
  9729.     }
  9730.     printf("  Provider Sub Type  = ");
  9731.     switch ( lpCommProp->dwProvSubType ) {
  9732.     case PST_UNSPECIFIED     :
  9733.         printf("Unspecified");
  9734.         break;
  9735.     case PST_RS232           :
  9736.         printf("RS232");
  9737.         break;
  9738.     case PST_PARALLELPORT    :
  9739.         printf("Parallel Port");
  9740.         break;
  9741.     case PST_RS422           :
  9742.         printf("RS422");
  9743.         break;
  9744.     case PST_RS423           :
  9745.         printf("RS423");
  9746.         break;
  9747.     case PST_RS449           :
  9748.         printf("RS449");
  9749.         break;
  9750.     case PST_MODEM           :
  9751.         printf("Modem");
  9752.         break;
  9753.     case PST_FAX             :
  9754.         printf("Fax");
  9755.         break;
  9756.     case PST_SCANNER         :
  9757.         printf("Scanner");
  9758.     case PST_NETWORK_BRIDGE  :
  9759.         printf("Network Bridge");
  9760.         break;
  9761.     case PST_LAT             :
  9762.         printf("LAT");
  9763.         break;
  9764.     case PST_TCPIP_TELNET    :
  9765.         printf("TCP/IP Telnet");
  9766.         break;
  9767.     case PST_X25             :
  9768.         printf("X.25");
  9769.         break;
  9770.     default:
  9771.         printf("Unknown");
  9772.     }
  9773.     printf("\n");
  9774.     printf("  Provider Capabilities:\n");
  9775.     if ( lpCommProp->dwProvCapabilities & PCF_16BITMODE )
  9776.         printf("    Special 16 Bit Mode supported\n");
  9777.     if ( lpCommProp->dwProvCapabilities & PCF_DTRDSR )
  9778.         printf("    DTR (data-terminal-ready)/DSR (data-set-ready) supported\n");
  9779.     if ( lpCommProp->dwProvCapabilities & PCF_INTTIMEOUTS )
  9780.         printf("    Interval time-outs supported\n");
  9781.     if ( lpCommProp->dwProvCapabilities & PCF_PARITY_CHECK )
  9782.         printf("    Parity checking supported\n");
  9783.     if ( lpCommProp->dwProvCapabilities & PCF_RLSD )
  9784.         printf("    RLSD (receive-line-signal-detect) supported\n");
  9785.     if ( lpCommProp->dwProvCapabilities & PCF_RTSCTS )
  9786.         printf("    RTS (request-to-send)/CTS (clear-to-send) supported\n");
  9787.     if ( lpCommProp->dwProvCapabilities & PCF_SETXCHAR )
  9788.         printf("    Settable XON/XOFF supported\n");
  9789.     if ( lpCommProp->dwProvCapabilities & PCF_SPECIALCHARS )
  9790.         printf("    Special character support provided\n");
  9791.     if ( lpCommProp->dwProvCapabilities & PCF_TOTALTIMEOUTS )
  9792.         printf("    Total (elapsed) time-outs supported\n");
  9793.     if ( lpCommProp->dwProvCapabilities & PCF_XONXOFF )
  9794.         printf("    XON/XOFF flow control supported\n");
  9795.     printf("  Settable Parameters:\n");
  9796.     if ( lpCommProp->dwSettableParams & SP_BAUD )
  9797.         printf("    Baud Rate\n");
  9798.     if ( lpCommProp->dwSettableParams & SP_DATABITS )
  9799.         printf("    DataBits\n");
  9800.     if ( lpCommProp->dwSettableParams & SP_HANDSHAKING )
  9801.         printf("    Handshaking (flow control)\n");
  9802.     if ( lpCommProp->dwSettableParams & SP_PARITY )
  9803.         printf("    Parity\n");
  9804.     if ( lpCommProp->dwSettableParams & SP_PARITY_CHECK )
  9805.         printf("    Parity checking\n");
  9806.     if ( lpCommProp->dwSettableParams & SP_RLSD )
  9807.         printf("    RLSD (receive-line-signal-detect)\n");
  9808.     if ( lpCommProp->dwSettableParams & SP_STOPBITS )
  9809.         printf("    StopBits\n");
  9810. #ifdef COMMENT
  9811.     DWORD dwSettableBaud;      // allowable baud rates
  9812.     WORD  wSettableData;       // allowable byte sizes
  9813.     WORD  wSettableStopParity; // stop bits/parity allowed
  9814. #endif
  9815.     printf("  Current Tx Queue   = %d (bytes)\n",lpCommProp->dwCurrentTxQueue);
  9816.     printf("  Current Rx Queue   = %d (bytes)\n",lpCommProp->dwCurrentRxQueue);
  9817.  
  9818.     if ( lpCommProp->dwProvSubType == PST_MODEM && lpCommProp->wcProvChar[0]) {
  9819.         lpModemDevCaps = (LPMODEMDEVCAPS) lpCommProp->wcProvChar;
  9820.         printf("Modem Device Capabilities:\n");
  9821.         printf("  Modem Provider Version = %x\n",lpModemDevCaps->dwModemProviderVersion);
  9822.         if ( isWin95() ) {
  9823.         printf("  Modem Manufacturer     = %s\n",
  9824.                 lpModemDevCaps->dwModemManufacturerOffset ?
  9825.                 (LPCSTR) lpModemDevCaps + lpModemDevCaps->dwModemManufacturerOffset :
  9826.                 "(not specified)");
  9827.         printf("  Modem Model            = %s\n",
  9828.                 lpModemDevCaps->dwModemModelOffset ?
  9829.                 (LPCSTR) lpModemDevCaps + lpModemDevCaps->dwModemModelOffset :
  9830.                 "(not specified)");
  9831.         printf("  Modem Version          = %s\n",
  9832.                 lpModemDevCaps->dwModemVersionOffset ?
  9833.                 (LPCSTR) lpModemDevCaps + lpModemDevCaps->dwModemVersionOffset :
  9834.                 "(not specified)");
  9835.         }
  9836.         else {
  9837.             char strbuf[256];
  9838.             WORD * word;
  9839.             int    i,len;
  9840.             if ( lpModemDevCaps->dwModemManufacturerOffset ) {
  9841.                 len = lpModemDevCaps->dwModemManufacturerSize;
  9842.                 word = (WORD *)((LPCSTR) lpModemDevCaps +
  9843.                                  lpModemDevCaps->dwModemManufacturerOffset);
  9844.                 for ( i=0 ; i < len ; i++ )
  9845.                     strbuf[i] = (char) word[i];
  9846.                 strbuf[i] = '\0';
  9847.                 printf("  Modem Manufacturer     = %s\n",strbuf);
  9848.             }
  9849.             else
  9850.                 printf("  Modem Manufacturer     = (not specified)\n");
  9851.  
  9852.             if ( lpModemDevCaps->dwModemModelOffset ) {
  9853.                 len = lpModemDevCaps->dwModemModelSize;
  9854.                 word = (WORD *)((LPCSTR) lpModemDevCaps +
  9855.                                  lpModemDevCaps->dwModemModelOffset);
  9856.                 for ( i=0 ; i < len ; i++ )
  9857.                     strbuf[i] = (char) word[i];
  9858.                 strbuf[i] = '\0';
  9859.                 printf("  Modem Model            = %s\n",strbuf);
  9860.             }
  9861.             else
  9862.                 printf("  Modem Model            = (not specified)\n");
  9863.  
  9864.             if ( lpModemDevCaps->dwModemVersionOffset ) {
  9865.                 len = lpModemDevCaps->dwModemVersionSize;
  9866.                 word = (WORD *)((LPCSTR) lpModemDevCaps +
  9867.                                  lpModemDevCaps->dwModemVersionOffset);
  9868.                 for ( i=0 ; i < len ; i++ )
  9869.                     strbuf[i] = (char) word[i];
  9870.                 strbuf[i] = '\0';
  9871.                 printf("  Modem Version          = %s\n",strbuf);
  9872.             }
  9873.             else
  9874.                 printf("  Modem Version          = (not specified)\n");
  9875.         }
  9876.         printf("  Dial Options:\n");
  9877.         if ( lpModemDevCaps->dwDialOptions & DIALOPTION_BILLING )
  9878.             printf("    Specifies that the modem supports waiting for billing tone (bong).\n");
  9879.         if ( lpModemDevCaps->dwDialOptions & DIALOPTION_QUIET )
  9880.             printf("    Specifies that the modem supports waiting for quiet.\n");
  9881.         if ( lpModemDevCaps->dwDialOptions & DIALOPTION_DIALTONE )
  9882.             printf("    Specifies that the modem supports waiting for a dial tone.\n");
  9883.         printf("  Max CallSetupFailTimer = %d (seconds)\n",
  9884.                 lpModemDevCaps->dwCallSetupFailTimer);
  9885.         printf("  Max Inactivity Timeout = %d (1/10 seconds)\n",
  9886.                 lpModemDevCaps->dwInactivityTimeout);
  9887.         printf("  Speaker Volumes:\n");
  9888.         if ( lpModemDevCaps->dwSpeakerVolume & MDMVOLFLAG_LOW )
  9889.             printf("    Low\n");
  9890.         if ( lpModemDevCaps->dwSpeakerVolume & MDMVOLFLAG_MEDIUM )
  9891.             printf("    Medium\n");
  9892.         if ( lpModemDevCaps->dwSpeakerVolume & MDMVOLFLAG_HIGH )
  9893.             printf("    High\n");
  9894.         printf("  Speaker Modes:\n");
  9895.         if ( lpModemDevCaps->dwSpeakerVolume & MDMSPKRFLAG_OFF )
  9896.             printf("    Off\n");
  9897.         if ( lpModemDevCaps->dwSpeakerVolume & MDMSPKRFLAG_DIAL )
  9898.             printf("    Dial\n");
  9899.         if ( lpModemDevCaps->dwSpeakerVolume & MDMSPKRFLAG_ON )
  9900.             printf("    On\n");
  9901.         if ( lpModemDevCaps->dwSpeakerVolume & MDMSPKRFLAG_CALLSETUP )
  9902.             printf("    Call Setup\n");
  9903.         printf("  Modem Options:\n");
  9904.         if ( lpModemDevCaps->dwModemOptions & MDM_BLIND_DIAL )
  9905.             printf("    Blind Dial\n");
  9906.         if ( lpModemDevCaps->dwModemOptions & MDM_FLOWCONTROL_SOFT )
  9907.             printf("    Software Flow Control\n");
  9908.         if ( lpModemDevCaps->dwModemOptions & MDM_CCITT_OVERRIDE )
  9909.             printf("    CCITT modulation override\n");
  9910.         if ( lpModemDevCaps->dwModemOptions & MDM_FORCED_EC )
  9911.             printf("    Forced Error Correction\n");
  9912.         if ( lpModemDevCaps->dwModemOptions & MDM_CELLULAR )
  9913.             printf("    Cellular\n");
  9914.         if ( lpModemDevCaps->dwModemOptions & MDM_SPEED_ADJUST )
  9915.             printf("    Speed Adjustment\n");
  9916.         if ( lpModemDevCaps->dwModemOptions & MDM_COMPRESSION )
  9917.             printf("    Compression\n");
  9918.         if ( lpModemDevCaps->dwModemOptions & MDM_TONE_DIAL )
  9919.             printf("    Tone Dial\n");
  9920.         if ( lpModemDevCaps->dwModemOptions & MDM_ERROR_CONTROL )
  9921.             printf("    Error Control\n");
  9922.         if ( lpModemDevCaps->dwModemOptions & MDM_V23_OVERRIDE )
  9923.             printf("    V.23 override\n");
  9924.         if ( lpModemDevCaps->dwModemOptions & MDM_FLOWCONTROL_HARD )
  9925.             printf("    Hardware flow control\n");
  9926.         printf("  Max DTE Rate           = %d (bits/second)\n",
  9927.                 lpModemDevCaps->dwMaxDTERate);
  9928.         printf("  Max DCE Rate           = %d (bits/second)\n",
  9929.                 lpModemDevCaps->dwMaxDCERate);
  9930.     }
  9931.     printf("\n");
  9932.     free(lpCommProp);
  9933.     return;
  9934. }
  9935. #endif /* NT */
  9936.  
  9937. #ifdef BPRINT
  9938. extern int  printbidi;                  /* SET BPRINTER (bidirectional) */
  9939. extern long pportspeed;                 /* Bidirection printer port speed, */
  9940. extern int  pportparity;                /*  parity, */
  9941. extern int  pportflow;                  /*  and flow control */
  9942. extern char *printername;
  9943. #ifdef NT
  9944. TID         tidBPrint=NULL;
  9945. #else
  9946. TID         tidBPrint=0;
  9947. #endif /* NT */
  9948.  
  9949. #ifdef NT
  9950. HANDLE hBPrinter = NULL;
  9951. #else /* NT */
  9952. HFILE  hBPrinter = 0;
  9953. #endif /* NT */
  9954.  
  9955. #ifdef NT
  9956. int
  9957. prtcfg(HANDLE hPrt) {
  9958.     DCB dcbBPrint;
  9959.     COMMTIMEOUTS timeouts ;
  9960.  
  9961.     if ( pportflow == FLO_KEEP && !pportspeed && !pportparity )
  9962.         return(TRUE);
  9963.  
  9964.     SetCommMask( (HANDLE) hPrt, EV_RXCHAR ) ;
  9965.     SetupComm( (HANDLE) hPrt, 20000, 20000 ) ;
  9966.     PurgeComm( (HANDLE) hPrt,
  9967.                PURGE_RXABORT | PURGE_TXABORT | PURGE_RXCLEAR | PURGE_TXCLEAR ) ;
  9968.  
  9969.     dcbBPrint.DCBlength = sizeof(DCB);
  9970.     if (!GetCommState( (HANDLE) hPrt, &dcbBPrint )) {
  9971.         return FALSE ;
  9972.     }
  9973.  
  9974.     if (!GetCommTimeouts(hPrt, &timeouts)) {
  9975.         return FALSE ;
  9976.     }
  9977.  
  9978.     if ( deblog )
  9979.         debugComm( "prtcfg initial values", &dcbBPrint, &timeouts );
  9980.  
  9981.     dcbBPrint.fBinary = TRUE ;
  9982.     dcbBPrint.fErrorChar = FALSE ;
  9983.     dcbBPrint.fAbortOnError = FALSE ;
  9984.     dcbBPrint.ErrorChar = '?' ;
  9985.     dcbBPrint.fParity = TRUE ;
  9986.     dcbBPrint.StopBits = ONESTOPBIT ;
  9987.     dcbBPrint.BaudRate = pportspeed;
  9988.     dcbBPrint.fDsrSensitivity = FALSE ;
  9989.     dcbBPrint.fDtrControl = DTR_CONTROL_ENABLE ;
  9990.  
  9991.     switch (pportparity) {
  9992.         case 'o':
  9993.             dcbBPrint.ByteSize = 7;     /* Data bits */
  9994.             dcbBPrint.Parity   = 1;
  9995.             break;
  9996.         case 'e':
  9997.             dcbBPrint.ByteSize = 7;     /* Data bits */
  9998.             dcbBPrint.Parity   = 2;
  9999.             break;
  10000.         case 'm':
  10001.             dcbBPrint.ByteSize = 7;     /* Data bits */
  10002.             dcbBPrint.Parity   = 3;
  10003.             break;
  10004.         case 's':
  10005.             dcbBPrint.ByteSize = 7;     /* Data bits */
  10006.             dcbBPrint.Parity   = 4;
  10007.             break;
  10008.         default :
  10009.             dcbBPrint.ByteSize = 8;     /* Data bits */
  10010.             dcbBPrint.Parity   = 0;     /* No parity */
  10011.     }
  10012.     switch(pportflow) {
  10013.     case FLO_XONX:
  10014.         dcbBPrint.fOutX = TRUE ;
  10015.         dcbBPrint.fInX = TRUE ;
  10016.         dcbBPrint.fRtsControl = RTS_CONTROL_ENABLE ;
  10017.         dcbBPrint.fOutxCtsFlow = FALSE ;
  10018.         dcbBPrint.fTXContinueOnXoff = /* TRUE */ FALSE ;
  10019.         break;
  10020.     case FLO_RTSC:
  10021.         dcbBPrint.fOutX = FALSE ;
  10022.         dcbBPrint.fInX = FALSE ;
  10023.         dcbBPrint.fRtsControl = RTS_CONTROL_HANDSHAKE ;
  10024.         dcbBPrint.fOutxCtsFlow = TRUE ;
  10025.         dcbBPrint.fTXContinueOnXoff = TRUE ;
  10026.         break;
  10027.     case FLO_KEEP:
  10028.         /* leave things exactly as they are */
  10029.         break;
  10030.     case FLO_NONE:
  10031.         /* turn off all flow control completely */
  10032.         dcbBPrint.fOutX = FALSE ;
  10033.         dcbBPrint.fInX = FALSE ;
  10034.         dcbBPrint.fRtsControl = RTS_CONTROL_ENABLE ;
  10035.         dcbBPrint.fOutxCtsFlow = FALSE ;
  10036.         dcbBPrint.fTXContinueOnXoff = TRUE ;
  10037.         break;
  10038.     }
  10039.  
  10040.     dcbBPrint.XonChar = 0x11 ;
  10041.     dcbBPrint.XoffChar = 0x13;
  10042.     dcbBPrint.XonLim = 10 ;
  10043.     dcbBPrint.XoffLim = 10 ;
  10044.  
  10045.     if (!SetCommState( hPrt, &dcbBPrint )) {
  10046.         return FALSE ;
  10047.     }
  10048.  
  10049.     /* Timeouts for Overlapped I/O from MS TTY.C example */
  10050.     timeouts.ReadIntervalTimeout = MAXDWORD ;
  10051.     timeouts.ReadTotalTimeoutMultiplier = MAXDWORD ;
  10052.     timeouts.ReadTotalTimeoutConstant = 10 ;
  10053.     timeouts.WriteTotalTimeoutMultiplier = 1000 ;
  10054.     timeouts.WriteTotalTimeoutConstant   = 1000 ;
  10055.  
  10056.     if (!SetCommTimeouts( hPrt, &timeouts )) {
  10057.         return FALSE ;
  10058.     }
  10059.     return(TRUE);
  10060. }
  10061. #endif /* NT */
  10062.  
  10063. int
  10064. bprtstart( void )
  10065. {
  10066. #ifdef NT
  10067.     SECURITY_ATTRIBUTES security ;
  10068.  
  10069.     if ( hBPrinter )
  10070.         return TRUE;
  10071.  
  10072.     memset(&security, 0, sizeof(SECURITY_ATTRIBUTES));
  10073.     security.nLength = sizeof(SECURITY_ATTRIBUTES);
  10074.     security.lpSecurityDescriptor = NULL ;
  10075.     security.bInheritHandle = FALSE ;
  10076.  
  10077.     if ((hBPrinter = CreateFile( printername ? printername : "PRN",
  10078.                             GENERIC_READ | GENERIC_WRITE,
  10079.                             FALSE, /* TRUE, /* do not share */
  10080.                             &security,
  10081.                             OPEN_EXISTING,
  10082.                             FILE_ATTRIBUTE_NORMAL,
  10083.                             NULL)) == INVALID_HANDLE_VALUE) {
  10084.         hBPrinter = NULL;
  10085.         return FALSE;
  10086.     }
  10087.  
  10088.     if ( !prtcfg(hBPrinter) ) {
  10089.         CloseHandle( hBPrinter );
  10090.         hBPrinter = NULL;
  10091.         return FALSE;
  10092.     }
  10093.  
  10094.     /* The Port should now be configured, so lets start the thread */
  10095.     tidBPrint = (TID) ckThreadBegin( &bprtthread,THRDSTKSIZ,0,FALSE,0);
  10096.     if ( !tidBPrint )
  10097.     {
  10098.         CloseHandle( hBPrinter );
  10099.         hBPrinter = NULL;
  10100.         return FALSE ;
  10101.     }
  10102.     return TRUE;
  10103. #else /* NT */
  10104.     DCBINFO dcbBPrint;
  10105.     LINECONTROL lc;
  10106.     UINT parm = 0, data = 0;
  10107.     ULONG action = 0;
  10108.     struct {
  10109.       long rate;
  10110.       char fract;
  10111.     } speed;
  10112.     ULONG   error;
  10113.  
  10114.     if (error = DosOpen(printername ? printername : "PRN",
  10115.                         (PHFILE)&hBPrinter,&action,0L,0,FILE_OPEN,
  10116.         OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYREADWRITE | OPEN_FLAGS_FAIL_ON_ERROR,
  10117.                        0L)) {
  10118.         hBPrinter = 0;
  10119.         return FALSE;
  10120.     }
  10121.  
  10122.     DosDevIOCtl(&data,sizeof(data),&parm,sizeof(parm),
  10123.                 DEV_FLUSHINPUT,IOCTL_GENERAL,hBPrinter); /* Flush driver */
  10124.  
  10125.     /* Get the current settings */
  10126.     if (DosDevIOCtl(&dcbBPrint,sizeof(dcbBPrint),NULL,0,
  10127.                      ASYNC_GETDCBINFO,IOCTL_ASYNC,hBPrinter))
  10128.     {
  10129.         DosClose(hBPrinter);
  10130.         hBPrinter = 0;
  10131.         return FALSE;
  10132.     }
  10133.  
  10134.     dcbBPrint.fbCtlHndShake = MODE_DTR_CONTROL;
  10135.     dcbBPrint.fbFlowReplace &= ~(MODE_AUTO_RECEIVE | MODE_AUTO_TRANSMIT |
  10136.     /* clear only a few */    MODE_RTS_CONTROL  | MODE_RTS_HANDSHAKE);
  10137.  
  10138.     if (pportflow == FLO_XONX) {
  10139.         dcbBPrint.fbFlowReplace |=
  10140.             (MODE_AUTO_RECEIVE | MODE_AUTO_TRANSMIT | MODE_RTS_CONTROL);
  10141.     }
  10142.     else if (pportflow == FLO_RTSC) {
  10143.         dcbBPrint.fbCtlHndShake |= MODE_CTS_HANDSHAKE;
  10144.         dcbBPrint.fbFlowReplace |= MODE_RTS_HANDSHAKE;
  10145.     }
  10146.     else if ( pportflow != FLO_KEEP ) {
  10147.         dcbBPrint.fbFlowReplace |= MODE_RTS_CONTROL;
  10148.     }
  10149.  
  10150.     /* set write timeout */
  10151.     dcbBPrint.fbTimeout &= ~MODE_NO_WRITE_TIMEOUT;
  10152.     dcbBPrint.usWriteTimeout = 15 * 100;        /* 15-second timeout */
  10153.  
  10154.     /* Read "some" data from line mode */
  10155.     dcbBPrint.fbTimeout &= ~MODE_NOWAIT_READ_TIMEOUT;
  10156.     dcbBPrint.fbTimeout |= MODE_WAIT_READ_TIMEOUT;
  10157.  
  10158.     /* Timeouts */
  10159.     dcbBPrint.usReadTimeout = 9;        /* Test every  0.1s per call */
  10160.  
  10161.     /* Set DCB */
  10162.     if (DosDevIOCtl(NULL,0,&dcbBPrint,sizeof(dcbBPrint),
  10163.                      ASYNC_SETDCBINFO,IOCTL_ASYNC,hBPrinter))
  10164.     {
  10165.         DosClose(hBPrinter);
  10166.         hBPrinter = 0;
  10167.         return FALSE;
  10168.     }
  10169.  
  10170.     if (pportflow != FLO_RTSC && pportflow != FLO_KEEP) {/* keep RTS permanently on */
  10171.         MODEMSTATUS ms;
  10172.         UINT data;
  10173.         ms.fbModemOn = RTS_ON;
  10174.         ms.fbModemOff = 255;
  10175.         DosDevIOCtl(&data,sizeof(data),&ms,sizeof(ms),
  10176.                     ASYNC_SETMODEMCTRL,IOCTL_ASYNC,hBPrinter);
  10177.     }
  10178.  
  10179.     if (DosDevIOCtl(&lc,sizeof(lc),NULL,0,
  10180.                     ASYNC_GETLINECTRL,IOCTL_ASYNC,hBPrinter))
  10181.     {
  10182.         DosClose(hBPrinter);
  10183.         hBPrinter = 0;
  10184.         return FALSE;
  10185.     }
  10186.  
  10187.     switch (pportparity) {
  10188.         case 'o':
  10189.             lc.bDataBits = 7;   /* Data bits */
  10190.             lc.bParity   = 1;
  10191.             break;
  10192.         case 'e':
  10193.             lc.bDataBits = 7;   /* Data bits */
  10194.             lc.bParity   = 2;
  10195.             break;
  10196.         case 'm':
  10197.             lc.bDataBits = 7;   /* Data bits */
  10198.             lc.bParity   = 3;
  10199.             break;
  10200.         case 's':
  10201.             lc.bDataBits = 7;   /* Data bits */
  10202.             lc.bParity   = 4;
  10203.             break;
  10204.         default :
  10205.             lc.bDataBits = 8;   /* Data bits */
  10206.             lc.bParity   = 0;   /* No parity */
  10207.     }
  10208.     switch (1) {
  10209.         case 2:
  10210.             lc.bStopBits = 2;   /* Two stop bits */
  10211.             break;
  10212.         case 1:
  10213.             lc.bStopBits = 0;   /* One stop bit */
  10214.             break;
  10215.         default:                /* No change */
  10216.             break;
  10217.     }
  10218.     if (DosDevIOCtl(NULL,0,&lc,sizeof(lc),
  10219.                     ASYNC_SETLINECTRL,IOCTL_ASYNC,hBPrinter))
  10220.     {
  10221.         DosClose(hBPrinter);
  10222.         hBPrinter = 0;
  10223.         return FALSE;
  10224.     }
  10225.  
  10226.     if (pportspeed > 65535L) {
  10227.       speed.rate = pportspeed;
  10228.       speed.fract = 0;
  10229.       if (DosDevIOCtl(NULL,0,&speed,sizeof(speed),0x0043,IOCTL_ASYNC,hBPrinter))
  10230.       {
  10231.           DosClose(hBPrinter);
  10232.           hBPrinter = 0;
  10233.           return FALSE;
  10234.       }
  10235.  
  10236.     } else if (DosDevIOCtl(NULL,0,&pportspeed,sizeof(pportspeed),
  10237.                          ASYNC_SETBAUDRATE,IOCTL_ASYNC,hBPrinter))
  10238.     {
  10239.         DosClose(hBPrinter);
  10240.         hBPrinter = 0;
  10241.         return FALSE;
  10242.     }
  10243.  
  10244.     /* Still must start the thread */
  10245.     tidBPrint = (TID) ckThreadBegin( &bprtthread,THRDSTKSIZ,0,FALSE,0);
  10246.     if ( !tidBPrint )
  10247.     {
  10248.         DosClose( hBPrinter );
  10249.         hBPrinter = 0;
  10250.         return FALSE ;
  10251.     }
  10252.  
  10253.     return TRUE;
  10254. #endif /* NT */
  10255. }
  10256.  
  10257. int
  10258. bprtstop( void )
  10259. {
  10260. #ifdef NT
  10261.     if ( hBPrinter == NULL )
  10262.         return TRUE;
  10263.  
  10264.     CloseHandle( hBPrinter );
  10265.     hBPrinter = NULL;
  10266.     msleep( 500 );
  10267.     CloseHandle( tidBPrint );
  10268.     tidBPrint = NULL;
  10269.     return TRUE;
  10270. #else /* NT */
  10271.     if ( !hBPrinter )
  10272.         return TRUE;
  10273.  
  10274.     DosClose(hBPrinter);
  10275.     hBPrinter = 0;
  10276.     DosClose(tidBPrint);
  10277.     tidBPrint = 0;
  10278.     msleep(500);
  10279.     return TRUE;
  10280. #endif /* NT */
  10281. }
  10282.  
  10283. void
  10284. bprtthread( void * dummy )
  10285. {
  10286.     CHAR  buf[64];
  10287. #ifdef NT
  10288.     DWORD read;
  10289. #else
  10290.     ULONG read;
  10291.     ULONG Nesting;
  10292. #endif
  10293.  
  10294. #ifdef NT
  10295.     while ( hBPrinter ) {
  10296. #ifdef COMMENT
  10297.         if ( WaitForSingleObject( hBPrinter, -1L ) != WAIT_OBJECT_0 ) {
  10298.             debug(F111,"BPrinter WaitForSingleObject",
  10299.                    "GetLastError",GetLastError());
  10300.             continue;
  10301.         }
  10302. #endif
  10303.  
  10304.         if ( ReadFile( hBPrinter, buf, 64, &read, NULL ) )
  10305.         {
  10306.             if ( read ) {
  10307.                 buf[read] = '\0';
  10308.                 debug(F111,"BPrinter Read",buf,read);
  10309.                 ttxout( buf, read );
  10310.             }
  10311.             else
  10312.                 msleep(100);
  10313.         }
  10314.         else {
  10315.             DWORD error = GetLastError();
  10316.             debug(F111,"BPrinter ReadFile","GetLastError",error);
  10317.             switch ( error ) {
  10318.             default:
  10319.                 break;
  10320.             }
  10321.             msleep(100);
  10322.         }
  10323.     }
  10324. #else /* NT */
  10325.     while ( hBPrinter ) {
  10326.         ULONG error;
  10327.         DosEnterMustComplete( &Nesting ) ;
  10328.         if ( !(error =DosRead(hBPrinter,buf,64,&read)) )
  10329.         {
  10330.             DosExitMustComplete( &Nesting );
  10331.             if ( read ) {
  10332.                 buf[read] = '\0';
  10333.                 debug(F111,"BPrinter Read",buf,read);
  10334.                 sendchars( buf, read );
  10335.             }
  10336.             else
  10337.                 msleep(100);
  10338.         }
  10339.         else {
  10340.             DosExitMustComplete( &Nesting );
  10341.             debug(F111,"BPrinter DosRead","Error",error);
  10342.             switch ( error ) {
  10343.             default:
  10344.                 break;
  10345.             }
  10346.             msleep(100);
  10347.         }
  10348.     }
  10349. #endif /* NT */
  10350. }
  10351.  
  10352. int
  10353. bprtwrite( char * s, int len )
  10354. {
  10355. #ifdef NT
  10356.     DWORD written=0;
  10357.     debug(F111,"BPrinter Write", s,len);
  10358.     if (!WriteFile( hBPrinter, s, len, &written, NULL )) {
  10359.         debug(F111,"BPrinter WriteFile",
  10360.                "GetLastError",GetLastError());
  10361.         return -1;
  10362.     }
  10363.     else {
  10364.         return written;
  10365.     }
  10366. #else /* NT */
  10367.     UINT written;
  10368.     if(DosWrite(hBPrinter,s,len,(PVOID)&written))
  10369.         return -1 ;
  10370.     else
  10371.         return written ;
  10372. #endif /* NT */
  10373. }
  10374. #endif /* BPRINT */
  10375.  
  10376. struct tm *
  10377. #ifdef CK_ANSIC
  10378. cmdate2tm(char * date, int gmt)         /* date as "yyyymmdd hh:mm:ss" */
  10379. #else
  10380. cmdate2tm(date,gmt) char * date; int gmt;
  10381. #endif
  10382. {
  10383.     /* date as "yyyymmdd hh:mm:ss" */
  10384.     static struct tm _tm;
  10385.     time_t now;
  10386.  
  10387.     if ( strlen(date) != 17 ||
  10388.          date[8] != ' ' ||
  10389.          date[11] != ':' ||
  10390.          date[14] != ':')
  10391.         return(NULL);
  10392.  
  10393.     time(&now);
  10394.     if ( gmt )
  10395.         _tm = *gmtime(&now);
  10396.     else
  10397.         _tm = *localtime(&now);
  10398.     _tm.tm_year = (date[0]-'0')*1000 + (date[1]-'0')*100 +
  10399.                    (date[2]-'0')*10   + (date[3]-'0')-1900;
  10400.     _tm.tm_mon  = (date[4]-'0')*10   + (date[5]-'0')-1;
  10401.     _tm.tm_mday = (date[6]-'0')*10   + (date[7]-'0');
  10402.     _tm.tm_hour = (date[9]-'0')*10   + (date[10]-'0');
  10403.     _tm.tm_min  = (date[12]-'0')*10  + (date[13]-'0');
  10404.     _tm.tm_sec  = (date[15]-'0')*10  + (date[16]-'0');
  10405.  
  10406.     _tm.tm_wday = 0;
  10407.     _tm.tm_yday = 0;
  10408.  
  10409.     return(&_tm);
  10410. }
  10411.  
  10412. /*---------------------------------------------------------------------------*/
  10413. /* IsWARPed()                                                                */
  10414. /* In OS/2 terms, this means we have support for flexible column widths      */
  10415. /*---------------------------------------------------------------------------*/
  10416. bool
  10417. IsWARPed( void ) {
  10418. #ifdef NT
  10419.     return TRUE ;
  10420. #else
  10421.     ULONG StartIndex = QSV_VERSION_MAJOR ; /* Major Version Number */
  10422.     ULONG EndIndex   = QSV_VERSION_REVISION ; /* Revision Letter      */
  10423.     ULONG DataBuf[3] ;
  10424.     ULONG DataBufLen = 3 * sizeof(ULONG) ;
  10425.     APIRET rc ;
  10426.  
  10427.     DataBuf[0] = DataBuf[1] = DataBuf[2] = 0 ;
  10428.  
  10429.     rc = DosQuerySysInfo( StartIndex,
  10430.                           EndIndex,
  10431.                           DataBuf,
  10432.                           DataBufLen );
  10433.  
  10434.     return ( DataBuf[0] > 20 ||
  10435.              DataBuf[0] == 20 && DataBuf[1] >= 30 ) ;
  10436. #endif /* NT */
  10437. }
  10438.  
  10439.  
  10440.  
  10441. #ifdef COMMENT
  10442. WINBASEAPI DWORD WINAPI SetConsoleDisplayMode(HANDLE, DWORD, LPDWORD);
  10443. WINBASEAPI BOOL WINAPI  GetConsoleDisplayMode(LPDWORD);
  10444.  
  10445. are not declared in any header, they are in KERNEL32.LIB.  So, after
  10446. declaring them (as above, for example) you can link with them.  Use:
  10447.  
  10448.         SetConsoleDisplayMode(GetStdHandle(STD_OUTPUT_HANDLE), 1, &Result);
  10449. or
  10450.         SetConsoleDisplayMode(GetStdHandle(STD_OUTPUT_HANDLE), 0, &Result);
  10451.  
  10452. to go to fullscreen or windowed (respectively).  I don't recall what
  10453. "Result" holds when you're done, the curent status (post-execution) I think;
  10454. a DejaNews search for the function name ought to turn up that info.
  10455.  
  10456.  - Vince
  10457. #endif /* Undocumented Windows functions */
  10458.