blob: e2c89c657677e7f99f84a0bf1fb58bb2f43a3a62 [file] [log] [blame]
#include "ckcsym.h"
/* C K U U S X -- "User Interface" common functions. */
/*
Authors:
Frank da Cruz <fdc@columbia.edu>,
The Kermit Project, Columbia University, New York City
Jeffrey E Altman <jaltman@secure-endpoints.com>
Secure Endpoints Inc., New York City
Copyright (C) 1985, 2004,
Trustees of Columbia University in the City of New York.
All rights reserved. See the C-Kermit COPYING.TXT file or the
copyright text in the ckcmai.c module for disclaimer and permissions.
*/
/*
This module contains user interface functions needed by both the interactive
user interface and the command-line-only user interface.
*/
/* Includes */
#include "ckcdeb.h"
#include "ckcasc.h"
#include "ckcker.h"
#include "ckuusr.h"
#include "ckcxla.h"
#ifndef NOHTERMCAP
#ifdef NOTERMCAP
#define NOHTERMCAP
#else
#ifndef BSD44
#define NOHTERMCAP
#else
#ifdef __bsdi__
#define NOHTERMCAP
#else
#ifdef OPENBSD
#define NOHTERMCAP
#else
#ifdef MACOSX
#define NOHTERMCAP
#endif /* MACOSX */
#endif /* OPENBSD */
#endif /* __bsdi__ */
#endif /* BSD44 */
#endif /* NOTERMCAP */
#endif /* NOHTERMCAP */
#ifndef NOTERMCAP
#ifdef BSD44
#ifndef NOHTERMCAP
#include <termcap.h>
#endif /* NOHTERMCAP */
#endif /* BSD44 */
#else /* !BSD44 */
#ifdef linux
#include <term.h>
#endif /* linux */
#endif /* NOTERMCAP */
#ifdef OS2
#include <string.h>
_PROTOTYP(char * os2_gethostname, (void));
#define getpid _getpid
#endif /* OS2 */
#ifdef BSD44
#include <errno.h>
#endif /* BSD44 */
extern xx_strp xxstring;
#ifdef OS2
#include "ckcnet.h"
#else /* OS2 */
_PROTOTYP(int getlocalipaddr, (void));
_PROTOTYP(int istncomport, (void));
#ifndef NOCKGETFQHOST
_PROTOTYP( char * ckgetfqhostname,(char *));
#endif /* NOCKGETFQHOST */
#ifndef NETCONN
/*
We should just pull in ckcnet.h here, but it causes a conflict with curses.h.
*/
#ifdef TCPSOCKET
#define NETCONN
#else
#ifdef SUNX25
#define NETCONN
#else
#ifdef STRATUSX25
#define NETCONN
#else
#ifdef IBMX25
#define NETCONN
#else
#ifdef HPX25
#define NETCONN
#else
#ifdef DECNET
#define NETCONN
#else
#ifdef NPIPE
#define NETCONN
#else
#ifdef CK_NETBIOS
#define NETCONN
#ifdef SUPERLAT
#define NETCONN
#else
#endif /* SUPERLAT */
#endif /* TCPSOCKET */
#endif /* SUNX25 */
#endif /* STRATUSX25 */
#endif /* IBMX25 */
#endif /* HPX25 */
#endif /* DECNET */
#endif /* NPIPE */
#endif /* CK_NETBIOS */
#endif /* NETCONN */
#endif /* OS2 */
#ifndef TCPSOCKET
#ifdef MULTINET
#define TCPSOCKET
#endif /* MULTINET */
#ifdef DEC_TCPIP
#define TCPSOCKET
#endif /* DEC_TCPIP */
#ifdef WINTCP
#define TCPSOCKET
#endif /* WINTCP */
#ifdef TCPWARE
#define TCPSOCKET
#endif /* TCPWARE */
#endif /* TCPSOCKET */
#ifdef OS2
#ifdef NT
#include <windows.h>
#include <tapi.h>
#include "ckntap.h"
#else /* NT */
#define INCL_VIO
#include <os2.h>
#endif /* NT */
#ifdef COMMENT /* Would you believe */
#undef COMMENT /* <os2.h> defines this ? */
#endif /* COMMENT */
#ifdef CK_NETBIOS
#include "ckonbi.h"
#endif /* CK_NETBIOS */
#include "ckocon.h"
extern ascreen commandscreen;
#ifdef KUI
#include "ikui.h"
#endif /* KUI */
#endif /* OS2 */
#ifdef NT
#include "cknwin.h"
#endif /* NT */
#ifdef OS2
#include "ckowin.h"
#include "ckosyn.h"
#endif /* OS2 */
#ifdef CK_TAPI
extern int tttapi;
extern int tapipass;
#endif /* CK_TAPI */
#ifdef CK_KERBEROS
#include "ckuath.h"
#endif /* CK_KERBEROS */
#ifndef WINTCP
#include <signal.h>
#endif /* WINTCP */
#ifdef VMS
#include <descrip.h>
#include <ssdef.h>
#include <stsdef.h>
#ifndef OLD_VMS
#include <lib$routines.h> /* Not for VAX C 2.3 */
#else
#include <libdef.h>
#endif /* OLD_VMS */
#ifdef WINTCP
#include <signal.h>
#endif /* WINTCP */
#endif /* VMS */
#ifdef DCLFDOPEN
/* fdopen() needs declaring because it's not declared in <stdio.h> */
_PROTOTYP( FILE * fdopen, (int, char *) );
#endif /* DCLFDOPEN */
#ifdef DCLPOPEN
/* popen() needs declaring because it's not declared in <stdio.h> */
_PROTOTYP( FILE * popen, (char *, char *) );
#endif /* DCLPOPEN */
int tt_crd = 0; /* Carriage return display */
int interrupted = 0; /* Interrupted from keyboard flag */
static int fxd_inited = 0; /* Fullscreen stuff initialized */
#ifdef DEBUG
char debfil[CKMAXPATH+1]; /* Debugging log file name */
#endif /* DEBUG */
#ifdef TLOG
char trafil[CKMAXPATH+1]; /* Transaction log file name */
#endif /* TLOG */
char sesfil[CKMAXPATH+1]; /* Session log file name */
#ifdef CKLOGDIAL
char diafil[CKMAXPATH+1]; /* Connection log file name */
char cxlogbuf[CXLOGBUFL+1]; /* Connection log record buffer */
int cx_active = 0; /* Connection is active */
extern int dialog;
#endif /* CKLOGDIAL */
#ifdef DYNAMIC
static char *cmdstr = NULL; /* Place to build generic command */
#else
#ifdef pdp11
static char cmdstr[256];
#else
static char cmdstr[4096];
#endif /* pdp11 */
#endif /* DYNAMIC */
#ifndef NOMSEND
char fspec[CMDBL+4]; /* Filename string for \v(filespec) */
int fspeclen = CMDBL;
#else
char fspec[CKMAXPATH+4];
int fspeclen = CKMAXPATH;
#endif /* NOMSEND */
char * rfspec = NULL; /* Received filespec: local */
char * prfspec = NULL; /* Preliminary rfspec */
char * sfspec = NULL; /* Sent filespec: local */
char * psfspec = NULL; /* Preliminary sfspec */
char * srfspec = NULL; /* Received filespec: remote */
char * psrfspec = NULL; /* Preliminary srfspec */
char * rrfspec = NULL; /* Sent filespec: remote */
char * prrfspec = NULL; /* Preliminary rrfspec */
int success = 1, /* Command success/failure flag */
cmdlvl = 0, /* Command level */
action = 0, /* Action selected on command line */
slogts = 0, /* Session-log timestamps on/off */
#ifdef UNIX
sessft = XYFT_T, /* Session log file type */
#else
sessft = XYFT_B, /* (text for UNIX binary for others) */
#endif /* UNIX */
pflag = 1, /* Print prompt */
msgflg = 1; /* Print informational messages */
extern int xaskmore, saveask; /* More-prompting */
#ifdef CK_APC
extern int apcactive;
#endif /* CK_APC */
/* External variables */
extern int local, quiet, binary, network, what, parity, xitsta, escape,
tlevel, bgset, backgrd, xsuspend, cmdint, nettype, seslog, dfloc;
extern int cmd_rows, cmd_cols, xcmdsrc;
extern char cmdfil[];
#ifdef VMS
extern int batch;
#endif /* VMS */
#ifdef datageneral /* 2/12/92 ENH */
#include <sysid.h>
extern int con_reads_mt, conint_ch, conint_avl;
#endif /* datageneral */
extern long speed;
extern char ttname[], *dftty, *cmarg, **cmlist, *versio, myhost[];
#ifndef NOCSETS
extern int fcharset, tcharset, xfrxla;
extern struct csinfo fcsinfo[], tcsinfo[];
#endif /* NOCSETS */
#ifdef OS2
extern unsigned char colorcmd;
#endif /* OS2 */
#ifdef NOXFER
int fdispla = XYFD_N;
#else /* NOXFER is not defined */
#ifdef OS2 /* File transfer display type */
int fdispla = XYFD_C; /* Curses (fullscreen) if we have it */
#else
#ifdef CK_CURSES
int fdispla = XYFD_C;
#else
int fdispla = XYFD_S; /* Otherwise CRT */
#endif /* CK_CURSES */
#endif /* OS2 */
extern struct ck_p ptab[];
extern int protocol, xfrbel, xfrint;
#ifdef STREAMING
extern int streaming, streamok;
#endif /* STREAMING */
/* Used internally */
_PROTOTYP( VOID screenc, (int, char, long, char *) );
_PROTOTYP( VOID screeng, (int, char, long, char *) );
#ifdef CK_CURSES
#ifndef DYNAMIC
static char xtrmbuf[TRMBUFL]; /* tgetent() buffer */
char * trmbuf = xtrmbuf;
#else
char * trmbuf = NULL;
#endif /* DYNAMIC */
_PROTOTYP( static VOID dpyinit, (void) );
_PROTOTYP( static long shocps, (int, long, long) );
_PROTOTYP( static long shoetl, (long, long, long, long) );
#endif /* CK_CURSES */
static int ft_win = 0; /* Fullscreen file transfer display window is active */
/* Variables declared here */
static char * skreason[] = {
"", /* 0 */
"Remote file not older", /* SKP_DAT */
"Identical modification times", /* SKP_EQU */
"Type", /* SKP_TYP */
"Size", /* SKP_SIZ */
"Name collision", /* SKP_NAM */
"Exception List", /* SKP_EXL */
"Dot file", /* SKP_DOT */
"Backup file", /* SKP_BKU */
"Recovery not needed", /* SKP_RES */
"Access denied", /* SKP_ACC */
"Not a regular file", /* SKP_NRF */
"Simulated", /* SKP_SIM */
"Simulated - Remote file older", /* SKP_XUP */
"Simulated - No remote file", /* SKP_XNX */
};
static int nskreason = (sizeof(skreason) / sizeof(char *));
char *
gskreason(n) int n; {
return((n > 0 && n < nskreason) ? skreason[n] : "");
}
char pktfil[CKMAXPATH+1]; /* Packet log file name */
#ifndef NOMSEND /* Multiple SEND */
char *msfiles[MSENDMAX];
#endif /* NOMSEND */
#ifdef CK_TIMERS
extern long rttdelay;
extern int rttflg;
#endif /* CK_TIMERS */
extern int rcvtimo;
#ifdef CK_RESEND
extern int sendmode;
extern long sendstart, rs_len;
#endif /* CK_RESEND */
#ifdef CK_PCT_BAR /* File transfer thermometer */
int thermometer = 1; /* ON by default */
#endif /* CK_PCT_BAR */
#ifdef GFTIMER
CKFLOAT gtv = -1.0, oldgtv = -1.0;
#else
#ifndef OS2
static
#endif /* OS2 */
long gtv = -1L, oldgtv = -1L;
#endif /* GFTIMER */
extern int server, bctu, rptflg, ebqflg, spsiz, urpsiz, wmax, czseen, cxseen,
winlo, displa, timint, npad, ebq, bctr, rptq, atcapu, lpcapu,
swcapu, wslotn, wslotr, rtimo, mypadn, sq, capas, rpsiz, tsecs,
pktlog, lscapu, dest, srvdis, wslots, spackets, spktl, rpktl,
retrans, wcur, numerrs, fsecs, whatru, crunched, timeouts,
rpackets, fncnv, bye_active, discard, inserver, diractive, cdactive;
extern long filcnt, filrej, ffc, tfc, rptn, fsize, filcps, tfcps, cps, peakcps;
long oldcps = 0L;
extern CHAR *rdatap, padch, seol, ctlq, mypadc, eol, *epktmsg;
extern char *xfrmsg;
#ifdef IKSDB
FILE * dbfp = NULL; /* File pointer to database file */
int dbenabled = 1; /* Flag for database is enabled */
extern int ikdbopen; /* Flag for database is open */
unsigned long mydbseek = 0L; /* Seek pointer to my record */
int mydbslot = 0; /* My slot number */
unsigned long myflags = 0L; /* My flags */
unsigned long myatype = 0L; /* My authorization type */
unsigned long myamode = 0L; /* My authorization mode */
unsigned long mystate = 0L; /* My state (SEND, RECEIVE, etc) */
unsigned long mypid = 0L; /* My PID */
unsigned long myip = 0L; /* My IP address */
unsigned long peerip = 0L; /* My peer's IP address */
unsigned long dbip = 0L; /* IP address in db record */
unsigned long dbpid = 0L; /* PID in db record */
unsigned long dbflags = 0L; /* Flags field in db record */
unsigned long dblastused = 0L; /* Last in-use record in db */
char dbrec[DB_RECL]; /* Database record buffer */
char * dbdir = NULL; /* Database directory */
char * dbfile = NULL; /* Database file full pathname */
char myhexip[33] = { NUL, NUL }; /* My IP address in hex */
char peerhexip[33] = { NUL, NUL }; /* Client's IP address in hex */
#endif /* IKSDB */
#ifdef GFTIMER
extern CKFLOAT fpfsecs, fptsecs, fpxfsecs;
#else
extern long xfsecs;
#endif /* GFTIMER */
#endif /* NOXFER */
#ifdef TCPSOCKET
#ifdef NEWFTP
extern char * ftp_host, ftp_srvtyp[];
extern int ftp_csx, ftp_csl, ftp_deb;
#endif /* NEWFTP */
extern char myipaddr[];
#endif /* TCPSOCKET */
#ifndef NOICP
#ifndef NOSPL
extern struct mtab *mactab; /* For ON_EXIT macro. */
extern int nmac;
#endif /* NOSPL */
#ifdef DCMDBUF
extern char *cmdbuf; /* Command buffer */
#else
extern char cmdbuf[]; /* Command buffer */
#endif /* DCMDBUF */
extern int cmd_quoting;
#endif /* NOICP */
#ifndef NOCCTRAP
#ifdef NT
#include <setjmpex.h>
#else /* NT */
#include <setjmp.h>
#endif /* NT */
#include "ckcsig.h"
extern ckjmpbuf cmjbuf;
#endif /* NOCCTRAP */
extern int xfiletype, nscanfile;
int
shoesc(escape) int escape; {
extern char * ccntab[]; /* C0 control character name table */
extern int tt_escape;
if ((escape > 0 && escape < 32) || (escape == 127)) {
printf(" Escape character: Ctrl-%c (ASCII %d, %s): %s\r\n",
ctl(escape),
escape,
(escape == 127 ? "DEL" : ccntab[escape]),
tt_escape ? "enabled" : "disabled"
);
} else {
printf(" Escape character: Code %d",escape);
if (escape > 160 && escape < 256)
printf(" (%c)",escape);
printf(": %s\r\n", tt_escape ? "enabled" : "disabled");
}
return(0);
}
#ifndef NOXFER
/* P R E S E T -- Reset global protocol variables */
extern int recursive;
#ifdef PATTERNS
int patterns = SET_AUTO; /* Whether to use filename patterns */
extern int g_patterns; /* For saving and restoring */
#else
int patterns = SET_OFF;
#endif /* PATTERNS */
#ifndef NOICP
#ifdef CK_LABELED
extern int g_lf_opts, lf_opts;
#endif /* CK_LABELED */
extern int g_matchdot, g_usepipes, usepipes;
extern int g_binary, g_proto, g_displa, g_spath, g_rpath, g_fncnv;
extern int g_recursive;
extern int g_xfermode, xfermode;
extern int g_urpsiz, g_spsizf, g_spsiz;
extern int g_spsizr, g_spmax, g_wslotr, g_prefixing, g_fncact;
extern int g_fnspath, g_fnrpath, g_skipbup;
extern int nolinks;
#ifdef CKSYMLINK
extern int zgfs_link;
#endif /* CKSYMLINK */
#ifndef NOSPL
extern int g_pflg, pwflg, g_pcpt, pwcrypt;
extern char * g_pswd, pwbuf[];
#endif /* NOSPL */
#endif /* NOICP */
extern int spsizf, spsizr, spmax, prefixing, fncact, fnspath, fnrpath;
extern int moving; /* SEND criteria */
extern char sndafter[], sndbefore[], *sndexcept[], *rcvexcept[];
extern long sndlarger, sndsmaller, calibrate, skipbup;
extern int rmailf, rprintf;
extern char optbuf[];
#ifdef PIPESEND
extern char * g_sfilter, * g_rfilter;
extern char * sndfilter, * rcvfilter;
#endif /* PIPESEND */
extern char ** sndarray;
VOID
ftreset() {
#ifndef NOICP
int i;
extern char * filefile;
extern int reliable, xreliable, c_save, ss_save, slostart, urclear;
extern int oopts, omode, oname, opath, kactive, autopath;
extern char * snd_move; /* Directory to move sent files to */
extern char * snd_rename; /* What to rename sent files to */
extern char * rcv_move;
extern char * rcv_rename;
extern char * g_snd_move;
extern char * g_snd_rename;
extern char * g_rcv_move;
extern char * g_rcv_rename;
#ifdef CK_TMPDIR
extern int f_tmpdir;
extern char savdir[];
#endif /* CK_TMPDIR */
#ifdef CK_SPEED
#ifdef COMMENT
extern int f_ctlp;
extern short s_ctlp[], ctlp[];
#endif /* COMMENT */
#endif /* CK_SPEED */
#ifndef NOCSETS
extern int fcs_save, tcs_save;
extern int g_xfrxla, xfrxla;
#endif /* NOCSETS */
/* Restore / reset per-command file-transfer switches */
makestr(&snd_move,g_snd_move);
makestr(&rcv_move,g_rcv_move);
makestr(&snd_rename,g_snd_rename);
makestr(&rcv_rename,g_rcv_rename);
kactive = 0; /* Kermit protocol no longer active */
oopts = -1; /* O-Packet Options */
omode = -1; /* O-Packet Transfer Mode */
oname = -1; /* O-Packet Filename Options */
opath = -1; /* O-Packet Pathname Options */
#ifdef CK_RESEND
rs_len = 0L; /* REGET position */
#endif /* CK_RESEND */
#ifdef COMMENT
#ifdef CK_SPEED
if (f_ctlp) {
for (i = 0; i < 256; i++)
ctlp[i] = s_ctlp[i];
f_ctlp = 0;
}
#endif /* CK_SPEED */
#endif /* COMMENT */
#ifdef CK_TMPDIR
if (f_tmpdir) { /* If we changed to download dir */
zchdir((char *) savdir); /* Go back where we came from */
f_tmpdir = 0;
}
#endif /* CK_TMPDIR */
calibrate = 0L; /* Calibration run */
if (xreliable > -1) {
reliable = xreliable;
debug(F101,"ftreset reliable","",reliable);
}
urclear = 0;
if (autopath) { /* SET RECEIVE PATHNAMES AUTO */
fnrpath = PATH_AUTO;
autopath = 0;
}
if (filefile) { /* File list */
zclose(ZMFILE);
makestr(&filefile,NULL);
}
if (c_save > -1) { /* Block Check Type */
bctr = c_save;
c_save = -1;
}
if (ss_save > -1) { /* Slow Start */
slostart = ss_save;
ss_save = -1;
}
#ifdef CK_LABELED
if (g_lf_opts > -1) {
lf_opts = g_lf_opts; /* Restore labeled transfer options */
g_lf_opts = -1;
}
#endif /* CK_LABELED */
#ifndef NOCSETS
if (tcs_save > -1) { /* Character sets */
tcharset = tcs_save;
tcs_save = -1;
}
if (fcs_save > -1) {
fcharset = fcs_save;
fcs_save = -1;
}
if (g_xfrxla > -1) {
xfrxla = g_xfrxla;
g_xfrxla = -1;
}
setxlatype(tcharset,fcharset); /* Translation type */
#endif /* NOCSETS */
#ifdef NETCONN
#ifndef NOSPL
if (g_pswd) {
ckstrncpy(pwbuf,g_pswd,PWBUFL);
makestr(&g_pswd,NULL);
}
if (g_pflg > -1) {
pwflg = g_pflg;
g_pflg = -1;
}
if (g_pcpt > -1) {
pwcrypt = g_pcpt;
g_pcpt = -1;
}
#endif /* NOSPL */
#endif /* NETCONN */
if (g_binary > -1) { /* File type */
binary = g_binary;
g_binary = -1;
}
if (g_xfermode > -1) { /* Transfer mode */
xfermode = g_xfermode;
g_xfermode = -1;
}
#ifdef PATTERNS
if (g_patterns > -1) { /* Filename patterns */
patterns = g_patterns;
g_patterns = -1;
}
#endif /* PATTERNS */
if (g_usepipes > -1) {
usepipes = g_usepipes;
g_usepipes = -1;
}
if (g_matchdot > -1) {
matchdot = g_matchdot;
g_matchdot = -1;
}
if (g_proto > -1) { /* Protocol */
protocol = g_proto;
g_proto = -1;
}
if (g_urpsiz > -1) {
urpsiz = g_urpsiz;
debug(F101,"ftreset restoring urpsiz","",urpsiz);
g_urpsiz = -1;
}
if (g_spsizf > -1) {
spsizf = g_spsizf;
debug(F101,"ftreset restoring spsizf","",spsizf);
g_spsizf = -1;
}
if (g_spsiz > -1) {
spsiz = g_spsiz;
debug(F101,"ftreset restoring spsiz","",spsiz);
g_spsiz = -1;
}
if (g_spsizr > -1) {
spsizr = g_spsizr;
debug(F101,"ftreset restoring spsizr","",spsizr);
g_spsizr = -1;
}
if (g_spmax > -1) {
spmax = g_spmax;
g_spmax = -1;
}
if (g_wslotr > -1) {
wslotr = g_wslotr;
g_wslotr = -1;
}
if (g_prefixing > -1) {
prefixing = g_prefixing;
g_prefixing = -1;
}
if (g_fncact > -1) {
fncact = g_fncact;
g_fncact = -1;
}
if (g_fncnv > -1) {
fncnv = g_fncnv;
g_fncnv = -1;
}
if (g_fnspath > -1) {
fnspath = g_fnspath;
g_fnspath = -1;
}
if (g_fnrpath > -1) {
fnrpath = g_fnrpath;
g_fnrpath = -1;
}
if (g_skipbup > -1) {
skipbup = g_skipbup;
g_skipbup = -1;
}
nolinks = 2; /* /FOLLOWLINKS is never global */
recursive = 0; /* /RECURSIVE can never be global */
xfiletype = -1;
if (g_displa > -1) { /* File transfer display */
fdispla = g_displa;
g_displa = -1;
}
if (g_spath > -1) { /* Send pathnames */
fnspath = g_spath;
g_spath = -1;
}
if (g_rpath > -1) { /* Receive pathnames */
fnrpath = g_rpath;
g_rpath = -1;
}
if (g_fncnv > -1) { /* Filename conversion */
fncnv = g_fncnv;
g_fncnv = -1;
}
#ifdef PIPESEND
makestr(&sndfilter,g_sfilter); /* Send filter */
makestr(&rcvfilter,g_rfilter); /* Receive filter */
#endif /* PIPESEND */
#ifndef NOFRILLS
rmailf = rprintf = 0; /* MAIL and PRINT modifiers for SEND */
optbuf[0] = NUL; /* MAIL and PRINT options */
#endif /* NOFRILLS */
moving = 0; /* Reset delete-after-send indicator */
sndafter[0] = NUL; /* Reset SEND selection switches */
sndbefore[0] = NUL;
for (i = 0; i < NSNDEXCEPT; i++) {
if (sndexcept[i])
free(sndexcept[i]);
sndexcept[i] = NULL;
if (rcvexcept[i])
free(rcvexcept[i]);
rcvexcept[i] = NULL;
}
sndlarger = -1L;
sndsmaller = -1L;
#ifdef GFTIMER
gtv = -1.0;
oldgtv = -1.0;
#else
gtv = -1L;
oldgtv = -1L;
#endif /* GFTIMER */
#endif /* NOICP */
}
#endif /* NOXFER */
char *
ttgtpn() { /* Get typical port name */
/*
Ideally this routine would be implemented in each of the cku?io.* modules,
but that requires changing the API definition.
*/
return(
#ifdef OS2
#ifdef OS2ONLY
"COM1"
#else /* OS2ONLY */
"TAPI [ name ] or COM1"
#endif /* OS2ONLY */
#else /* OS2 */
#ifdef VMS
"TXA0:, TTA0:, or LTA0:"
#else /* VMS */
#ifdef SOLARIS
"/dev/cua/a"
#else /* SOLARIS */
#ifdef HPUX10
"/dev/cua0p0"
#else /* HPUX10 */
#ifdef HPUX
"/dev/cua00"
#else /* HPUX */
#ifdef __FreeBSD__
"/dev/cuaa0"
#else /* __FreeBSD__ */
#ifdef __linux__
"/dev/ttyS0"
#else /* __linux__ */
#ifdef BSD44
"/dev/tty00"
#else /* BSD44 */
#ifdef OSK
"/t1"
#else /* OSK */
#ifdef QNX
"/dev/ser1"
#else /* QNX */
#ifdef QNX6
"/dev/ser1"
#else /* QNX6 */
#ifdef UNIXWARE
"/dev/term/00 or /dev/tty00"
#else /* UNIXWARE */
#ifdef CK_SCOV5
"/dev/tty1A"
#else /* CK_SCOV5 */
#ifdef CK_SCO32V4
"/dev/tty1A"
#else /* CK_SCO32V4 */
#ifdef M_XENIX
"/dev/tty1A"
#else /* M_XENIX */
#ifdef AIXRS
"/dev/tty0"
#else /* AIXRS */
#ifdef DGUX
"/dev/tty00"
#else /* DGUX */
#ifdef datageneral
"@con1"
#else /* datageneral */
#ifdef IRIX
"/dev/ttym0"
#else /* IRIX */
#ifdef SUNOS4
"/dev/ttyh0"
#else /* SUNOS4 */
#ifdef SV68R3V6
"/dev/scc0"
#else /* SV68R3V6 */
#ifdef MOTSV88R4
"/dev/contty00"
#else /* MOTSV88R4 */
#ifdef NEXT
"/dev/cufa"
#else
#ifdef OSF
"/dev/ttyd1"
#else
#ifdef SINIX
"/dev/ttyc1"
#else
#ifdef UNIX
"/dev/cua, /dev/acu, /dev/tty0, etc"
#else /* UNIX */
"(sorry no example available)"
#endif /* UNIX */
#endif /* SINIX */
#endif /* OSF */
#endif /* NEXT */
#endif /* MOTSV88R4 */
#endif /* SV68R3V6 */
#endif /* SUNOS4 */
#endif /* IRIX */
#endif /* datageneral */
#endif /* DGUX */
#endif /* AIX */
#endif /* M_XENIX */
#endif /* CK_SCO32V4 */
#endif /* CK_SCOV5 */
#endif /* UNIXWARE */
#endif /* QNX6 */
#endif /* QNX */
#endif /* OSK */
#endif /* BSD44 */
#endif /* __linux__ */
#endif /* __FreeBSD__ */
#endif /* HPUX */
#endif /* HPUX10 */
#endif /* SOLARIS */
#endif /* VMS */
#endif /* OS2 */
);
}
/* C K _ E R R S T R -- Return message from most recent system error */
#ifdef CKROOT
extern int ckrooterr;
#endif /* CKROOT */
char *
ck_errstr() {
#ifdef USE_STRERROR
#ifndef CK_ANSILIBS
/* Should have been declared in <string.h> */
_PROTOTYP( char * strerror, (int) );
#endif /* CK_ANSILIBS */
#ifdef CKROOT
if (ckrooterr)
return("Off limits");
#endif /* CKROOT */
return(strerror(errno));
#else /* !USE_STRERROR */
#ifdef VMS
extern char * ckvmserrstr(unsigned long);
#ifdef CKROOT
if (ckrooterr)
return("Off limits");
#endif /* CKROOT */
return(ckvmserrstr(0L));
#else /* !VMS */
#ifdef BSD44
#ifdef __386BSD__
#ifndef NDSYSERRLIST
extern int sys_nerr;
extern char *sys_errlist[];
#endif /* NDSYSERRLIST */
#else /* !__386BSD__ */
#ifndef __bsdi__
#ifndef NDSYSERRLIST
extern int sys_nerr;
extern const char *const sys_errlist[];
#endif /* NDSYSERRLIST */
#endif /* __bsdi__ */
#endif /* __386BSD__ */
#ifdef CKROOT
if (ckrooterr)
return("Off limits");
else
#endif /* CKROOT */
if (errno >= sys_nerr)
return("Error number out of range");
else
return((char *) sys_errlist[errno]);
#else /* !BSD44 */
#ifdef ATTSV
#ifndef NDSYSERRLIST
extern int sys_nerr;
extern char *sys_errlist[];
#endif /* NDSYSERRLIST */
#ifdef CKROOT
if (ckrooterr)
return("Off limits");
else
#endif /* CKROOT */
if (errno >= sys_nerr)
return("Error number out of range");
else
return((char *) sys_errlist[errno]);
#else /* !ATTSV */
#ifdef BSD4
#ifndef NDSYSERRLIST
extern int sys_nerr;
extern char *sys_errlist[];
#endif /* NDSYSERRLIST */
#ifdef CKROOT
if (ckrooterr)
return("Off limits");
else
#endif /* CKROOT */
if (errno >= sys_nerr)
return("Error number out of range");
else
return((char *) sys_errlist[errno]);
#else
#ifdef OS2
#ifndef NDSYSERRLIST
extern char *sys_errlist[];
#endif /* NDSYSERRLIST */
#ifdef NT
extern int_sys_nerr;
#endif /* NT */
char *e;
#ifdef CKROOT
if (ckrooterr)
return("Off limits");
#endif /* CKROOT */
e = (errno > -1
#ifdef NT
&& errno <= _sys_nerr
#endif /* NT */
) ?
#ifdef NT
(char *) sys_errlist[errno]
#else /* NT */
/* I don't know how to get a CLIB error string in OS/2 */
strerror(errno)
#endif /* NT */
: "";
return(e ? e : "");
#else /* OS2 */
return("");
#endif /* OS2 */
#endif /* BSD4 */
#endif /* ATTSV */
#endif /* BSD44 */
#endif /* VMS */
#endif /* USE_STRERROR */
}
#ifdef PATTERNS
/*
Filename pattern recognition lists for automatic text/binary switching.
These are somewhat passe after the addition of scanfile() (7.0).
But with the addition of FTP [M]GET, they're back in style (8.0).
Although, with FTP the lists need to be used in the reverse. With
Kermit the list is used to imply the types of the local system. Whereas
with FTP, the list must be used to imply the type of the remote system.
Therefore, all platforms must now support all of the lists.
*/
char *txtpatterns[FTPATTERNS+1] = { NULL, NULL };
char *binpatterns[FTPATTERNS+1] = { NULL, NULL };
/*
Default pattern lists for each platform...
NOTE: In most cases we leave ".hlp", ".ini", and ".scr" alone; although they
are traditionally text types, they are binary in Windows. So they are
handled by the prevailing SET FILE TYPE, rather than automatically.
Similarly for ".dat", ".inf", and so on. Also ".ps" since PostScript files
are not always text. ".log" is omitted since logs can be text or binary,
except in VMS they are usually text, etc etc.
Later (Sep 2003): Add PostScript to binary patterns.
*/
static char *txtp[SYS_MAX][FTPATTERNS] = {
/* UNKNOWN */ {
NULL, NULL
},
{ /* UNIX */
"*.txt","*.c","*.h","*.r","*.w","*.cpp","*.cc","*.ksc","*.bwr","*.upd",
"*.html","*.htm","*.mss","*.tex","*.nr","[Mm]akefile", "*.hex", "*.hqx",
"*.for","*.f77","*.f","*.F","*.s","*.pas","*.java","*.el","*.lisp","*.sh",
"*.m4","*.perl","*.pl","*.pod","*.pm","*.awk","*.sno","*.spt","*.sed",
"*.ksc","*.TXT", "*read.me", "*READ.ME", ".*", "*/.*", "*.mem","*.mac",
NULL
},
{ /* WIN32 */
"*.txt","*.ksc","*.htm","*.html","*.bat","*.cmd","*.jav","*.asm", "*.hex",
"*.hqx", "*.c", "*.h", "*.cpp", "*.hpp", "*.cxx", "*.cxx", "*.w",
"*.java", "*.bwr", "*.upd", "*.mak", "read.me", "*.map", "makefile",
"*.mem","*.mac","*.cc","*.pl","*.pod","*.pm","*.m4",NULL
},
{ /* VMS */
"*.com","*.txt","*.c", "*.for","*.pas","*.rno","*.rnh","*.mar","*.bli",
"*.hlp","*.mss","*.doc","*.bwr","*.cld","*.hex","*.bas","*.ini","*.log",
"*.mms","*.opt","*.ksc","*.perl","*.pl","*.pod","*.pm","*.sno","*.spt",
"*.mem",NULL
},
{ /* OS2 */
"*.txt","*.ksc","*.htm","*.html","*.bat","*.cmd","*.jav","*.asm", "*.hex",
"*.hqx", "*.c", "*.h", "*.cpp", "*.hpp", "*.cxx", "*.cxx", "*.w",
"*.java", "*.bwr", "*.upd", "*.mak", "read.me", "*.map", "makefile",
NULL
},
{ /* DOS */
"*.txt","*.ksc","*.htm","*.bat","*.cmd","*.jav","*.asm", "*.hex",
"*.hqx", "*.c", "*.h", "*.cpp", "*.hpp", "*.cxx", "*.cxx", "*.w",
"*.bwr", "*.upd", "*.mak", "read.me", "*.map", "makefile", NULL
},
{ /* TOPS-10 */
"*.cmd","*.hlp","*.doc","*.ini","*.txt","*.mac","*.for","*.sai","*.bli",
"*.pas","*.sno","*.spt","*.pcl","*.mss","*.rno","*.b36","*.tex","*.pub",
"*.req","*.r36","*.mem","*.bwr","*.ccl","*.ctl","*.rnh","*.ksc",NULL
},
{ /* TOPS-20 */
"*.cmd","*.hlp","*.doc","*.ini","*.txt","*.mac","*.for","*.sai","*.bli",
"*.pas","*.sno","*.spt","*.pcl","*.mss","*.rno","*.b36","*.tex","*.pub",
"*.req","*.r36","*.mem","*.bwr","*.ccl","*.ctl","*.rnh","*.ksc",NULL
},
{ /* STRATUS VOS */
"*.txt","*.ksc","*.htm","*.html","*.bat", "*.cmd","*.jav","*.asm","*.hex",
"*.hqx","*.c", "*.h", "*.w", "*.java","*.bwr","*.upd","*.ttp","*.cm",
"*.pl1","*.emacs", "read.me", "*.pl", "makefile", NULL
},
{ /* DG AOS/VS */
"*.txt", "*.c", "*.h", "*.w", "*.er", "*.bwr", "*.upd", "read.me",
"*.cli", "*.ksc", NULL
},
{ /* OSK */
"*.c","*.cpp","*.h","*.a","*akefile", /* program sources */
"*.for","*.f77","*.f","*.F","*.s","*.pas","*.java","*.el","*.lisp",
"*.sh","*.perl","*.awk","*.sno","*.spt","*.sed",
"*.txt","*.w", /* general text */
"*.ksc","*.bwr","*.upd",
"*.html","*.htm","*.mss","*.tex","*.nr","*.hex", "*.hqx",
"*.TXT", "*read.me", "*READ.ME", ".*", "*/.*",
NULL
}
};
/* Note: .DOC added to (some) binary patterns June 1998... Microsoft wins. */
static char *binp[SYS_MAX][FTPATTERNS] = {
{ /* UNKNOWN */
NULL, NULL
},
{ /* UNIX */
"*.gz","*.Z","*.tgz","*.gif", "*.tar","*.zip","*.o","*.so","*.a","*.out",
"*.exe", "*.jpg", "*.jpeg", "*.tif","*.tiff", "*.pdf", "*.so.*", "*.class",
"*.rpm", "*.bmp", "*.bz2", "*.BMP", "*.dll", "*.doc", "*.vxd", "*.dcx",
"*.xl*", "*.lzh", "*.lhz", "*.au", "*.voc", "*.mpg", "*.mpeg","[wk]ermit",
"*.ps", NULL
},
{ /* WIN32 */
"*.exe", "*.zip", "*.obj", "*.com", "*.gif", "*.jpg", "*.wav", "*.ram",
"*.class","*.cla","*.dll", "*.drv", "*.ocx", "*.vbx", "*.lib", "*.ico",
"*.bmp", "*.tif", "*.tar", "*.gz", "*.tgz", "*.xl*", "*.doc", "*.vxd",
"*.pdf", "*.lzh", "*.vxd", "*.snd", "*.au", "* .voc", "*.mpg", "*.mpeg",
"*.ps", NULL
},
{ /* VMS */
"*.exe","*.obj","*.bak","*.bin","*.adf","*.stb","*.mai","*.sys","*.dmp",
"*.ps", "*.dat","*.par", NULL
},
{ /* OS2 */
"*.exe", "*.zip", "*.obj", "*.com", "*.gif", "*.jpg", "*.wav", "*.ram",
"*.class", "*.cla", "*.dll", "*.drv", "*.ocx", "*.vbx", "*.lib", "*.ico",
"*.bmp", "*.tif", "*.tar", "*.gz", "*.tgz", "*.xl*", "*.doc", "*.vxd",
"*.pdf", "*.ps", "*.lzh", NULL
},
{ /* DOS */
"*.exe", "*.zip", "*.obj", "*.com", "*.gif", "*.jpg", "*.wav", "*.ram",
"*.cla", "*.dll", "*.drv", "*.ocx", "*.vbx", "*.lib", "*.ico",
"*.bmp", "*.tif", "*.tar", "*.gz", "*.tgz", "*.xl*", "*.doc", "*.vxd",
"*.pdf", "*.ps", "*.lzh", NULL
},
{ /* TOPS10 */
"*.exe","*.sav","*.bin","*.rim","*.rel","*.unv","*.lib","*.tap","*.dvi",
"*.ps", NULL
},
{ /* TOPS20 */
"*.exe","*.sav","*.bin","*.rim","*.rel","*.unv","*.lib","*.tap","*.dvi",
"*.ps", NULL
},
{ /* STRATUS VOS */
"*.exe", "*.zip", "*.obj", "*.com", "*.gif", "*.jpg", "*.wav", "*.ram",
"*.class", "*.cla", "*.dll", "*.drv", "*.ocx", "*.vbx", "*.lib", "*.ico",
"*.bmp", "*.tif", "*.tar", "*.gz", "*.tgz", "*.xl*", "*.doc", "*.vxd",
"*.pdf", "*.ps", "*.lzh", "*.pm", NULL
},
{ /* DG */
"*.ob", "*.pr", "*.dmp", "*.ps", NULL
},
{ /* OSK */
"*.gz","*.Z","*.z","*.tgz","*.lhz","*.tar", /* archivers */
"*.zip","*.ar","*.zoo","*.rpm","*.lzh",
/* object files, libraries, executables */
"*.r","*.l","*.exe", "*.dll", "*.so.*", "*.class",
/* images */
"*.gif", "*.jpg", "*.jpeg", "*.tif","*.tiff", "*.pdf", "*.ps",
"*.bmp", "*.bz2", "*.BMP","*.pcx",
NULL
}
};
/*
Set up default pattern lists so they can be freed and re-malloc'd.
Each pattern list must terminated by a null element.
*/
VOID
initpat() {
int i;
for (i = 0; i < FTPATTERNS; i++) {
txtpatterns[i] = NULL;
binpatterns[i] = NULL;
}
for (i = 0; i < FTPATTERNS; i++) {
#ifdef UNIX
makestr(&(txtpatterns[i]),txtp[SYS_UNIX][i]);
#else /* UNIX */
#ifdef OS2
#ifdef NT
makestr(&(txtpatterns[i]),txtp[SYS_WIN32][i]);
#else /* NT */
makestr(&(txtpatterns[i]),txtp[SYS_OS2][i]);
#endif /* NT */
#else /* OS2 */
#ifdef VMS
makestr(&(txtpatterns[i]),txtp[SYS_VMS][i]);
#else /* VMS */
#ifdef STRATUS
makestr(&(txtpatterns[i]),txtp[SYS_VOS][i]);
#else /* STRATUS */
#ifdef datageneral
makestr(&(txtpatterns[i]),txtp[SYS_DG][i]);
#else /* datageneral */
#ifdef OSK
makestr(&(txtpatterns[i]),txtp[SYS_OSK][i]);
#else /* OSK */
makestr(&(txtpatterns[i]),txtp[SYS_UNK][i]);
#endif /* OSK */
#endif /* datageneral */
#endif /* STRATUS */
#endif /* VMS */
#endif /* OS2 */
#endif /* UNIX */
if (!txtp[i])
break;
}
for (i = 0; i < FTPATTERNS; i++) {
#ifdef UNIX
makestr(&(binpatterns[i]),binp[SYS_UNIX][i]);
#else /* UNIX */
#ifdef OS2
#ifdef NT
makestr(&(binpatterns[i]),binp[SYS_WIN32][i]);
#else /* NT */
makestr(&(binpatterns[i]),binp[SYS_OS2][i]);
#endif /* NT */
#else /* OS2 */
#ifdef VMS
makestr(&(binpatterns[i]),binp[SYS_VMS][i]);
#else /* VMS */
#ifdef STRATUS
makestr(&(binpatterns[i]),binp[SYS_VOS][i]);
#else /* STRATUS */
#ifdef datageneral
makestr(&(binpatterns[i]),binp[SYS_DG][i]);
#else /* datageneral */
#ifdef OSK
makestr(&(binpatterns[i]),binp[SYS_OSK][i]);
#else /* OSK */
makestr(&(binpatterns[i]),binp[SYS_UNK][i]);
#endif /* OSK */
#endif /* datageneral */
#endif /* STRATUS */
#endif /* VMS */
#endif /* OS2 */
#endif /* UNIX */
if (!binp[i])
break;
}
}
/*
m a t c h n a m e -- Compare filename with text & binary name patterns.
Returns:
0 if name matches a text pattern but not a binary pattern.
1 if name matches a binary pattern but not a text pattern.
-1 if name matches no patterns.
-2 if name matches a binary pattern and a text pattern.
*/
int
matchname(filename, local, os) char * filename; int local; int os; {
int rc = -1; /* Return code */
char * name, * p;
#ifdef OS2ORUNIX
char tmpbuf[CKMAXPATH+1];
#endif /* OS2ORUNIX */
name = filename ? filename : ""; /* Copy of original arg */
if (patterns && *name) { /* If PATTERNS ON... */
int i;
#ifdef OS2ORUNIX
if (ckmatch("*.~[1-9]*~",name,1,1)) { /* Name has backup suffix? */
int k;
k = ckstrncpy(tmpbuf,name,CKMAXPATH+1); /* Yes, copy and strip */
for (i = k - 3; i > 4; i--) {
if (tmpbuf[i] == '~' && tmpbuf[i-1] == '.') {
tmpbuf[i-1] = NUL;
break;
}
}
name = tmpbuf; /* And point to stripped copy */
}
#endif /* OS2ORUNIX */
zstrip(name,&p); /* Strip pathname too */
name = p;
if (local) {
if (txtpatterns[0]) { /* Search text patterns */
for (i = 0; i < FTPATTERNS && txtpatterns[i]; i++) {
if (ckmatch(txtpatterns[i],name,filecase,1)) {
rc = 0;
break;
}
}
}
if (binpatterns[0]) { /* And search binary patterns */
for (i = 0; i < FTPATTERNS && binpatterns[i]; i++) {
if (ckmatch(binpatterns[i],name,filecase,1)) {
rc = (rc > -1) ? -2 : 1;
break;
}
}
}
} else {
if (os >= 0 && os < SYS_MAX) {
if (txtp[os][0]) {
for (i = 0; i < FTPATTERNS && txtp[os][i]; i++) {
if (ckmatch(txtp[os][i],name,filecase,1)) {
rc = 0;
break;
}
}
}
if (binp[os][0]) {
for (i = 0; i < FTPATTERNS && binp[os][i]; i++) {
if (ckmatch(binp[os][i],name,filecase,1)) {
rc = (rc > -1) ? -2 : 1;
break;
}
}
}
}
}
}
debug(F111,"matchname",name,rc);
return(rc);
}
#endif /* PATTERNS */
#ifdef UNICODE
#ifndef NOEVENMAX
#define EVENMAX
#endif /* NOEVENMAX */
#endif /* UNICODE */
/* S C A N F I L E -- Analyze a file's contents */
/*
Call with:
name: Pointer to name of existing file.
flag: Pointer to int in which to return additional numeric data.
Returns:
-1 on failure (to open file or to read from it).
Integer, 0..4, on success indicating file type:
0 = 7-bit text (flag = -1)
1 = UTF-8 text (flag = -1)
2 = UCS-2 text (flag = 0: big-endian; flag = 1: little-endian)
3 = 8-bit text (flag = 0: no C1 bytes; flag = 1: includes C1 bytes)
4 = binary (flag = -1)
If UNICODE is defined:
1. If file begins with a valid BOM, it is believed. Otherwise we
read the first 4K of the file (since it might be email with verbose
headers) and analyze it:
2. If file contains only valid UTF-8 sequences, we call it UTF-8;
otherwise:
3. If the file contains lots of alternate 0 bytes, we call it UCS-2, and
set the polarity according to whether the preponderance of them are in
even or odd positions; otherwise:
4. If EVENMAX is defined and the file contains lots of alternate bytes that
are identical, even if they aren't zero, and the number of such bytes
is at least four times the length of the maximum run of alternating
identical bytes of the opposite polarity, we call it UCS-2; otherwise:
5. If the file contained no bytes with their 8th bits on and no controls
other than CR, LF, HT, and FF, we call it ASCII; otherwise:
6. If it contains C0 control characters other than CR, LF, HT, and FF, we
call it binary; otherwise:
7. We call it 8-bit text, character set unknown (could be Latin-1 or
anything else).
Note that malformed UTF-8 is not diagnosed as UTF-8.
If UNICODE is not defined:
1. If the file contains C0 control characters other than CR, LF, HT, and
FF, we call it binary; otherwise:
2. If the file contains any 8-bit bytes, we call it 8-bit text; otherwise:
3. We call it 7-bit text.
In the non-Unicode case, UCS-2 is diagnosed as binary, but UTF-8 as
8-bit text.
There is no significant speed difference between the Unicode and
non-Unicode cases.
*/
int
scanfile(name,flag,nscanfile) char * name; int * flag, nscanfile; {
FILE * fp; /* File pointer */
unsigned char buf[SCANFILEBUF]; /* File data buffer for analysis */
int x, val = -1, count = 0; /* Workers */
int rc = -1; /* Return code */
int pv = -1; /* Pattern-match value */
int eof = 0; /* Flag for file EOF encountered */
int bytes = 0; /* Total byte count */
#ifdef UNICODE
unsigned int c0, c1; /* First 2 file bytes (for BOM) */
#endif /* UNICODE */
extern int pipesend, filepeek;
register int i; /* Loop control */
int readsize = 0; /* How much to read */
int eightbit = 0; /* Number of bytes with 8th bit on */
int c0controls = 0; /* C0 non-text control-char counter */
int c0noniso = 0; /* C0 non-ISO control-char counter */
int c1controls = 0; /* C1 control-character counter */
unsigned int c; /* Current character */
int runmax = 0; /* Longest run of 0 bytes */
int runzero = 0; /* Run of 0 bytes */
int pctzero = 0; /* Percentage of 0 bytes */
int txtcz = 0;
#ifdef CK_CTRLZ
extern int eofmethod;
#endif /* CK_CTRLZ */
#ifdef UNICODE
int notutf8 = 0; /* Nonzero if definitely not UTF-8 */
int utf8state = 0; /* UTF-8 recognizer state */
int oddzero = 0; /* Number of 0 bytes in odd postions */
int evenzero = 0; /* and in even positions */
int lfnul = 0; /* Number of <LF><NUL> sequences */
int crlf = 0; /* Number of <CRLF> sequences */
#else
int notutf8 = 1;
#endif /* UNICODE */
#ifdef COMMENT
#ifdef EVENMAX
int oddrun = 0, oddmax = 0, oddbyte = 0, oddmaxbyte = 0;
int evenrun = 0, evenmax = 0, evenbyte = 0, evenmaxbyte = 0;
#endif /* EVENMAX */
#endif /* COMMENT */
#ifndef NOXFER
if (pipesend || calibrate || sndarray) /* Only for real files */
return(-1);
#endif /* NOXFER */
debug(F111,"scanfile",name,nscanfile);
#ifdef PATTERNS
if (!filepeek) {
pv = matchname(name,1,-1);
if (pv < 0)
rc = -1;
else
rc = (pv == 1) ? FT_BIN : FT_TEXT;
debug(F111,"scanfile !filepeek result",name,rc);
return(rc);
}
#endif /* PATTERNS */
#ifdef VMS
/* We don't scan in VMS where text files have various record formats in */
/* which record headers contain seemingly non-text bytes. So the best */
/* we can do in VMS is tell whether the file is text or binary, period. */
{
int b, x;
b = binary; /* Save current binary setting */
if (zopeni(ZIFILE,name) > 0) { /* In VMS this sets binary */
x = binary; /* Get result */
zclose(ZIFILE); /* Close the file */
binary = b; /* Restore previous binary setting */
rc = x ? FT_BIN : FT_TEXT;
val = 0;
goto xscanfile;
}
}
#endif /* VMS */
eof = 0; /* End-of-file reached indicator */
#ifdef OS2
fp = fopen(name, "rb"); /* Open the file in binary mode */
#else
fp = fopen(name, "r");
#endif /* OS2 */
if (!fp) /* Failed? */
return(-1);
while (1) { /* One or more gulps from file */
if (eof) { /* EOF from last time? */
debug(F111,"scanfile at EOF",name,bytes);
if (runzero > runmax)
runmax = runzero;
break;
}
if (nscanfile < 0) { /* Reading whole file */
readsize = SCANFILEBUF;
} else { /* Reading first nscanfilee bytes */
readsize = nscanfile - bytes;
if (readsize < 1)
break;
if (readsize > SCANFILEBUF)
readsize = SCANFILEBUF;
}
debug(F101,"scanfile readsize","",readsize);
count = fread(buf,1,readsize,fp); /* Read a buffer */
if (count == EOF || count == 0) {
debug(F111,"scanfile EOF",name,count);
break;
}
debug(F111,"scanfile buffer ok",name,count);
if (bytes == 0 && count > 8) {
/* PDF files can look like text in the beginning. */
if (!ckstrcmp((char *)buf,"%PDF-1.",7,1)) {
if (isdigit(buf[7])) {
if (buf[8] == '\015' ||
count > 9 && buf[8] == SP && buf[9] == '\015') {
#ifdef DEBUG
buf[8] = NUL;
debug(F110,"scanfile PDF",buf,0);
#endif /* DEBUG */
binary = 1; /* But they are binary. */
break;
}
}
} else if (!ckstrcmp((char *)buf,"%!PS-Ado",8,1)) {
/* Ditto for PostScript */
#ifdef DEBUG
int i;
for (i = 8; i < count; i++) {
if (buf[i] < '!') {
buf[i] = NUL;
break;
}
}
debug(F110,"scanfile PostScript",buf,0);
#endif /* DEBUG */
binary = 1;
break;
#ifndef NOPCLSCAN
} else if (!ckstrcmp((char *)buf,") HP-PCL",8,1)) {
/* HP PCL printer language */
#ifdef DEBUG
int i;
for (i = 8; i < count; i++) {
if (buf[i] < '!') {
buf[i] = NUL;
break;
}
}
debug(F110,"scanfile PCL",buf,0);
#endif /* DEBUG */
binary = 1;
break;
}
#endif /* NOPCLSCAN */
#ifndef NOPJLSCAN
else if (buf[0] == '\033' && (buf[1] == 'E' || buf[1] == '%')) {
/* Ditto for PJL Job printer header */
#ifdef DEBUG
int i;
for (i = 2; i < count; i++) {
if (buf[i] < '!') {
buf[i] = NUL;
break;
}
}
debug(F110,"scanfile PJL Job printer header",buf,0);
#endif /* DEBUG */
binary = 1;
break;
#endif /* NOPJLSCAN */
}
}
#ifdef UNICODE
if (bytes == 0 && count > 1) {
int incl_cnt = 0;
/* First look for BOM */
c0 = (unsigned)((unsigned)buf[0]&0xFF); /* First file byte */
c1 = (unsigned)((unsigned)buf[1]&0xFF); /* Second byte */
if (c0 == 0xFE && c1 == 0xFF) { /* UCS-2 BE */
rc = FT_UCS2;
val = 0;
debug(F111,"scanfile UCS2 BOM BE",ckitoa(val),rc);
incl_cnt++;
} else if (c0 == 0xFF && c1 == 0xFE) { /* UCS-2 LE */
rc = FT_UCS2;
val = 1;
debug(F111,"scanfile UCS2 BOM LE",ckitoa(val),rc);
incl_cnt++;
} else if (count > 2) if (c0 == 0xEF && c1 == 0xBB &&
(unsigned)((unsigned)buf[2]&0xFF) == 0xBF) {
rc = FT_UTF8;
debug(F111,"scanfile UTF8 BOM",ckitoa(val),rc);
incl_cnt++;
}
if (incl_cnt) { /* Have BOM */
bytes += count;
goto xscanfile;
}
}
#endif /* UNICODE */
bytes += count; /* Count bytes read */
eof = feof(fp); /* Flag for at EOF */
for (i = 0; i < count; i++) { /* For each byte... */
c = (unsigned)buf[i]; /* For ease of reference */
if (!c) { /* Zero byte? */
#ifdef EVENMAX
if (i&1) /* In odd position */
oddzero++;
else
evenzero++; /* In even position */
#endif /* EVENMAX */
runzero++;
} else { /* Not a zero byte */
if (runzero > runmax)
runmax = runzero;
if (runmax > 2) /* That's all we need to be certain */
break; /* it's a binary file. */
runzero = 0;
}
#ifdef COMMENT
#ifdef EVENMAX
/* This is to catch UCS-2 with a non-ASCII, non-Latin-1 repertoire */
if (i > 1) { /* Look for runs of alternating chars */
if (i&1) {
if (c == buf[i-2]) { /* In odd positions */
oddrun++;
oddbyte = c;
} else {
oddmax = oddrun;
oddmaxbyte = oddbyte;
}
} else { /* and even positions */
if (c == buf[i-2]) {
evenrun++;
evenbyte = c;
} else {
evenmax = evenrun;
evenmaxbyte = evenbyte;
}
}
}
#endif /* EVENMAX */
#endif /* COMMENT */
if ((c & 0x80) == 0) { /* We have a 7-bit byte */
#ifdef UNICODE
if (i > 0 && c == 10) { /* Linefeed */
if (buf[i-1] == 0) lfnul++; /* Preceded by NUL */
else if (buf[i-1] == 13) crlf++; /* or by CR... */
}
#endif /* UNICODE */
if (c < ' ') { /* Check for CO controls */
if (c != LF && c != CR && c != HT && c != FF) {
c0controls++;
if (c != ESC && c != SO && c != SI)
c0noniso++;
}
if ((c == '\032') /* Ctrl-Z */
#ifdef COMMENT
&& eof && (i >= count - 2)
#endif /* COMMENT */
) {
c0controls--;
c0noniso--;
#ifdef CK_CTRLZ
if (eofmethod == XYEOF_Z && txtcz == 0) {
if (c0controls == 0) /* All text prior to Ctrl-Z */
txtcz = 1;
}
#endif /* CK_CTRLZ */
}
}
#ifdef UNICODE
if (!notutf8 && utf8state) { /* In UTF-8 sequence? */
utf8state = 0;
debug(F000,"scanfile","7-bit byte in UTF8 sequence",c);
notutf8++; /* Then it's not UTF-8 */
continue;
}
#endif /* UNICODE */
} else { /* We have an 8-bit byte */
eightbit++; /* Count it */
if (c >= 0x80 && c < 0xA0) /* Check for C1 controls */
c1controls++;
#ifdef UNICODE
if (!notutf8) { /* If it might still be UTF8... */
switch (utf8state) { /* Enter the UTF-8 state machine */
case 0: /* First byte... */
if ((c & 0xE0) == 0xC0) { /* Tells number of */
utf8state = 1; /* subsequent bytes */
} else if ((c & 0xF0) == 0xE0) {
utf8state = 2;
} else if ((c & 0xF8) == 0xF0) {
utf8state = 3;
} else {
notutf8++;
}
break;
case 1: /* Subsequent byte */
case 2:
case 3:
if ((c & 0xC0) != 0x80) { /* Must start with 10 */
debug(F000,"scanfile",
"bad byte in UTF8 sequence",c);
notutf8++;
break;
}
utf8state--; /* Good, one less in this sequence */
break;
default: /* Shouldn't happen */
debug(F111,"scanfile","bad UTF8 state",utf8state);
notutf8++;
}
}
#endif /* UNICODE */
}
}
}
fclose(fp); /* Close the file */
debug(F101,"scanfile bytes","",bytes);
if (bytes == 0) /* If nothing was read */
return(-1); /* we're done. */
#ifdef EVENMAX
/* In case we had a run that never broke... */
#ifdef COMMENT
if (oddmax == 0) {
oddmax = oddrun;
oddmaxbyte = oddbyte;
}
if (evenmax == 0) {
evenmax = evenrun;
evenmaxbyte = evenbyte;
}
#endif /* COMMENT */
if (runmax == 0) {
runmax = runzero;
}
#endif /* EVENMAX */
#ifdef UNICODE
if (bytes > 100) /* Bytes is not 0 */
pctzero = (evenzero + oddzero) / (bytes / 100);
else
pctzero = ((evenzero + oddzero) * 100) / bytes;
#endif /* UNICODE */
#ifdef DEBUG
if (deblog) { /* If debugging, dump statistics */
debug(F101,"scanfile c0controls ","",c0controls);
debug(F101,"scanfile c0noniso ","",c0noniso);
debug(F101,"scanfile c1controls ","",c1controls);
debug(F101,"scanfile eightbit ","",eightbit);
#ifdef UNICODE
debug(F101,"scanfile crlf ","",crlf);
debug(F101,"scanfile lfnul ","",lfnul);
debug(F101,"scanfile notutf8 ","",notutf8);
debug(F101,"scanfile evenzero ","",evenzero);
debug(F101,"scanfile oddzero ","",oddzero);
debug(F101,"scanfile even/odd ","",(evenzero / (oddzero + 1)));
debug(F101,"scanfile odd/even ","",(oddzero / (evenzero + 1)));
debug(F101,"scanfile pctzero ","",pctzero);
#endif /* UNICODE */
#ifdef COMMENT
#ifdef EVENMAX
debug(F101,"scanfile oddmax ","",oddmax);
debug(F101,"scanfile oddmaxbyte ","",oddmaxbyte);
debug(F101,"scanfile evenmax ","",evenmax);
debug(F101,"scanfile evenmaxbyte","",evenmaxbyte);
#endif /* EVENMAX */
#endif /* COMMENT */
debug(F101,"scanfile runmax ","",runmax);
}
#endif /* DEBUG */
#ifdef UNICODE
x = eightbit ? bytes / 20 : bytes / 4; /* For UCS-2... */
if (runmax > 2) { /* File has run of more than 2 NULs */
debug(F100,"scanfile BIN runmax","",0);
rc = FT_BIN; /* so it can't be any kind of text. */
goto xscanfile;
} else if (rc == FT_UCS2 || (rc == FT_UTF8 && runmax == 0)) {
goto xscanfile; /* File starts with a BOM */
} else if (eightbit > 0 && !notutf8) { /* File has 8-bit data */
if (runmax > 0) { /* and runs of NULs */
debug(F100,"scanfile BIN (nnUTF8) runmax","",0);
rc = FT_BIN; /* UTF-8 doesn't have NULs */
} else { /* No NULs */
debug(F100,"scanfile UTF8 (nnUTF8 + runmax == 0)","",0);
rc = FT_UTF8; /* and not not UTF-8, so is UTF-8 */
}
goto xscanfile;
}
/*
For UCS-2 detection, see if the text contains lines delimited by
ASCII controls and containing spaces, ASCII digits, or other ASCII
characters, thus forcing the presence of a certain percentage of zero bytes.
For this purpose require 20% zero bytes, with at least six times as many
in even (odd) positions as in odd (even) positions.
*/
if ((evenzero >= x && oddzero == 0) ||
((((evenzero / (oddzero + 1)) > 6) && (pctzero > 20)) &&
(crlf == 0) &&
(lfnul > 1))
) {
debug(F100,"scanfile UCS2 noBOM BE (even/oddzero)","",0);
rc = FT_UCS2;
val = 0;
} else if ((evenzero == 0 && oddzero >= x) ||
((((oddzero / (evenzero + 1)) > 6) && (pctzero > 20)) &&
(crlf == 0) &&
(lfnul > 1))
) {
debug(F100,"scanfile UCS2 noBOM LE (even/oddzero)","",0);
rc = FT_UCS2;
val = 1;
#ifdef COMMENT
#ifdef EVENMAX
/*
If the tests above fail, we still might have UCS-2 if there are significant
runs of identical bytes in alternating positions, but only if it also has
unusual C0 controls (otherwise we'd pick up hex files here). NOTE: We
don't actually do this -- EVENMAX is not defined (see comments above at
first occurrence of EVENMAX).
*/
} else if (c0noniso && evenmax > bytes / 4) {
debug(F100,"scanfile UCS2 BE (evenmax)","",0);
rc = FT_UCS2;
val = 0;
} else if (c0noniso && oddmax > bytes / 4) {
debug(F100,"scanfile UCS2 LE (evenmax)","",0);
rc = FT_UCS2;
val = 1;
#endif /* EVENMAX */
#endif /* COMMENT */
}
/*
It seems to be UCS-2 but let's be more certain since there is no BOM...
If the number of 7- and 8-bit characters is approximately equal, it might
be a compressed file. In this case we decide based on the name.
*/
if (rc == FT_UCS2) {
if (eightbit > 0) {
int j, k;
j = (c1controls * 100) / (c0controls + 1);
debug(F101,"scanfile c1/c0 ","",j);
k = (bytes * 100) / eightbit;
debug(F101,"scanfile pct 8bit ","",k);
if (k > 40 && k < 60 && j > 60) {
if (ckmatch("{*.Z,*.gz,*.zip,*.ZIP}",name,1,1)) {
debug(F110,"scanfile 8-bit BIN compressed",name,0);
rc = FT_BIN;
goto xscanfile;
}
}
}
/* Small file - not enough evidence unless ... */
if (bytes < 100) {
if (oddzero != 0 && evenzero != 0) {
debug(F100,"scanfile small UCS2 doubtful","",0);
rc = FT_BIN;
goto xscanfile;
} else if (oddzero == 0 && evenzero == 0) {
rc = eightbit ? FT_8BIT : FT_7BIT;
}
}
goto xscanfile; /* Seems to be UCS-2 */
}
/* If none of the above, it's probably not Unicode. */
if (!eightbit) { /* It's 7-bit */
if (c0controls) { /* This would be strange */
if ((c0noniso > 0) && (txtcz == 0)) {
debug(F100,"scanfile 7-bit BIN (c0coniso)","",0);
rc = FT_BIN;
} else {
debug(F100,"scanfile 7-bit ISO2022 TEXT (no c0noniso)","",0);
rc = FT_7BIT;
}
} else { /* 7-bit text */
debug(F100,"scanfile 7-bit TEXT (no c0controls)","",0);
rc = FT_7BIT;
}
} else if (!c0noniso || txtcz) { /* 8-bit text */
debug(F100,"scanfile 8-bit TEXT (no c0noniso)","",0);
rc = FT_8BIT;
val = c1controls ? 1 : 0;
} else { /* 8-bit binary */
debug(F100,"scanfile 8-bit BIN (c0noniso)","",0);
rc = FT_BIN;
}
#else /* !UNICODE */
if (c0noniso) {
debug(F100,"scanfile 8-bit BIN (c0noniso)","",0);
rc = FT_BIN;
} else if (eightbit) {
debug(F100,"scanfile 8-bit TEXT (no c0noniso)","",0);
rc = FT_8BIT;
val = c1controls ? 1 : 0;
} else {
debug(F100,"scanfile 7-bit TEXT (no c0noniso)","",0);
rc = FT_7BIT;
}
#endif /* UNICODE */
xscanfile:
if (flag) *flag = val;
debug(F101,"scanfile result ","",rc);
return(rc);
}
/* F I L E S E L E C T -- Select this file for sending */
int
#ifdef CK_ANSIC
fileselect(
char *f, char *sa, char *sb, char *sna, char *snb,
long minsiz, long maxsiz,
int nbu, int nxlist,
char ** xlist
)
#else
fileselect(f,sa,sb,sna,snb,minsiz,maxsiz,nbu,nxlist,xlist)
char *f,*sa,*sb,*sna,*snb; long minsiz,maxsiz; int nbu,nxlist; char ** xlist;
#endif /* CK_ANSIC */
/* fileselect */ {
char *fdate;
int n;
long z;
if (!sa) sa = "";
if (!sb) sb = "";
if (!sna) sna = "";
if (!snb) snb = "";
#ifdef CKSYMLINK
#ifndef NOICP
#ifndef NOXFER
if (nolinks) {
long zz;
zz = zgetfs(f);
debug(F111,"fileselect NOLINKS zgetfs",f,zz);
if (zz < 0L)
return(0);
debug(F111,"fileselect NOLINKS zgfs_link",f,zgfs_link);
if (zgfs_link)
return(0);
}
#endif /* NOXFER */
#endif /* NOICP */
#endif /* CKSYMLINK */
debug(F110,"fileselect",f,0);
if (*sa || *sb || *sna || *snb) {
fdate = zfcdat(f); /* Date/time of this file */
if (!fdate) fdate = "";
n = strlen(fdate);
debug(F111,"fileselect fdate",fdate,n);
if (n != 17) /* Failed to get it */
return(1);
/* /AFTER: */
if (sa[0] && (strcmp(fdate,(char *)sa) <= 0)) {
debug(F110,"fileselect sa",sa,0);
/* tlog(F110,"Skipping (too old)",f,0); */
return(0);
}
/* /BEFORE: */
if (sb[0] && (strcmp(fdate,(char *)sb) >= 0)) {
debug(F110,"fileselect sb",sb,0);
/* tlog(F110,"Skipping (too new)",f,0); */
return(0);
}
/* /NOT-AFTER: */
if (sna[0] && (strcmp(fdate,(char *)sna) > 0)) {
debug(F110,"fileselect sna",sna,0);
/* tlog(F110,"Skipping (too new)",f,0); */
return(0);
}
/* /NOT-BEFORE: */
if (snb[0] && (strcmp(fdate,(char *)snb) < 0)) {
debug(F110,"fileselect snb",snb,0);
/* tlog(F110,"Skipping (too old)",f,0); */
return(0);
}
}
if (minsiz > -1L || maxsiz > -1L) { /* Smaller or larger */
z = zchki(f); /* Get size */
debug(F101,"fileselect filesize","",z);
if (z < 0)
return(1);
if ((minsiz > -1L) && (z >= minsiz)) {
debug(F111,"fileselect minsiz skipping",f,minsiz);
/* tlog(F111,"Skipping (too big)",f,z); */
return(0);
}
if ((maxsiz > -1L) && (z <= maxsiz)) {
debug(F111,"fileselect maxsiz skipping",f,maxsiz);
/* tlog(F110,"Skipping (too small)",f,0); */
return(0);
}
}
if (nbu) { /* Skipping backup files? */
if (ckmatch(
#ifdef CKREGEX
"*.~[0-9]*~" /* Not perfect but close enough. */
#else
"*.~*~" /* Less close. */
#endif /* CKREGEX */
,f,filecase,1)) {
debug(F110,"fileselect skipping backup",f,0);
return(0);
}
}
for (n = 0; xlist && n < nxlist; n++) {
if (!xlist[n]) {
debug(F101,"fileselect xlist empty",0,n);
break;
}
if (ckmatch(xlist[n],f,filecase,1)) {
debug(F111,"fileselect xlist",xlist[n],n);
debug(F110,"fileselect skipping",f,0);
return(0);
}
}
if (xfiletype > -1) {
n = scanfile(f,NULL,nscanfile);
if (n < 0) {
n = binary ? 1 : 0;
} else {
n = (n == FT_BIN) ? 1 : 0;
}
if (n != xfiletype)
return(0);
}
debug(F110,"fileselect selecting",f,0);
return(1);
}
#ifdef TCPSOCKET
#ifdef NT
extern int WSASafeToCancel;
#endif /* NT */
#endif /* TCPSOCKET */
VOID
setflow() {
extern int flow, autoflow, mdmtyp, cxtype, cxflow[];
#ifndef NODIAL
extern int dialcapas, dialfc;
extern MDMINF * modemp[];
MDMINF * p = NULL;
long bits = 0;
#endif /* NODIAL */
debug(F101,"setflow autoflow","",autoflow);
/* #ifdef COMMENT */
/* WHY WAS THIS COMMENTED OUT? */
if (!autoflow) /* Only if FLOW is AUTO */
return;
/* #endif */ /* COMMENT */
debug(F101,"setflow local","",local);
debug(F101,"setflow network","",network);
debug(F101,"setflow cxtype","",cxtype);
#ifdef TN_COMPORT
if (network && istncomport()) {
flow = cxflow[CXT_MODEM];
debug(F101,"setflow TN_COMPORT flow","",flow);
return;
}
#endif /* TN_COMPORT */
if (network || !local || cxtype == CXT_DIRECT) {
flow = cxflow[cxtype]; /* Set appropriate flow control */
debug(F101,"setflow flow","",flow);
return;
}
if (cxtype != CXT_MODEM) /* Connection type should be modem */
return;
#ifndef NODIAL
bits = dialcapas; /* Capability bits */
if (!bits) { /* No bits? */
p = modemp[mdmtyp]; /* Look in modem info structure */
if (p)
bits = p->capas;
}
if (dialfc == FLO_AUTO) { /* If DIAL flow is AUTO */
#ifdef CK_RTSCTS /* If we can do RTS/CTS flow control */
if (bits & CKD_HW) /* and modem can do it too */
flow = FLO_RTSC; /* then switch to RTS/CTS */
else /* otherwise */
flow = FLO_XONX; /* use Xon/Xoff. */
#else
#ifndef NEXT
#ifndef IRIX
flow = FLO_XONX; /* Use Xon/Xoff. */
#endif /* IRIX */
#endif /* NEXT */
#endif /* CK_RTSCTS */
}
#endif /* NODIAL */
debug(F101,"setflow modem flow","",flow);
return;
}
#ifndef NOLOCAL
#ifdef CK_TRIGGER
/* A U T O E X I T C H K -- Check for CONNECT-mode trigger string */
/*
Returns -1 if trigger not found, or else the trigger index, 0 or greater.
(Replace with fancier and more efficient matcher later...)
NOTE: to prevent unnecessary function call overhead, call this way:
x = tt_trigger[0] ? autoexitchk(c) : -1;
*/
int
#ifdef CK_ANSIC
autoexitchk(CHAR c)
#else
autoexitchk(c) CHAR c;
#endif /* CK_ANSIC */
/* autoexitchk */ {
extern CHAR * tt_trmatch[];
extern char * tt_trigger[];
int i;
for (i = 0; i < TRIGGERS; i++) {
if (!tt_trigger[i]) { /* No more triggers in list */
break;
} else if (*tt_trigger[i]) {
if (!tt_trmatch[i]) /* Just starting? */
tt_trmatch[i] = (CHAR *)tt_trigger[i]; /* Set match pointer */
if (c == *tt_trmatch[i]) { /* Compare this character */
tt_trmatch[i]++; /* It matches */
if (!*tt_trmatch[i]) { /* End of match string? */
tt_trmatch[i] = (CHAR *) tt_trigger[i]; /* Yes, rewind, */
debug(F101,"autoexitchk",tt_trigger[i],i); /* log, */
return(i); /* and return success */
}
} else /* No match */
tt_trmatch[i] = (CHAR *) tt_trigger[i]; /* Rewind match string */
} /* and go on the next match string */
}
return(-1); /* No match found */
}
#endif /* CK_TRIGGER */
#ifndef NOSHOW
/* S H O M D M -- Show modem signals */
VOID
shomdm() {
/*
Note use of "\r\n" to make sure this report prints right, even when
called during CONNECT mode.
*/
int y;
y = ttgmdm();
switch (y) {
case -3: printf(
"Modem signals unavailable in this version of Kermit\r\n");
break;
case -2: printf("No modem control for this device\r\n"); break;
case -1: printf("Modem signals unavailable\r\n"); break;
default:
#ifndef MAC
printf(
" Carrier Detect (CD): %s\r\n",(y & BM_DCD) ? "On": "Off");
printf(
" Dataset Ready (DSR): %s\r\n",(y & BM_DSR) ? "On": "Off");
#endif /* MAC */
printf(
" Clear To Send (CTS): %s\r\n",(y & BM_CTS) ? "On": "Off");
#ifndef STRATUS
#ifndef MAC
printf(
" Ring Indicator (RI): %s\r\n",(y & BM_RNG) ? "On": "Off");
#endif /* MAC */
printf(
" Data Terminal Ready (DTR): %s\r\n",
#ifdef NT
"(unknown)"
#else /* NT */
(y & BM_DTR) ? "On": "Off"
#endif /* NT */
);
#ifndef MAC
printf(
" Request To Send (RTS): %s\r\n",
#ifdef NT
"(unknown)"
#else /* NT */
(y & BM_RTS) ? "On": "Off"
#endif /* NT */
);
#endif /* MAC */
#endif /* STRATUS */
}
#ifdef BETADEBUG
#ifdef CK_TAPI
if (tttapi && !tapipass) {
LPDEVCFG lpDevCfg = NULL;
LPCOMMCONFIG lpCommConfig = NULL;
LPMODEMSETTINGS lpModemSettings = NULL;
DCB * lpDCB = NULL;
if (cktapiGetModemSettings(&lpDevCfg,&lpModemSettings,
&lpCommConfig,&lpDCB)) {
printf("\n");
cktapiDisplayModemSettings(lpDevCfg,lpModemSettings,
lpCommConfig,lpDCB);
}
}
#endif /* CK_TAPI */
#endif /* BETADEBUG */
}
#endif /* NOSHOW */
#endif /* NOLOCAL */
#ifndef NOXFER
/* S D E B U -- Record spar results in debugging log */
VOID
sdebu(len) int len; {
debug(F111,"spar: data",(char *) rdatap,len);
debug(F101," spsiz ","", spsiz);
debug(F101," timint","",timint);
debug(F101," npad ","", npad);
debug(F101," padch ","", padch);
debug(F101," seol ","", seol);
debug(F101," ctlq ","", ctlq);
debug(F101," ebq ","", ebq);
debug(F101," ebqflg","",ebqflg);
debug(F101," bctr ","", bctr);
debug(F101," rptq ","", rptq);
debug(F101," rptflg","",rptflg);
debug(F101," lscapu","",lscapu);
debug(F101," atcapu","",atcapu);
debug(F101," lpcapu","",lpcapu);
debug(F101," swcapu","",swcapu);
debug(F101," wslotn","", wslotn);
debug(F101," whatru","", whatru);
}
/* R D E B U -- Debugging display of rpar() values */
VOID
rdebu(d,len) CHAR *d; int len; {
debug(F111,"rpar: data",d,len);
debug(F101," rpsiz ","", xunchar(d[0]));
debug(F101," rtimo ","", rtimo);
debug(F101," mypadn","",mypadn);
debug(F101," mypadc","",mypadc);
debug(F101," eol ","", eol);
debug(F101," ctlq ","", ctlq);
debug(F101," sq ","", sq);
debug(F101," ebq ","", ebq);
debug(F101," ebqflg","",ebqflg);
debug(F101," bctr ","", bctr);
debug(F101," rptq ","", d[8]);
debug(F101," rptflg","",rptflg);
debug(F101," capas ","", capas);
debug(F101," bits ","",d[capas]);
debug(F101," lscapu","",lscapu);
debug(F101," atcapu","",atcapu);
debug(F101," lpcapu","",lpcapu);
debug(F101," swcapu","",swcapu);
debug(F101," wslotr","", wslotr);
debug(F101," rpsiz(extended)","",rpsiz);
}
#ifdef COMMENT
/* C H K E R R -- Decide whether to exit upon a protocol error */
VOID
chkerr() {
if (backgrd && !server) fatal("Protocol error");
}
#endif /* COMMENT */
#endif /* NOXFER */
/* F A T A L -- Fatal error message */
VOID
fatal(msg) char *msg; {
extern int initflg;
static int initing = 0;
if (!msg) msg = "";
debug(F111,"fatal",msg,initflg);
if (!initflg) { /* If called from prescan */
if (initing) /* or called from sysinit() */
exit(253);
initing = 1;
sysinit();
}
debug(F111,"fatal",msg,xitsta);
tlog(F110,"Fatal:",msg,0L);
#ifdef VMS
if (strncmp(msg,"%CKERMIT",8))
conol("%CKERMIT-E-FATAL, ");
conoll(msg);
#else /* !VMS */
conoll(msg);
#endif /* VMS */
#ifdef OS2
#ifndef NOXFER
if (xfrbel) {
bleep(BP_FAIL);
sleep(1);
bleep(BP_FAIL);
}
#endif /* NOXFER */
#endif /* OS2 */
doexit(BAD_EXIT,xitsta | 1); /* Exit indicating failure */
}
#ifndef NOXFER
/* B L D L E N -- Make length-encoded copy of string */
char *
bldlen(str,dest) char *str, *dest; {
int len;
len = (int)strlen(str);
if (len > 94)
*dest = SP;
else
*dest = (char) tochar(len);
strcpy(dest+1,str); /* Checked below in setgen() */
return(dest+len+1);
}
/* S E T G E N -- Construct a generic command */
/*
Call with Generic command character followed by three string arguments.
Trailing strings are allowed to be empty (""). Each string except the last
non-empty string must be less than 95 characters long. The final nonempty
string is allowed to be longer.
*/
CHAR
#ifdef CK_ANSIC
setgen(char type, char * arg1, char * arg2, char * arg3)
#else
setgen(type,arg1,arg2,arg3) char type, *arg1, *arg2, *arg3;
#endif /* CK_ANSIC */
/* setgen */ {
char *upstr, *cp;
#ifdef DYNAMIC
if (!cmdstr)
if (!(cmdstr = malloc(MAXSP + 1)))
fatal("setgen: can't allocate memory");
#endif /* DYNAMIC */
cp = cmdstr;
*cp++ = type;
*cp = NUL;
if (!arg1) arg1 = "";
if (!arg2) arg2 = "";
if (!arg3) arg3 = "";
if (((int)strlen(arg1)+(int)strlen(arg2)+(int)strlen(arg3)+4) < MAXSP) {
if (*arg1 != NUL) {
upstr = bldlen(arg1,cp);
if (*arg2 != NUL) {
upstr = bldlen(arg2,upstr);
if (*arg3 != NUL) bldlen(arg3,upstr);
}
}
cmarg = cmdstr;
debug(F110,"setgen",cmarg,0);
return('g');
}
return('E');
}
#endif /* NOXFER */
#ifndef NOMSEND
static char *mgbufp = NULL;
/* F N P A R S E -- */
/*
Argument is a character string containing one or more filespecs.
This function breaks the string apart into an array of pointers, one
to each filespec, and returns the number of filespecs. Used by server
when it receives a GET command to allow it to process multiple file
specifications in one transaction. Sets cmlist to point to a list of
file pointers, exactly as if they were command line arguments.
This version of fnparse treats spaces as filename separators. If your
operating system allows spaces in filenames, you'll need a different
separator.
This version of fnparse mallocs a string buffer to contain the names. It
cannot assume that the string that is pointed to by the argument is safe.
*/
int
fnparse(string) char *string; {
char *p, *s, *q;
int r = 0, x; /* Return code */
#ifdef RECURSIVE
debug(F111,"fnparse",string,recursive);
#endif /* RECURSIVE */
if (mgbufp) free(mgbufp); /* Free this from last time. */
mgbufp = malloc((int)strlen(string)+2);
if (!mgbufp) {
debug(F100,"fnparse malloc error","",0);
return(0);
}
#ifndef NOICP
#ifndef NOSPL
ckstrncpy(fspec,string,fspeclen); /* Make copy for \v(filespec) */
#endif /* NOSPL */
#endif /* NOICP */
s = string; /* Input string */
p = q = mgbufp; /* Point to the copy */
r = 0; /* Initialize our return code */
while (*s == SP || *s == HT) /* Skip leading spaces and tabs */
s++;
for (x = strlen(s); /* Strip trailing spaces */
(x > 1) && (s[x-1] == SP || s[x-1] == HT);
x--)
s[x-1] = NUL;
while (1) { /* Loop through rest of string */
if (*s == CMDQ) { /* Backslash (quote character)? */
if ((x = xxesc(&s)) > -1) { /* Go interpret it. */
*q++ = (char) x; /* Numeric backslash code, ok */
} else { /* Just let it quote next char */
s++; /* get past the backslash */
*q++ = *s++; /* deposit next char */
}
continue;
} else if (*s == SP || *s == NUL) { /* Unquoted space or NUL? */
*q++ = NUL; /* End of output filename. */
msfiles[r] = p; /* Add this filename to the list */
debug(F111,"fnparse",msfiles[r],r);
r++; /* Count it */
if (*s == NUL) break; /* End of string? */
while (*s == SP) s++; /* Skip repeated spaces */
p = q; /* Start of next name */
continue;
} else *q++ = *s; /* Otherwise copy the character */
s++; /* Next input character */
}
debug(F101,"fnparse r","",r);
msfiles[r] = ""; /* Put empty string at end of list */
cmlist = msfiles;
return(r);
}
#endif /* NOMSEND */
char * /* dbchr() for DEBUG SESSION */
dbchr(c) int c; {
static char s[8];
char *cp = s;
c &= 0xff;
if (c & 0x80) { /* 8th bit on */
*cp++ = '~';
c &= 0x7f;
}
if (c < SP) { /* Control character */
*cp++ = '^';
*cp++ = (char) ctl(c);
} else if (c == DEL) {
*cp++ = '^';
*cp++ = '?';
} else { /* Printing character */
*cp++ = (char) c;
}
*cp = '\0'; /* Terminate string */
cp = s; /* Return pointer to it */
return(cp);
}
/* C K H O S T -- Get name of local host (where C-Kermit is running) */
/*
Call with pointer to buffer to put hostname in, and length of buffer.
Copies hostname into buffer on success, puts null string in buffer on
failure.
*/
#ifdef BSD44
#define BSD4
#undef ATTSV
#endif /* BSD44 */
#ifdef SVORPOSIX
#ifndef BSD44
#ifndef apollo
#include <sys/utsname.h>
#endif /* apollo */
#endif /* BSD44 */
#else
#ifdef BELLV10
#include <utsname.h>
#endif /* BELLV10 */
#endif /* SVORPOSIX*/
#ifdef CKSYSLOG
extern char uidbuf[], * clienthost;
#endif /* CKSYSLOG */
VOID
ckhost(vvbuf,vvlen) char * vvbuf; int vvlen; {
#ifndef NOPUSH
extern int nopush;
#ifndef NOSERVER
extern int en_hos;
#endif /* NOSERVER */
#endif /* NOPUSH */
#ifdef pdp11
*vvbuf = NUL;
#else /* Everything else - rest of this routine */
char *g;
int havefull = 0;
#ifdef VMS
int x;
#endif /* VMS */
#ifdef SVORPOSIX
#ifndef BSD44
#ifndef _386BSD
#ifndef APOLLOSR10
struct utsname hname;
#endif /* APOLLOSR10 */
#endif /* _386BSD */
#endif /* BSD44 */
#endif /* SVORPOSIX */
#ifdef datageneral
int ac0 = (char *) vvbuf, ac1 = -1, ac2 = 0;
#endif /* datageneral */
#ifndef NOPUSH
if (getenv("CK_NOPUSH")) { /* No shell access allowed */
nopush = 1; /* on this host... */
#ifndef NOSERVER
en_hos = 0;
#endif /* NOSERVER */
}
#endif /* NOPUSH */
*vvbuf = NUL; /* How let's get our host name ... */
#ifndef BELLV10 /* Does not have gethostname() */
#ifndef OXOS
#ifdef SVORPOSIX
#ifdef APOLLOSR10
ckstrncpy(vvbuf,"Apollo",vvlen);
#else
#ifdef BSD44
if (gethostname(vvbuf,vvlen) < 0)
*vvbuf = NUL;
#else
#ifdef _386BSD
if (gethostname(vvbuf,vvlen) < 0) *vvbuf = NUL;
#else
#ifdef QNX
#ifdef TCPSOCKET
if (gethostname(vvbuf,vvlen) < 0) *vvbuf = NUL;
#else
if (uname(&hname) > -1) ckstrncpy(vvbuf,hname.nodename,vvlen);
#endif /* TCPSOCKET */
#else /* SVORPOSIX but not _386BSD or BSD44 */
#ifdef __ia64__
if (uname(&hname) > -1) ckstrncpy(vvbuf,hname.nodename,vvlen);
#else
if (uname(&hname) > -1) {
char * p;
p = hname.nodename;
#ifdef TCPSOCKET
#ifndef NOCKGETFQHOST
if (!ckstrchr(p,'.'))
p = (char *)ckgetfqhostname(p);
#endif /* NOCKGETFQHOST */
#endif /* TCPSOCKET */
if (!p) p = "";
if (!*p) p = "(unknown)";
ckstrncpy(vvbuf,p,vvlen);
}
#endif /* __ia64__ */
#endif /* QNX */
#endif /* _386BSD */
#endif /* BSD44 */
#endif /* APOLLOSR10 */
#else /* !SVORPOSIX */
#ifdef BSD4
if (gethostname(vvbuf,vvlen) < 0) *vvbuf = NUL;
#else /* !BSD4 */
#ifdef VMS
g = getenv("SYS$NODE");
if (g) ckstrncpy(vvbuf,g,vvlen);
x = (int)strlen(vvbuf);
if (x > 1 && vvbuf[x-1] == ':' && vvbuf[x-2] == ':') vvbuf[x-2] = NUL;
#else
#ifdef datageneral
if (sys($HNAME,&ac0,&ac1,&ac2) == 0) /* successful */
vvlen = ac2 + 1; /* enh - have to add one */
#else
#ifdef OS2 /* OS/2 */
g = os2_gethostname();
if (g) ckstrncpy(vvbuf,g,vvlen);
#else /* OS2 */
#ifdef OSK
#ifdef TCPSOCKET
if (gethostname(vvbuf, vvlen) < 0) *vvbuf = NUL;
#endif /* TCPSOCKET */
#endif /* OSK */
#endif /* OS2 */
#endif /* datageneral */
#endif /* VMS */
#endif /* BSD4 */
#endif /* SVORPOSIX */
#else /* OXOS */
/* If TCP/IP is not installed, gethostname() fails, use uname() */
if (gethostname(vvbuf,vvlen) < 0) {
if (uname(&hname) > -1)
ckstrncpy(vvbuf,hname.nodename,vvlen);
else
*vvbuf = NUL;
}
#endif /* OXOS */
#endif /* BELLV10 */
if (*vvbuf == NUL) { /* If it's still empty */
g = getenv("HOST"); /* try this */
if (g) ckstrncpy(vvbuf,g,vvlen);
}
vvbuf[vvlen-1] = NUL; /* Make sure result is terminated. */
#endif /* pdp11 */
}
#ifdef BSD44
#undef BSD4
#define ATTSV
#endif /* BSD44 */
/*
A S K M O R E -- Poor person's "more".
Returns 0 if no more, 1 if more wanted.
*/
int
askmore() {
char c;
int rv, cx;
#ifdef IKSD
extern int timelimit;
#endif /* IKSD */
#ifdef IKSDCONF
extern int iksdcf;
#endif /* IKSDCONF */
#ifdef CK_APC
extern int apcstatus, apcactive;
#endif /* CK_APC */
#ifdef NOICP
return(1);
#else
if (!xaskmore)
return(1);
#ifdef IKSDCONF
if (inserver && !iksdcf)
return(1);
#endif /* IKSDCONF */
#ifdef CK_APC
if (apcactive == APC_LOCAL ||
(apcactive == APC_REMOTE && (apcstatus & APC_NOINP)))
return(1);
#endif /* CK_APC */
#ifdef VMS
if (batch)
return(1);
#else
#ifdef UNIX
if (backgrd)
return(1);
#endif /* UNIX */
#endif /* VMS */
#ifndef VMS
concb((char)escape); /* Force CBREAK mode. */
#endif /* VMS */
rv = -1;
while (rv < 0) {
#ifndef OS2
printf("more? ");
#ifdef UNIX
#ifdef NOSETBUF
fflush(stdout);
#endif /* NOSETBUF */
#endif /* UNIX */
#else
printf("more? ");
fflush(stdout);
#endif /* OS2 */
#ifdef IKSD
if (inserver) {
cx = cmdgetc(timelimit);
if (cx < -1 && timelimit) {
printf("\n?IKS idle timeout - Goodbye.\n");
doexit(GOOD_EXIT,0);
} else if (cx == -1) { /* Connection lost */
doexit(BAD_EXIT,0);
}
c = (char) cx;
} else {
#endif /* IKSD */
#ifdef VMS
conbin((char)escape); /* Protect against Ctrl-Z */
cx = coninc(0);
concb((char)escape);
#else
cx = cmdgetc(0);
#endif /* VMS */
debug(F101,"askmore cmdgetc","",cx);
if (cx == EOF) {
debug(F100,"askmore EOF","",0);
#ifdef VMS
c = '\032';
#else
c = 'n';
#endif /* VMS */
} else {
c = (char)cx;
}
debug(F101,"askmore c","",c);
#ifdef IKSD
}
#endif /* IKSD */
switch (c) {
/* Yes */
case 'p': case 'P': case 'g': case 'G': /* Proceed or Go */
xaskmore = 0;
/* fall thru on purpose */
case SP: case 'y': case 'Y': case 012: case 015:
#ifdef OSK
write(1, "\015 \015", sizeof "\015 \015" - 1);
#else
printf("\015 \015");
#endif /* OSK */
rv = 1;
break;
/* No */
case 'n': case 'N': case 'q': case 'Q':
#ifdef OSK
printf("\n");
#else
printf("\015\012");
#endif /* OSK */
rv = 0;
break;
case '\003':
case '\004':
case '\032':
#ifdef OSK
printf("^%c...\n", (c + 0100));
#else
printf("^%c...\015\012", (c + 0100));
#endif /* OSK */
rv = 0;
break;
/* Invalid answer */
default:
debug(F111,"askmore","invalid answer",c);
printf("Y or space-bar for yes, N for no, G to show the rest\n");
continue;
}
#ifdef OS2
printf("\r \r");
fflush(stdout);
#endif /* OS2 */
}
return(rv);
#endif /* NOICP */
}
/* T R A P -- Terminal interrupt handler */
SIGTYP
#ifdef CK_ANSIC
trap(int sig)
#else
trap(sig) int sig;
#endif /* CK_ANSIC */
/* trap */ {
extern int b_save, f_save;
#ifndef NOICP
extern int timelimit;
#endif /* NOICP */
#ifdef OS2
extern unsigned long startflags;
#ifndef NOSETKEY
extern int os2gks;
#endif /* NOSETKEY */
int i;
#endif /* OS2 */
#ifndef NOSPL
extern int i_active, instatus;
#endif /* NOSPL */
#ifdef VMS
int i; FILE *f;
#endif /* VMS */
extern int zchkod, zchkid;
#ifndef NOSPL
extern int unkmacro;
#endif /* NOSPL */
debok = 1;
#ifdef NTSIG
connoi();
#endif /* NTSIG */
#ifdef __EMX__
signal(SIGINT, SIG_ACK);
#endif
#ifdef GEMDOS
/* GEM is not reentrant, no i/o from interrupt level */
cklongjmp(cmjbuf,1); /* Jump back to parser now! */
#endif /* GEMDOS */
#ifdef DEBUG
if (deblog) {
if (sig == SIGINT)
debug(F101,"trap caught SIGINT","",sig);
else
debug(F101,"trap caught signal","",sig);
}
#endif /* DEBUG */
#ifdef OS2
if ( sig == SIGBREAK && (startflags & 128) ) {
debug(F101,"trap ignoring SIGBREAK","",sig);
return;
}
#endif /* OS2 */
#ifndef NOICP
timelimit = 0; /* In case timed ASK interrupted */
#ifndef NOSPL
unkmacro = 0; /* Or ON_UNKNOWN_MACRO interrupted.. */
#endif /* NOSPL */
#endif /* NOICP */
zchkod = 0; /* Or file expansion interrupted... */
zchkid = 0;
interrupted = 1;
if (what & W_CONNECT) { /* Are we in CONNECT mode? */
/*
The HP workstation Reset key sends some kind of ueber-SIGINT that can not
be SIG_IGNored, so we wind up here somehow (even though this is *not* the
current SIGINT handler). Just return.
*/
debug(F101,"trap: SIGINT caught during CONNECT","",sig);
SIGRETURN;
}
#ifndef NOSPL
if (i_active) { /* INPUT command was active? */
i_active = 0; /* Not any more... */
instatus = INP_UI; /* INPUT status = User Interrupted */
}
#endif /* NOSPL */
#ifndef NOXFER
ftreset(); /* Restore global protocol settings */
binary = b_save; /* Then restore these */
fncnv = f_save;
bye_active = 0;
diractive = 0;
cdactive = 0;
#endif /* NOXFER */
zclose(ZIFILE); /* If we were transferring a file, */
zclose(ZOFILE); /* close it. */
#ifndef NOICP
cmdsquo(cmd_quoting); /* If command quoting was turned off */
#ifdef CKLEARN
{
extern FILE * learnfp;
extern int learning;
if (learnfp) {
fclose(learnfp);
learnfp = NULL;
learning = 0;
}
}
#endif /* CKLEARN */
#endif /* NOICP */
#ifdef CK_APC
delmac("_apc_commands",1);
apcactive = APC_INACTIVE;
#endif /* CK_APC */
#ifdef VMS
/*
Fix terminal.
*/
if (ft_win) { /* If curses window open */
debug(F100,"^C trap() curses","",0);
xxscreen(SCR_CW,0,0L,""); /* Close it */
conres