Import ekermit-1.7 from

http://www.kermitproject.org/ftp/kermit/archives/ek17.tar

EK (Embedded Kermit, E-Kermit) is an implementation of the Kermit file
transfer protocol written in ANSI C and designed for embedding in
devices or firmware, use in realtime applications, or for construction
of DLLs and libraries.  A sample calling environment and i/o support are
provided for Unix.
This commit is contained in:
apb 2014-08-08 19:20:38 +00:00
parent f3b28c737c
commit a704a1616e
10 changed files with 3317 additions and 0 deletions

35
external/bsd/ekermit/dist/COPYING vendored Normal file
View File

@ -0,0 +1,35 @@
E-Kermit 1.7 -- Embedded Kermit
Author: Frank da Cruz
License: Revised 3-Clause BSD License
Copyright (C) 1995, 2011,
Trustees of Columbia University in the City of New York.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of Columbia University nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

33
external/bsd/ekermit/dist/cdefs.h vendored Normal file
View File

@ -0,0 +1,33 @@
#ifndef __CDEFS_H__
#define __CDEFS_H__
/*
By default, the internal routines of kermit.c are not static,
because this is not allowed in some embedded environments.
To have them declared static, define STATIC=static on the cc
command line.
*/
#ifdef XAC /* HiTech's XAC cmd line is small */
#define STATIC static
#else /* XAC */
#ifndef STATIC
#define STATIC
#endif /* STATIC */
#endif /* XAC */
/*
By default we assume the compiler supports unsigned char and
unsigned long. If not you can override these definitions on
the cc command line.
*/
#ifndef HAVE_UCHAR
typedef unsigned char UCHAR;
#endif /* HAVE_UCHARE */
#ifndef HAVE_ULONG
typedef unsigned long ULONG;
#endif /* HAVE_ULONG */
#ifndef HAVE_USHORT
typedef unsigned short USHORT;
#endif /* HAVE_USHORT */
#endif /* __CDEFS_H__ */

40
external/bsd/ekermit/dist/debug.h vendored Normal file
View File

@ -0,0 +1,40 @@
#ifndef NODEBUG /* NODEBUG inhibits debugging */
#ifndef DEBUG /* and if DEBUG not already defined */
#ifndef MINSIZE /* MINSIZE inhibits debugging */
#ifndef DEBUG
#define DEBUG
#endif /* DEBUG */
#endif /* MINSIZE */
#endif /* DEBUG */
#endif /* NODEBUG */
#ifdef DEBUG /* Debugging included... */
/* dodebug() function codes... */
#define DB_OPN 1 /* Open log */
#define DB_LOG 2 /* Write label+string or int to log */
#define DB_MSG 3 /* Write message to log */
#define DB_CHR 4 /* Write label + char to log */
#define DB_PKT 5 /* Record a Kermit packet in log */
#define DB_CLS 6 /* Close log */
void dodebug(int, UCHAR *, UCHAR *, long); /* Prototype */
/*
dodebug() is accessed throug a macro that:
. Coerces its args to the required types.
. Accesses dodebug() directly or thru a pointer according to context.
. Makes it disappear entirely if DEBUG not defined.
*/
#ifdef KERMIT_C
/* In kermit.c we debug only through a function pointer */
#define debug(a,b,c,d) \
if(*(k->dbf))(*(k->dbf))(a,(UCHAR *)b,(UCHAR *)c,(long)(d))
#else /* KERMIT_C */
/* Elsewhere we can call the debug function directly */
#define debug(a,b,c,d) dodebug(a,(UCHAR *)b,(UCHAR *)c,(long)(d))
#endif /* KERMIT_C */
#else /* Debugging not included... */
#define debug(a,b,c,d)
#endif /* DEBUG */

1619
external/bsd/ekermit/dist/kermit.c vendored Normal file

File diff suppressed because it is too large Load Diff

423
external/bsd/ekermit/dist/kermit.h vendored Normal file
View File

@ -0,0 +1,423 @@
#ifndef __KERMIT_H__
#define __KERMIT_H__
#define VERSION "1.7" /* Kermit module version number */
/*
kermit.h -- Symbol and struct definitions for embedded Kermit.
As of version 1.6 of 30 March 2011, E-Kermit is Open Source software under
the Revised 3-Clause BSD license which follows. E-Kermit 1.6 is identical
to version 1.51 except for the new license.
Author: Frank da Cruz.
Copyright (C) 1995, 2011,
Trustees of Columbia University in the City of New York.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of Columbia University nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef COMMENT /* COMMENT must not be defined */
#undef COMMENT /* (e.g. in a platform header file) */
#endif /* COMMENT */
/*
Never use NULL as a pointer. Always use 0 cast to the appropriate type,
for example: (UCHAR *)0. Reason: compiler might define NULL to be an
integer 0, and when passed to a function that wants a pointer, might wind
up with junk in the left half (if pointers wider than ints).
*/
#ifdef NULL
#undef NULL
#endif /* NULL */
/* Feature Selection */
/* XAC compiler for Philips XAG30 microprocessor */
/* See http://www.columbia.edu/kermit/em-apex.html */
#ifdef XAC /* XAC has tiny command line */
#define NO_LP /* Long packets too big for APF9 */
#define NO_SSW
#define NO_SCAN /* No file system */
#define FN_MAX 16
#define IBUFLEN 128
#define OBUFLEN 512
#else /* XAC */
#ifdef MINSIZE
#define NO_LP
#define NO_AT
#define NO_CTRLC
#define NO_SSW
#define NO_CRC
#define NO_SCAN
#endif /* MINSIZE */
#endif /* XAC */
#ifndef NO_LP
#define F_LP /* Long packets */
#endif /* NO_LP */
#ifndef NO_AT
#define F_AT /* Attribute packets */
#endif /* NO_AT */
#ifndef NO_CTRLC
#define F_CTRLC /* 3 consecutive Ctrl-C's to quit */
#endif /* NO_CTRLC */
#ifndef NO_SSW
#define F_SSW /* Simulated sliding windows */
#endif /* NO_SSW */
#ifndef NO_SCAN
#define F_SCAN /* Scan files for text/binary */
#endif /* NO_SCAN */
#ifndef NO_CRC /* Type 2 and 3 block checks */
#define F_CRC
#endif /* NO_CRC */
/*
F_SSW means we say (in negotiations) that we support sliding windows, but we
really don't. This allows the sender to send to us in a steady stream, and
works just fine except that error recovery is via go-back-to-n rather than
selective repeat.
*/
#ifdef COMMENT /* None of the following ... */
/*
+ = It works if selected
- = Partially implemented but doesn't work
0 = Not implemented
*/
#define F_TSW /* - True sliding windows */
#define F_LS /* 0 Locking shifts */
#define F_RS /* 0 Recovery */
#endif /* COMMENT */
#ifdef F_TSW /* F_SW is defined if either */
#ifndef F_SW /* F_SSW or F_TSW is defined... */
#define F_SW
#endif /* F_SW */
#endif /* F_TSW */
#ifdef F_SSW
#ifndef F_SW
#define F_SW
#endif /* F_SW */
#endif /* F_SSW */
/* Control character symbols */
#define NUL '\0' /* Null */
#define SOH 001 /* Start of header */
#define LF 012 /* Linefeed */
#define CR 015 /* Carriage Return */
#define SO 016 /* Shift Out */
#define SI 017 /* Shift In */
#define DLE 020 /* Datalink Escape */
#define ESC 033 /* Escape */
#define XON 021 /* XON */
#define XOFF 023 /* XOFF */
#define SP 040 /* Space */
#define DEL 0177 /* Delete (Rubout) */
#ifndef HAVE_VERSION /* k_data struct has version member */
#define HAVE_VERSION /* as of version 1.1 */
#endif /* HAVE_VERSION */
/* Main program return codes */
#define SUCCESS 0
#define FAILURE 1
/* Buffer lengths (can be overridden in platform.h) */
#ifndef RECVONLY
#ifndef IBUFLEN
#define IBUFLEN 1024 /* File input buffer size */
#endif /* IBUFLEN */
#endif /* RECVONLY */
#ifndef OBUFLEN
#define OBUFLEN 1024 /* File output buffer size */
#endif /* OBUFLEN */
#ifndef IDATALEN /* S/I packet data max length */
#define IDATALEN 32
#endif /* IDATALEN */
#ifndef FN_MAX
#define FN_MAX 1024 /* Maximum filename length */
#endif /* FN_MAX */
#define DATE_MAX 20 /* Max length for file date */
/* Protocol parameters */
#ifndef P_WSLOTS
#ifdef F_SW /* Window slots */
#ifdef F_TSW /* True window slots */
#define P_WSLOTS 4 /* Max is 4 */
#else
#define P_WSLOTS 31 /* Simulated max is 31 */
#endif /* F_TSW */
#else
#define P_WSLOTS 1
#endif /* F_SW */
#endif /* P_WSLOTS */
#ifndef P_PKTLEN /* Kermit max packet length */
#ifdef F_LP
#define P_PKTLEN 4096
#else
#define P_PKTLEN 94
#endif /* F_LP */
#endif /* P_PKTLEN */
/* Generic On/Off values */
#define OFF 0
#define ON 1
/* File Transfer Modes */
#define BINARY 0
#define TEXT 1
/* Parity values */
#define PAR_NONE 0
#define PAR_SPACE 1
#define PAR_EVEN 2
#define PAR_ODD 3
#define PAR_MARK 4
/* Protocol parameters */
#define P_S_TIMO 40 /* Timeout to tell other Kermit */
#define P_R_TIMO 5 /* Default timeout for me to use */
#define P_RETRY 10 /* Per-packet retramsit limit */
#define P_PARITY PAR_NONE /* Default parity */
#define P_R_SOH SOH /* Incoming packet start */
#define P_S_SOH SOH /* Outbound packet start */
#define P_R_EOM CR /* Incoming packet end */
#define P_S_EOM CR /* Outbound packet end */
/* Capability bits */
#define CAP_LP 2 /* Long packet capability */
#define CAP_SW 4 /* Sliding windows capability */
#define CAP_AT 8 /* Attribute packet capability */
#define CAP_RS 16 /* Resend capability */
#define CAP_LS 32 /* Locking shift capability */
/* Actions */
#define A_SEND 1 /* Send file(s) */
#define A_RECV 2 /* Receive file(s) */
/* Receive protocol states */
#define R_ERROR -1 /* Fatal protocol error */
#define R_NONE 0 /* Protocol not running */
#define R_WAIT 1 /* Waiting for S packet */
#define R_FILE 2 /* Waiting for F or B packet */
#define R_ATTR 3 /* Waiting for A or D packet */
#define R_DATA 4 /* Waiting for D or Z packet */
/* Send protocol states */
#define S_ERROR -1 /* Fatal protocol error */
#define S_NONE 10 /* Protocol not running */
#define S_INIT 11 /* Sent S packet */
#define S_FILE 12 /* Sent F packet */
#define S_ATTR 13 /* Sent A packet */
#define S_DATA 14 /* Sent D packet */
#define S_EOF 15 /* Sent Z packet */
#define S_EOT 16 /* Sent B packet */
/* What I'm Doing */
#define W_NOTHING 0
#define W_SEND 1
#define W_RECV 2
/* Kermit module function codes */
#define K_INIT 0 /* Initialize */
#define K_RUN 1 /* Run */
#define K_STATUS 2 /* Request status */
#define K_CONTINUE 3 /* Keep going */
#define K_QUIT 4 /* Quit immediately */
#define K_ERROR 5 /* Quit with error packet, msg given */
#define K_SEND 6 /* Begin Send sequence */
/* Kermit module return codes */
#define X_ERROR -1 /* Fatal error */
#define X_OK 0 /* OK, no action needed */
#define X_FILE 1 /* Filename received */
#define X_DATA 2 /* File data received */
#define X_DONE 3 /* Done */
#define X_STATUS 4 /* Status report */
/* Interruption codes */
#define I_FILE 1 /* Cancel file */
#define I_GROUP 2 /* Cancel group */
struct packet {
int len; /* Length */
short seq; /* Sequence number */
char typ; /* Type */
short rtr; /* Retry count */
UCHAR * dat; /* Pointer to data */
short flg; /* Flags */
};
struct k_data { /* The Kermit data structure */
UCHAR * version; /* Version number of Kermit module */
short remote; /* 0 = local, 1 = remote */
short xfermode; /* 0 = automatic, 1 = manual */
short binary; /* 0 = text, 1 = binary */
short state; /* Kermit protocol state */
short what; /* Action (send or receive) */
short s_first; /* Enocode at beginning of file */
short s_next; /* Encode lookahead byte */
short s_seq; /* Sequence number sent */
short r_seq; /* Sequence number received */
short s_type; /* Packet type sent */
short r_type; /* Packet type received */
short s_soh; /* Packet start sent */
short r_soh; /* Packet start received */
short s_eom; /* Packet end sent */
short r_eom; /* Packet end received */
int size; /* Current size of output pkt data */
int osize; /* Previous output packet data size */
int r_timo; /* Receive and send timers */
int s_timo; /* ... */
int r_maxlen; /* maximum packet length to receive */
int s_maxlen; /* maximum packet length to send */
short window; /* maximum window slots */
short wslots; /* current window slots */
short parity; /* 0 = none, nonzero = some */
short retry; /* retry limit */
short cancel; /* Cancellation */
short ikeep; /* Keep incompletely received files */
char s_ctlq; /* control-prefix out */
char r_ctlq; /* control-prefix in */
char ebq; /* 8-bit prefix */
char ebqflg; /* 8-bit prefixing negotiated */
char rptq; /* Repeat-count prefix */
int s_rpt; /* Current repeat count */
short rptflg; /* flag for repeat counts negotiated */
short bct; /* Block-check type 1..3 */
unsigned short capas; /* Capability bits */
#ifdef F_CRC
USHORT crcta[16]; /* CRC generation table A */
USHORT crctb[16]; /* CRC generation table B */
#endif /* F_CRC */
UCHAR s_remain[6]; /* Send data leftovers */
UCHAR ipktbuf[P_PKTLEN+8][P_WSLOTS]; /* Buffers for incoming packets */
struct packet ipktinfo[P_WSLOTS]; /* Incoming packet info */
#ifdef COMMENT
UCHAR opktbuf[P_PKTLEN+8][P_WSLOTS]; /* Buffers for outbound packets */
#else
UCHAR opktbuf[P_PKTLEN+8]; /* Outbound packet buffer */
int opktlen; /* Outbound packet length */
UCHAR xdatabuf[P_PKTLEN+2]; /* Buffer for building data field */
#endif /* COMMENT */
struct packet opktinfo[P_WSLOTS]; /* Outbound packet info */
UCHAR * xdata; /* Pointer to data field of outpkt */
#ifdef F_TSW
short r_pw[64]; /* Packet Seq.No. to window-slot map */
short s_pw[64]; /* Packet Seq.No. to window-slot map */
#endif /* F_TSW */
UCHAR ack_s[IDATALEN]; /* Our own init parameter string */
UCHAR * obuf;
int rx_avail; /* Comms bytes available for reading */
int obuflen; /* Length of output file buffer */
int obufpos; /* Output file buffer position */
UCHAR ** filelist; /* List of files to send */
UCHAR * dir; /* Directory */
UCHAR * filename; /* Name of current file */
UCHAR * istring; /* Pointer to string to encode from */
UCHAR * ostring; /* Pointer to string to decode to */
int (*rxd)(struct k_data *, UCHAR *, int); /* Comms read function */
int (*txd)(struct k_data *, UCHAR *, int); /* and comms write function */
int (*ixd)(struct k_data *); /* and comms info function */
int (*openf)(struct k_data *,UCHAR *,int); /* open-file function */
ULONG (*finfo)(struct k_data *,UCHAR *,UCHAR *,int,short *,short);
int (*readf)(struct k_data *); /* read-file function */
int (*writef)(struct k_data *,UCHAR *, int); /* write-file function */
int (*closef)(struct k_data *,UCHAR,int); /* close-file function */
int (*dbf)(int,UCHAR *,UCHAR *,long); /* debug function */
UCHAR * zinbuf; /* Input file buffer itself */
int zincnt; /* Input buffer position */
int zinlen; /* Length of input file buffer */
UCHAR * zinptr; /* Pointer to input file buffer */
int bctf; /* Flag to force type 3 block check */
int dummy;
};
struct k_response { /* Report from Kermit */
short status; /* Current status */
UCHAR filename[FN_MAX]; /* Name of current file */
UCHAR filedate[DATE_MAX]; /* Date of file */
long filesize; /* Size of file */
long sofar; /* Bytes transferred so far */
};
/* Macro definitions */
#define tochar(ch) (UCHAR)((UCHAR)((UCHAR)(ch) + SP ))
#define xunchar(ch) (UCHAR)((UCHAR)((UCHAR)(ch) - SP ))
#define ctl(ch) (UCHAR)((UCHAR)((UCHAR)(ch) ^ 64 ))
#ifdef COMMENT
#define tochar(ch) (((ch) + SP ) & 0xFF ) /* Digit to character */
#define xunchar(ch) (((ch) - SP ) & 0xFF ) /* Character to number */
#define ctl(ch) (((ch) ^ 64 ) & 0xFF ) /* Controllify/uncontrollify */
#endif /* COMMENT */
/* Prototypes for kermit() functions */
int kermit(short, struct k_data *, short, int, char *, struct k_response *);
UCHAR * getrslot(struct k_data *, short *);
UCHAR * getsslot(struct k_data *, short *);
void freerslot(struct k_data *, short);
void freesslot(struct k_data *, short);
#endif /* __KERMIT_H__ */

447
external/bsd/ekermit/dist/main.c vendored Normal file
View File

@ -0,0 +1,447 @@
/* Embedded Kermit demo, main program. */
/*
Author: Frank da Cruz, the Kermit Project, Columbia University, New York.
Copyright (C) 1995, 2011,
Trustees of Columbia University in the City of New York.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of Columbia University nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
/*
This is a demo/test framework, to be replaced by a real control program.
It includes a simple Unix-style command-line parser to allow setup and
testing of the Kermit module. Skip past all this to where it says REAL
STUFF to see the real stuff. ANSI C required. Note: order of the
following includes is important.
*/
#include "cdefs.h" /* Data types for all modules */
#include "debug.h" /* Debugging */
#include "platform.h" /* Platform-specific includes and definitions */
#include "kermit.h" /* Kermit symbols and data structures */
#ifdef __linux
#include <errno.h>
#endif /* __linux */
/*
Sample prototypes for i/o functions.
The functions are defined in a platform-specific i/o module.
The function names are unknown to the Kermit module.
The names can be changed but not their calling conventions.
The following prototypes are keyed to unixio.c.
*/
int devopen(char *); /* Communications device/path */
int devsettings(char *);
int devrestore(void);
int devclose(void);
int pktmode(short);
int readpkt(struct k_data *, UCHAR *, int); /* Communications i/o functions */
int tx_data(struct k_data *, UCHAR *, int);
int inchk(struct k_data *);
int openfile(struct k_data *, UCHAR *, int); /* File i/o functions */
int writefile(struct k_data *, UCHAR *, int);
int readfile(struct k_data *);
int closefile(struct k_data *, UCHAR, int);
ULONG fileinfo(struct k_data *, UCHAR *, UCHAR *, int, short *, short);
/* External data */
extern UCHAR o_buf[]; /* Must be defined in io.c */
extern UCHAR i_buf[]; /* Must be defined in io.c */
extern int errno;
/* Data global to this module */
struct k_data k; /* Kermit data structure */
struct k_response r; /* Kermit response structure */
char **xargv; /* Global pointer to arg vector */
UCHAR **cmlist = (UCHAR **)0; /* Pointer to file list */
char * xname = "ek"; /* Default program name */
int xargc; /* Global argument count */
int nfils = 0; /* Number of files in file list */
int action = 0; /* Send or Receive */
int xmode = 0; /* File-transfer mode */
int ftype = 1; /* Global file type 0=text 1=binary*/
int keep = 0; /* Keep incompletely received files */
int db = 0; /* Debugging */
short fmode = -1; /* Transfer mode for this file */
int parity = 0; /* Parity */
#ifdef F_CRC
int check = 3; /* Block check */
#else
int check = 1;
#endif /* F_CRC */
int remote = 1; /* 1 = Remote, 0 = Local */
#ifdef DEBUG
int errorrate = 0; /* Simulated error rate */
int seed = 1234; /* Random number generator seed */
#endif /* DEBUG */
void
doexit(int status) {
devrestore(); /* Restore device */
devclose(); /* Close device */
exit(status); /* Exit with indicated status */
}
void
usage() {
fprintf(stderr,"E-Kermit %s\n",VERSION);
fprintf(stderr,"Usage: %s <options>\n",xname);
fprintf(stderr,"Options:\n");
fprintf(stderr," -r Receive files\n");
#ifndef RECVONLY
fprintf(stderr," -s <files> Send files\n");
#endif /* RECVONLY */
fprintf(stderr," -p [neoms] Parity: none, even, odd, mark, space\n");
#ifdef F_CRC
fprintf(stderr," -b [1235] Block check type: 1, 2, 3, or 5\n");
#endif /* F_CRC */
fprintf(stderr," -k Keep incompletely received files\n");
fprintf(stderr," -B Force binary mode\n");
fprintf(stderr," -T Force text mode\n");
fprintf(stderr," -R Remote mode (vs local)\n");
fprintf(stderr," -L Local mode (vs remote)\n");
#ifdef DEBUG
fprintf(stderr," -E <number> Simulated error rate (0-100)\n");
fprintf(stderr," -d Create debug.log\n");
#endif /* DEBUG */
fprintf(stderr," -h Help (this message)\n");
doexit(FAILURE);
}
void
fatal(char *msg1, char *msg2, char *msg3) { /* Not to be called except */
if (msg1) { /* from this module */
fprintf(stderr,"%s: %s",xname,msg1);
if (msg2) fprintf(stderr,"%s",msg2);
if (msg3) fprintf(stderr,"%s",msg3);
fprintf(stderr,"\n");
}
doexit(FAILURE);
}
/* Simple user interface for testing */
int
doarg(char c) { /* Command-line option parser */
int x; /* Parses one option with its arg(s) */
char *xp, *s;
struct stat statbuf;
xp = *xargv+1; /* Pointer for bundled args */
while (c) {
#ifdef DEBUG
if (errorrate) seed += (int)c;
#endif /* DEBUG) */
switch (c) {
case 'r': /* Receive */
if (action) fatal("Conflicting actions",(char *)0,(char *)0);
action = A_RECV;
break;
#ifndef RECVONLY
case 's': /* Send */
if (action)
fatal("Conflicting actions",(char *)0,(char *)0);
if (*(xp+1))
fatal("Invalid argument bundling after -s",(char *)0,(char *)0);
nfils = 0; /* Initialize file counter, flag */
cmlist = (UCHAR **)(xargv+1); /* Remember this pointer */
while (--xargc > 0) { /* Traverse the list */
xargv++;
s = *xargv;
#ifdef DEBUG
if (errorrate) seed += (int)*s;
#endif /* DEBUG) */
if (**xargv == '-')
break;
errno = 0;
x = stat(s,&statbuf);
if (x < 0)
fatal("File '",s,"' not found");
if (access(s,4) < 0)
fatal("File '",s,"' not accessible");
nfils++;
}
xargc++, *xargv--; /* Adjust argv/argc */
if (nfils < 1)
fatal("Missing filename for -s",(char *)0,(char *)0);
action = A_SEND;
break;
#endif /* RECVONLY */
#ifdef F_CRC
case 'b': /* Block-check type */
#endif /* F_CRC */
#ifdef DEBUG
case 'E': /* Simulated error rate */
#endif /* DEBUG */
if (*(xp+1))
fatal("Invalid argument bundling",(char *)0,(char *)0);
*xargv++, xargc--;
if ((xargc < 1) || (**xargv == '-'))
fatal("Missing option argument",(char *)0,(char *)0);
s = *xargv;
while (*s) {
if (!isdigit(*s))
fatal("Numeric argument required",(char *)0,(char *)0);
s++;
}
if (c == 'b') {
check = atoi(*xargv);
if (check < 1 || check > 5 || check == 4)
fatal("Invalid block check",(char *)0,(char *)0);
#ifdef DEBUG
} else if (c == 'E') {
errorrate = atoi(*xargv);
if (errorrate > 100)
fatal("Invalid error rate",(char *)0,(char *)0);
#endif /* DEBUG */
}
break;
case 'h': /* Help */
case '?':
usage();
case 'B': /* Force binary file transfer */
xmode = 1; /* So no automatic switching */
ftype = BINARY;
break;
case 'T': /* Force text file transfer */
xmode = 1; /* So no automatic switching */
ftype = TEXT;
break;
case 'R': /* Tell Kermit it's in remote mode */
remote = 1;
break;
case 'L': /* Tell Kermit it's in local mode */
remote = 0;
break;
case 'k': /* Keep incompletely received files */
keep = 1;
break;
case 'p': /* Parity */
if (*(xp+1))
fatal("Invalid argument bundling",(char *)0,(char *)0);
*xargv++, xargc--;
if ((xargc < 1) || (**xargv == '-'))
fatal("Missing parity",(char *)0,(char *)0);
switch(x = **xargv) {
case 'e': /* Even */
case 'o': /* Odd */
case 'm': /* Mark */
case 's': parity = x; break; /* Space */
case 'n': parity = 0; break; /* None */
default: fatal("Invalid parity '", *xargv, "'");
}
break;
#ifdef DEBUG
case 'd':
db++;
break;
#endif /* DEBUG */
default: /* Anything else */
fatal("Unknown command-line option ",
*xargv,
" type 'ek -h' for help."
);
}
c = *++xp; /* See if options are bundled */
}
return(action);
}
void
main(int argc, char ** argv) {
int status, rx_len, i, x;
char c;
UCHAR *inbuf;
short r_slot;
parity = P_PARITY; /* Set this to desired parity */
status = X_OK; /* Initial kermit status */
xargc = argc;
xargv = argv;
xname = argv[0];
while (--xargc > 0) { /* Loop through command-line words */
xargv++;
if (**xargv == '-') { /* Have dash */
c = *(*xargv+1); /* Get the option letter */
x = doarg(c); /* Go handle the option */
if (x < 0) doexit(FAILURE);
} else { /* No dash where expected */
fatal("Malformed command-line option: '",*xargv,"'");
}
}
if (!action) /* Nothing to do, give usage message */
usage();
#ifdef DEBUG
debug(DB_LOG,"SIMULATED ERROR RATE:",0,errorrate);
if (errorrate) srand(seed); /* Init random error generator */
#endif /* DEBUG */
/* THE REAL STUFF IS FROM HERE DOWN */
if (!devopen("dummy")) /* Open the communication device */
doexit(FAILURE);
if (!devsettings("dummy")) /* Perform any needed settings */
doexit(FAILURE);
if (db) /* Open debug log if requested */
debug(DB_OPN,"debug.log",0,0);
debug(DB_MSG,"Initializing...",0,0);
/* Fill in parameters for this run */
k.xfermode = xmode; /* Text/binary automatic/manual */
k.remote = remote; /* Remote vs local */
k.binary = ftype; /* 0 = text, 1 = binary */
k.parity = parity; /* Communications parity */
k.bct = (check == 5) ? 3 : check; /* Block check type */
k.ikeep = keep; /* Keep incompletely received files */
k.filelist = cmlist; /* List of files to send (if any) */
k.cancel = 0; /* Not canceled yet */
/* Fill in the i/o pointers */
k.zinbuf = i_buf; /* File input buffer */
k.zinlen = IBUFLEN; /* File input buffer length */
k.zincnt = 0; /* File input buffer position */
k.obuf = o_buf; /* File output buffer */
k.obuflen = OBUFLEN; /* File output buffer length */
k.obufpos = 0; /* File output buffer position */
/* Fill in function pointers */
k.rxd = readpkt; /* for reading packets */
k.txd = tx_data; /* for sending packets */
k.ixd = inchk; /* for checking connection */
k.openf = openfile; /* for opening files */
k.finfo = fileinfo; /* for getting file info */
k.readf = readfile; /* for reading files */
k.writef = writefile; /* for writing to output file */
k.closef = closefile; /* for closing files */
#ifdef DEBUG
k.dbf = db ? dodebug : 0; /* for debugging */
#else
k.dbf = 0;
#endif /* DEBUG */
/* Force Type 3 Block Check (16-bit CRC) on all packets, or not */
k.bctf = (check == 5) ? 1 : 0;
/* Initialize Kermit protocol */
status = kermit(K_INIT, &k, 0, 0, "", &r);
#ifdef DEBUG
debug(DB_LOG,"init status:",0,status);
debug(DB_LOG,"version:",k.version,0);
#endif /* DEBUG */
if (status == X_ERROR)
doexit(FAILURE);
if (action == A_SEND)
status = kermit(K_SEND, &k, 0, 0, "", &r);
/*
Now we read a packet ourselves and call Kermit with it. Normally, Kermit
would read its own packets, but in the embedded context, the device must be
free to do other things while waiting for a packet to arrive. So the real
control program might dispatch to other types of tasks, of which Kermit is
only one. But in order to read a packet into Kermit's internal buffer, we
have to ask for a buffer address and slot number.
To interrupt a transfer in progress, set k.cancel to I_FILE to interrupt
only the current file, or to I_GROUP to cancel the current file and all
remaining files. To cancel the whole operation in such a way that the
both Kermits return an error status, call Kermit with K_ERROR.
*/
while (status != X_DONE) {
/*
Here we block waiting for a packet to come in (unless readpkt times out).
Another possibility would be to call inchk() to see if any bytes are waiting
to be read, and if not, go do something else for a while, then come back
here and check again.
*/
inbuf = getrslot(&k,&r_slot); /* Allocate a window slot */
rx_len = k.rxd(&k,inbuf,P_PKTLEN); /* Try to read a packet */
debug(DB_PKT,"main packet",&(k.ipktbuf[0][r_slot]),rx_len);
/*
For simplicity, kermit() ACKs the packet immediately after verifying it was
received correctly. If, afterwards, the control program fails to handle the
data correctly (e.g. can't open file, can't write data, can't close file),
then it tells Kermit to send an Error packet next time through the loop.
*/
if (rx_len < 1) { /* No data was read */
freerslot(&k,r_slot); /* So free the window slot */
if (rx_len < 0) /* If there was a fatal error */
doexit(FAILURE); /* give up */
/* This would be another place to dispatch to another task */
/* while waiting for a Kermit packet to show up. */
}
/* Handle the input */
switch (status = kermit(K_RUN, &k, r_slot, rx_len, "", &r)) {
case X_OK:
#ifdef DEBUG
/*
This shows how, after each packet, you get the protocol state, file name,
date, size, and bytes transferred so far. These can be used in a
file-transfer progress display, log, etc.
*/
debug(DB_LOG,"NAME",r.filename ? (char *)r.filename : "(NULL)",0);
debug(DB_LOG,"DATE",r.filedate ? (char *)r.filedate : "(NULL)",0);
debug(DB_LOG,"SIZE",0,r.filesize);
debug(DB_LOG,"STATE",0,r.status);
debug(DB_LOG,"SOFAR",0,r.sofar);
#endif /* DEBUG */
/* Maybe do other brief tasks here... */
continue; /* Keep looping */
case X_DONE:
break; /* Finished */
case X_ERROR:
doexit(FAILURE); /* Failed */
}
}
doexit(SUCCESS);
}

69
external/bsd/ekermit/dist/makefile vendored Normal file
View File

@ -0,0 +1,69 @@
#Makefile for embedded Kermit.
#
# Copyright (C) 1995, 2011,
# Trustees of Columbia University in the City of New York.
# All Rights Reserved. See kermit.c for license.
OBJS= main.o kermit.o unixio.o
EK = makewhat
ALL = $(EK)
all: $(ALL)
ek: $(OBJS)
$(CC) $(CFLAGS) -o ek $(OBJS)
#Dependencies
main.o: main.c cdefs.h debug.h kermit.h platform.h
kermit.o: kermit.c cdefs.h debug.h kermit.h
unixio.o: unixio.c cdefs.h debug.h platform.h kermit.h
#Targets
#Build with cc.
cc:
make ek
#Build with gcc.
gcc:
@UNAME=`uname` ; make "CC=gcc" "CC2=gcc" "CFLAGS=-D$$UNAME -O2" ek
#Ditto but no debugging.
gccnd:
make "CC=gcc" "CC2=gcc" "CFLAGS=-DNODEBUG -O2" ek
#Build with gcc, Receive-Only, minimum size and features.
gccmin:
make "CC=gcc" "CC2=gcc" \
"CFLAGS=-DMINSIZE -DOBUFLEN=256 -DFN_MAX=16 -O2" ek
#Ditto but Receive-Only:
gccminro:
make "CC=gcc" "CC2=gcc" \
"CFLAGS=-DMINSIZE -DOBUFLEN=256 -DFN_MAX=16 -DRECVONLY -O2" ek
#Minimum size, receive-only, but with debugging:
gccminrod:
make "CC=gcc" "CC2=gcc" \
"CFLAGS=-DMINSIZE -DOBUFLEN=256 -DFN_MAX=16 -DRECVONLY -DDEBUG -O2" ek
#HP-UX 9.0 or higher with ANSI C.
hp:
make "SHELL=/usr/bin/sh" CC=/opt/ansic/bin/cc CC2=/opt/ansic/bin/cc \
ek "CFLAGS=-DHPUX -Aa"
#To get profile, build this target, run it, then "gprof ./ek > file".
gprof:
make "CC=gcc" "CC2=gcc" ek "CFLAGS=-DNODEBUG -pg" "LNKFLAGS=-pg"
clean:
rm -f $(OBJS) core
makewhat:
@echo 'Defaulting to gcc...'
make gcc
#End of Makefile

12
external/bsd/ekermit/dist/platform.h vendored Normal file
View File

@ -0,0 +1,12 @@
/* Unix platform.h for EK */
#include <stdio.h>
#include <sys/stat.h>
#ifndef IBUFLEN
#define IBUFLEN 4096 /* File input buffer size */
#endif /* IBUFLEN */
#ifndef OBUFLEN
#define OBUFLEN 8192 /* File output buffer size */
#endif /* OBUFLEN */

12
external/bsd/ekermit/dist/unix.h vendored Normal file
View File

@ -0,0 +1,12 @@
/* Unix platform.h for EK */
#include <stdio.h>
#include <sys/stat.h>
#ifndef IBUFLEN
#define IBUFLEN 4096 /* File input buffer size */
#endif /* IBUFLEN */
#ifndef OBUFLEN
#define OBUFLEN 8192 /* File output buffer size */
#endif /* OBUFLEN */

627
external/bsd/ekermit/dist/unixio.c vendored Normal file
View File

@ -0,0 +1,627 @@
/* Sample system-dependent communications i/o routines for embedded Kermit. */
/*
Author: Frank da Cruz.
Copyright (C) 1995, 2011.
Trustees of Columbia University in the City of New York.
All rights reserved.
See kermit.c for license.
*/
/*
The sample i/o routines for UNIX that provide packet i/o
functions on the console (login) device.
Copy this file, rename it appropriately, and replace the contents
of each routine appropriately for your platform.
Device i/o:
int devopen() Communications device - open
int pktmode() Communications device - enter/exit packet mode
int readpkt() Communications device - read a packet
int tx_data() Communications device - send data
int devclose() Communications device - close
int inchk() Communications device - check if bytes are ready to read
File i/o:
int openfile() File - open for input or output
ULONG fileinfo() Get input file modtime and size
int readfile() Input file - read data
int writefile() Output file - write data
int closefile() Input or output file - close
Full definitions below, prototypes in kermit.h.
These routines must handle speed setting, parity, flow control, file i/o,
and similar items without the kermit() routine knowing anything about it.
If parity is in effect, these routines must add it to outbound characters
and strip it from inbound characters.
*/
#include <stdio.h>
#include <sys/stat.h>
#include <time.h>
#include <errno.h>
#ifndef O_WRONLY
#include <sys/file.h>
#ifdef X_OK
#undef X_OK
#endif /* X_OK */
#endif /* O_WRONLY */
#include "cdefs.h"
#include "debug.h"
#include "platform.h"
#include "kermit.h"
UCHAR o_buf[OBUFLEN+8]; /* File output buffer */
UCHAR i_buf[IBUFLEN+8]; /* File output buffer */
/*
In this example, the output file is unbuffered to ensure that every
output byte is commited. The input file, however, is buffered for speed.
This is just one of many possible implmentation choices, invisible to the
Kermit protocol module.
*/
static int ttyfd, ofile = -1; /* File descriptors */
static FILE * ifile = (FILE *)0; /* and pointers */
/* Debugging */
#ifdef DEBUG
static FILE * dp = (FILE *)0; /* Debug log */
static int xdebug = 0; /* Debugging on/off */
void
dodebug(int fc, UCHAR * label, UCHAR * sval, long nval) {
if (fc != DB_OPN && !xdebug)
return;
if (!label)
label = "";
switch (fc) { /* Function code */
case DB_OPN: /* Open debug log */
if (dp) fclose(dp);
if (!*label) label = "debug.log";
dp = fopen(label,"w");
if (!dp) {
dp = stderr;
} else {
setbuf(dp,(char *)0);
}
xdebug = 1;
fprintf(dp,"DEBUG LOG OPEN\n");
return;
case DB_MSG: /* Write a message */
if (dp) fprintf(dp,"%s\n",label);
return;
case DB_CHR: /* Write label and character */
if (dp) fprintf(dp,"%s=[%c]\n",label,(char)nval);
return;
case DB_PKT: /* Log a packet */
/* (fill in later, fall thru for now...) */
case DB_LOG: /* Write label and string or number */
if (sval && dp)
fprintf(dp,"%s[%s]\n",label,sval);
else
fprintf(dp,"%s=%ld\n",label,nval);
return;
case DB_CLS: /* Close debug log */
if (dp) {
fclose(dp);
dp = (FILE *)0;
}
xdebug = 0;
}
}
#endif /* DEBUG */
/* D E V O P E N -- Open communications device */
/*
Call with: string pointer to device name. This routine should get the
current device settings and save them so devclose() can restore them.
It should open the device. If the device is a serial port, devopen()
set the speed, stop bits, flow control, etc.
Returns: 0 on failure, 1 on success.
*/
int
devopen(char *device) {
ttyfd = 0;
return(1);
}
/* P K T M O D E -- Put communications device into or out of packet mode */
/*
Call with: 0 to put in normal (cooked) mode, 1 to put in packet (raw) mode.
For a "dumb i/o device" like an i/o port that does not have a login attached
to it, this routine can usually be a no-op.
Returns: 0 on failure, 1 on success.
*/
int
pktmode(short on) {
if (ttyfd < 0) /* Device must be open */
return(0);
system(on ? "stty raw -echo" : "stty sane"); /* Crude but effective */
return(1);
}
/* D E V S E T T I N G S */
int
devsettings(char * s) {
/* Get current device settings, save them for devrestore() */
/* Parse string s, do whatever it says, e.g. "9600;8N1" */
if (!pktmode(ON)) /* And put device in packet mode */
return(0);
return(1);
}
/* D E V R E S T O R E */
int
devrestore(void) {
/* Put device back as we found it */
pktmode(OFF);
return(1);
}
/* D E V C L O S E -- Closes the current open communications device */
/*
Call with: nothing
Closes the device and puts it back the way it was found by devopen().
Returns: 0 on failure, 1 on success.
*/
int
devclose(void) {
ttyfd = -1;
return(1);
}
/* I N C H K -- Check if input waiting */
/*
Check if input is waiting to be read, needed for sliding windows. This
sample version simply looks in the stdin buffer (which is not portable
even among different Unixes). If your platform does not provide a way to
look at the device input buffer without blocking and without actually
reading from it, make this routine return -1. On success, returns the
numbers of characters waiting to be read, i.e. that can be safely read
without blocking.
*/
int
inchk(struct k_data * k) {
#ifdef _IO_file_flags /* Linux */
if (ttyfd < 0) /* Device must be open */
return(0);
return((int) ((stdin->_IO_read_end) - (stdin->_IO_read_ptr)));
#else
#ifdef AIX /* AIX */
if (ttyfd < 0)
return(0);
return(stdin->_cnt);
#else
#ifdef SunOS /* Solaris and SunOS */
if (ttyfd < 0)
return(0);
return(stdin->_cnt);
#else
#ifdef HPUX /* HPUX */
if (ttyfd < 0)
return(0);
return(stdin->__cnt);
#else
return(-1);
#endif /* HPUX */
#endif /* SunOS */
#endif /* AIX */
#endif /* _IO_file_flags */
}
/* R E A D P K T -- Read a Kermit packet from the communications device */
/*
Call with:
k - Kermit struct pointer
p - pointer to read buffer
len - length of read buffer
When reading a packet, this function looks for start of Kermit packet
(k->r_soh), then reads everything between it and the end of the packet
(k->r_eom) into the indicated buffer. Returns the number of bytes read, or:
0 - timeout or other possibly correctable error;
-1 - fatal error, such as loss of connection, or no buffer to read into.
*/
int
readpkt(struct k_data * k, UCHAR *p, int len, int fc) {
int x, n, max;
short flag;
UCHAR c;
/*
Timeout not implemented in this sample.
It should not be needed. All non-embedded Kermits that are capable of
making connections are also capable of timing out, and only one Kermit
needs to time out. NOTE: This simple example waits for SOH and then
reads everything up to the negotiated packet terminator. A more robust
version might be driven by the value of the packet-length field.
*/
#ifdef DEBUG
char * p2;
#endif /* DEBUG */
#ifdef F_CTRLC
short ccn;
ccn = 0;
#endif /* F_CTRLC */
if (ttyfd < 0 || !p) { /* Device not open or no buffer */
debug(DB_MSG,"readpkt FAIL",0,0);
return(-1);
}
flag = n = 0; /* Init local variables */
#ifdef DEBUG
p2 = p;
#endif /* DEBUG */
while (1) {
x = getchar(); /* Replace this with real i/o */
c = (k->parity) ? x & 0x7f : x & 0xff; /* Strip parity */
#ifdef F_CTRLC
/* In remote mode only: three consecutive ^C's to quit */
if (k->remote && c == (UCHAR) 3) {
if (++ccn > 2) {
debug(DB_MSG,"readpkt ^C^C^C",0,0);
return(-1);
}
} else {
ccn = 0;
}
#endif /* F_CTRLC */
if (!flag && c != k->r_soh) /* No start of packet yet */
continue; /* so discard these bytes. */
if (c == k->r_soh) { /* Start of packet */
flag = 1; /* Remember */
continue; /* But discard. */
} else if (c == k->r_eom /* Packet terminator */
|| c == '\012' /* 1.3: For HyperTerminal */
) {
#ifdef DEBUG
*p = NUL; /* Terminate for printing */
debug(DB_PKT,"RPKT",p2,n);
#endif /* DEBUG */
return(n);
} else { /* Contents of packet */
if (n++ > k->r_maxlen) /* Check length */
return(0);
else
*p++ = x & 0xff;
}
}
debug(DB_MSG,"READPKT FAIL (end)",0,0);
return(-1);
}
/* T X _ D A T A -- Writes n bytes of data to communication device. */
/*
Call with:
k = pointer to Kermit struct.
p = pointer to data to transmit.
n = length.
Returns:
X_OK on success.
X_ERROR on failure to write - i/o error.
*/
int
tx_data(struct k_data * k, UCHAR *p, int n) {
int x;
int max;
max = 10; /* Loop breaker */
while (n > 0) { /* Keep trying till done */
x = write(ttyfd,p,n);
debug(DB_MSG,"tx_data write",0,x);
if (x < 0 || --max < 1) /* Errors are fatal */
return(X_ERROR);
n -= x;
p += x;
}
return(X_OK); /* Success */
}
/* O P E N F I L E -- Open output file */
/*
Call with:
Pointer to filename.
Size in bytes.
Creation date in format yyyymmdd hh:mm:ss, e.g. 19950208 14:00:00
Mode: 1 = read, 2 = create, 3 = append.
Returns:
X_OK on success.
X_ERROR on failure, including rejection based on name, size, or date.
*/
int
openfile(struct k_data * k, UCHAR * s, int mode) {
switch (mode) {
case 1: /* Read */
if (!(ifile = fopen(s,"r"))) {
debug(DB_LOG,"openfile read error",s,0);
return(X_ERROR);
}
k->s_first = 1; /* Set up for getkpt */
k->zinbuf[0] = '\0'; /* Initialize buffer */
k->zinptr = k->zinbuf; /* Set up buffer pointer */
k->zincnt = 0; /* and count */
debug(DB_LOG,"openfile read ok",s,0);
return(X_OK);
case 2: /* Write (create) */
ofile = creat(s,0644);
if (ofile < 0) {
debug(DB_LOG,"openfile write error",s,0);
return(X_ERROR);
}
debug(DB_LOG,"openfile write ok",s,0);
return(X_OK);
#ifdef COMMENT
case 3: /* Append (not used) */
ofile = open(s,O_WRONLY|O_APPEND);
if (ofile < 0) {
debug(DB_LOG,"openfile append error",s,0);
return(X_ERROR);
}
debug(DB_LOG,"openfile append ok",s,0);
return(X_OK);
#endif /* COMMENT */
default:
return(X_ERROR);
}
}
/* F I L E I N F O -- Get info about existing file */
/*
Call with:
Pointer to filename
Pointer to buffer for date-time string
Length of date-time string buffer (must be at least 18 bytes)
Pointer to int file type:
0: Prevailing type is text.
1: Prevailing type is binary.
Transfer mode (0 = auto, 1 = manual):
0: Figure out whether file is text or binary and return type.
1: (nonzero) Don't try to figure out file type.
Returns:
X_ERROR on failure.
0L or greater on success == file length.
Date-time string set to yyyymmdd hh:mm:ss modtime of file.
If date can't be determined, first byte of buffer is set to NUL.
Type set to 0 (text) or 1 (binary) if mode == 0.
*/
#ifdef F_SCAN
#define SCANBUF 1024
#define SCANSIZ 49152
#endif /* F_SCAN */
ULONG
fileinfo(struct k_data * k,
UCHAR * filename, UCHAR * buf, int buflen, short * type, short mode) {
struct stat statbuf;
struct tm * timestamp, * localtime();
#ifdef F_SCAN
FILE * fp; /* File scan pointer */
char inbuf[SCANBUF]; /* and buffer */
#endif /* F_SCAN */
if (!buf)
return(X_ERROR);
buf[0] = '\0';
if (buflen < 18)
return(X_ERROR);
if (stat(filename,&statbuf) < 0)
return(X_ERROR);
timestamp = localtime(&(statbuf.st_mtime));
sprintf(buf,"%04d%02d%02d %02d:%02d:%02d",
timestamp->tm_year + 1900,
timestamp->tm_mon + 1,
timestamp->tm_mday,
timestamp->tm_hour,
timestamp->tm_min,
timestamp->tm_sec
);
#ifdef F_SCAN
/*
Here we determine if the file is text or binary if the transfer mode is
not forced. This is an extremely crude sample, which diagnoses any file
that contains a control character other than HT, LF, FF, or CR as binary.
A more thorough content analysis can be done that accounts for various
character sets as well as various forms of Unicode (UTF-8, UTF-16, etc).
Or the diagnosis could be based wholly or in part on the filename.
etc etc. Or the implementation could skip this entirely by not defining
F_SCAN and/or by always calling this routine with type set to -1.
*/
if (!mode) { /* File type determination requested */
int isbinary = 1;
fp = fopen(filename,"r"); /* Open the file for scanning */
if (fp) {
int n = 0, count = 0;
char c, * p;
debug(DB_LOG,"fileinfo scan ",filename,0);
isbinary = 0;
while (count < SCANSIZ && !isbinary) { /* Scan this much */
n = fread(inbuf,1,SCANBUF,fp);
if (n == EOF || n == 0)
break;
count += n;
p = inbuf;
while (n--) {
c = *p++;
if (c < 32 || c == 127) {
if (c != 9 && /* Tab */
c != 10 && /* LF */
c != 12 && /* FF */
c != 13) { /* CR */
isbinary = 1;
debug(DB_MSG,"fileinfo BINARY",0,0);
break;
}
}
}
}
fclose(fp);
*type = isbinary;
}
}
#endif /* F_SCAN */
return((ULONG)(statbuf.st_size));
}
/* R E A D F I L E -- Read data from a file */
int
readfile(struct k_data * k) {
if (!k->zinptr) {
#ifdef DEBUG
fprintf(dp,"readfile ZINPTR NOT SET\n");
#endif /* DEBUG */
return(X_ERROR);
}
if (k->zincnt < 1) { /* Nothing in buffer - must refill */
if (k->binary) { /* Binary - just read raw buffers */
k->dummy = 0;
k->zincnt = fread(k->zinbuf, 1, k->zinlen, ifile);
debug(DB_LOG,"readfile binary ok zincnt",0,k->zincnt);
} else { /* Text mode needs LF/CRLF handling */
int c; /* Current character */
for (k->zincnt = 0; (k->zincnt < (k->zinlen - 2)); (k->zincnt)++) {
if ((c = getc(ifile)) == EOF)
break;
if (c == '\n') /* Have newline? */
k->zinbuf[(k->zincnt)++] = '\r'; /* Insert CR */
k->zinbuf[k->zincnt] = c;
}
#ifdef DEBUG
k->zinbuf[k->zincnt] = '\0';
debug(DB_LOG,"readfile text ok zincnt",0,k->zincnt);
#endif /* DEBUG */
}
k->zinbuf[k->zincnt] = '\0'; /* Terminate. */
if (k->zincnt == 0) /* Check for EOF */
return(-1);
k->zinptr = k->zinbuf; /* Not EOF - reset pointer */
}
(k->zincnt)--; /* Return first byte. */
debug(DB_LOG,"readfile exit zincnt",0,k->zincnt);
debug(DB_LOG,"readfile exit zinptr",0,k->zinptr);
return(*(k->zinptr)++ & 0xff);
}
/* W R I T E F I L E -- Write data to file */
/*
Call with:
Kermit struct
String pointer
Length
Returns:
X_OK on success
X_ERROR on failure, such as i/o error, space used up, etc
*/
int
writefile(struct k_data * k, UCHAR * s, int n) {
int rc;
rc = X_OK;
debug(DB_LOG,"writefile binary",0,k->binary);
if (k->binary) { /* Binary mode, just write it */
if (write(ofile,s,n) != n)
rc = X_ERROR;
} else { /* Text mode, skip CRs */
UCHAR * p, * q;
int i;
q = s;
while (1) {
for (p = q, i = 0; ((*p) && (*p != (UCHAR)13)); p++, i++) ;
if (i > 0)
if (write(ofile,q,i) != i)
rc = X_ERROR;
if (!*p) break;
q = p+1;
}
}
return(rc);
}
/* C L O S E F I L E -- Close output file */
/*
Mode = 1 for input file, mode = 2 or 3 for output file.
For output files, the character c is the character (if any) from the Z
packet data field. If it is D, it means the file transfer was canceled
in midstream by the sender, and the file is therefore incomplete. This
routine should check for that and decide what to do. It should be
harmless to call this routine for a file that that is not open.
*/
int
closefile(struct k_data * k, UCHAR c, int mode) {
int rc = X_OK; /* Return code */
switch (mode) {
case 1: /* Closing input file */
if (!ifile) /* If not not open */
break; /* do nothing but succeed */
debug(DB_LOG,"closefile (input)",k->filename,0);
if (fclose(ifile) < 0)
rc = X_ERROR;
break;
case 2: /* Closing output file */
case 3:
if (ofile < 0) /* If not open */
break; /* do nothing but succeed */
debug(DB_LOG,"closefile (output) name",k->filename,0);
debug(DB_LOG,"closefile (output) keep",0,k->ikeep);
if (close(ofile) < 0) { /* Try to close */
rc = X_ERROR;
} else if ((k->ikeep == 0) && /* Don't keep incomplete files */
(c == 'D')) { /* This file was incomplete */
if (k->filename) {
debug(DB_LOG,"deleting incomplete",k->filename,0);
unlink(k->filename); /* Delete it. */
}
}
break;
default:
rc = X_ERROR;
}
return(rc);
}
#ifdef DEBUG
int xerror() {
unsigned int x;
extern int errorrate; /* Fix this - NO EXTERNS */
if (!errorrate)
return(0);
x = rand() % 100; /* Fix this - NO C LIBRARY */
debug(DB_LOG,"RANDOM",0,x);
debug(DB_LOG,"ERROR",0,(x < errorrate));
return(x < errorrate);
}
#endif /* DEBUG */