home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
kermit.columbia.edu
/
kermit.columbia.edu.tar
/
kermit.columbia.edu
/
bin
/
p205.zip
/
exesrc
/
p.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-12-18
|
15KB
|
669 lines
/*****************************************************************************/
/* Copyright (c) 1994 by Jyrki Salmi <jytasa@jyu.fi> */
/* You may modify, recompile and distribute this file freely. */
/*****************************************************************************/
/*
The main module of P.EXE. Parses the command-line and calls P.DLL.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "typedefs.h"
#include "p.h"
#include "callback.h"
#include "p_dll.h"
#include "tcpipapi.h"
#include "global.h"
#include "common.h"
#include "usage.h"
#define SERIAL_NUM 0 /* Our serial number, zero for none */
/* Stuff needed for command-line parsing */
enum {
CFG_ENTRY_TYPE,
CFG_ENTRY_DEVICE,
CFG_ENTRY_HOST,
CFG_ENTRY_PORT,
CFG_ENTRY_SERVER,
CFG_ENTRY_WAIT,
CFG_ENTRY_SHARE,
CFG_ENTRY_HANDLE,
CFG_ENTRY_LOOSE,
CFG_ENTRY_TELNET,
CFG_ENTRY_RECEIVE,
CFG_ENTRY_SEND,
CFG_ENTRY_PROTOCOL,
CFG_ENTRY_ESCAPE,
CFG_ENTRY_ALTERNATIVE,
CFG_ENTRY_KILO,
CFG_ENTRY_WINDOW,
CFG_ENTRY_AUTOMATIC,
CFG_ENTRY_SERIAL,
CFG_ENTRY_ATTENTION,
CFG_ENTRY_COMMBUFS,
CFG_ENTRY_COMMINBUF,
CFG_ENTRY_COMMOUTBUF,
CFG_ENTRY_FILEBUF,
CFG_ENTRY_SPEED,
CFG_ENTRY_MILEAGE,
CFG_ENTRY_OPTIONS,
CFG_ENTRY_HEADERS,
CFG_ENTRY_FRAMEENDS,
CFG_ENTRY_NOTE,
CFG_ENTRY_QUIET,
CFG_ENTRY_PRIORITY,
CFG_ENTRY_DSZLOG,
CFG_ENTRY_PAUSE,
CFG_ENTRY_DIRECTORY,
CFG_ENTRY_PATHS,
CFG_ENTRY_CREATE,
CFG_ENTRY_CLEAN,
CFG_ENTRY_TOUCH,
CFG_ENTRY_RECURSIVE,
CFG_ENTRY_TEXT,
CFG_ENTRY_RESUME,
CFG_ENTRY_EXISTING,
CFG_ENTRY_UPDATE,
CFG_ENTRY_APPEND,
CFG_ENTRY_REPLACE,
CFG_ENTRY_NEWER,
CFG_ENTRY_DIFFERENT,
CFG_ENTRY_PROTECT,
CFG_ENTRY_RENAME,
CFG_ENTRIES
};
typedef struct _CFG_ENTRY {
U8 *str;
U32 num_of_args;
} CFG_ENTRY;
CFG_ENTRY cfg_entry[CFG_ENTRIES] = {
{ "type", 1 },
{ "device", 1 },
{ "host", 1 },
{ "port", 1 },
{ "server", 0 },
{ "wait", 1 },
{ "share", 0 },
{ "handle", 1 },
{ "loose", 0 },
{ "telnet", 0 },
{ "receive", 0 },
{ "send", 0 },
{ "protocol", 1 },
{ "escape", 1 },
{ "alternative", 0 },
{ "kilo", 0 },
{ "window", 1 },
{ "automatic", 0 },
{ "serial", 0 },
{ "attention", 1 },
{ "commbufs", 1 },
{ "comminbuf", 1 },
{ "commoutbuf", 1 },
{ "filebuf", 1 },
{ "speed", 1 },
{ "mileage", 0 },
{ "options", 0 },
{ "headers", 0 },
{ "frameends", 0 },
{ "note", 1 },
{ "quiet", 0 },
{ "priority", 2 },
{ "dszlog", 1 },
{ "pause", 0 },
{ "directory", 1 },
{ "paths", 0 },
{ "create", 0 },
{ "clean", 0 },
{ "touch", 0 },
{ "recursive", 0 },
{ "text", 0 },
{ "resume", 0 },
{ "existing", 0 },
{ "update", 0 },
{ "append", 0 },
{ "replace", 0 },
{ "newer", 0 },
{ "different", 0 },
{ "protect", 0 },
{ "rename", 0 },
};
U8 *dev_type_str[] = {
"async",
"pipe",
"socket"
};
U8 *protocol_str[] = {
"Xmodem",
"Ymodem",
"Ymodem-g",
"Zmodem"
};
U8 *escaping_str[] = {
"controls",
"minimal"
};
U8 *checking_str[] = {
"crc32",
"crc16",
"checksum"
};
/* Checks and reports possible inconsistency in command-line options */
U32 check_inconsistency(void) {
if (!p_cfg.dev_handle) {
switch (p_cfg.dev_type) {
case DEV_TYPE_ASYNC:
case DEV_TYPE_PIPE:
if (p_cfg.dev_path == NULL) {
fprintf(stderr, "No communication device specified, use -device to specify one.\n");
return(1);
}
break;
case DEV_TYPE_SOCKET:
if (!(p_cfg.attr & CFG_DEV_SERVER) && p_cfg.socket_host == NULL) {
fprintf(stderr,
"No host specified, use -host to specify one, or if acting\n"
"as a server, use -server option.\n");
return(1);
}
if (!p_cfg.socket_port) {
fprintf(stderr, "No port specified, use -port to specify one.\n");
return(1);
}
break;
}
}
if (!p_cfg.transfer_direction) {
fprintf(stderr, "No transfer direction specified, use -receive or -send to specify one.\n");
return(1);
}
if (tl == NULL) { /* No files specified */
if (p_cfg.transfer_direction == DIR_SEND) {
fprintf(stderr, "Files to be sent must be specified.\n");
return(1);
}
if (p_cfg.transfer_direction == DIR_RECV &&
p_cfg.protocol_type == PROTOCOL_X) {
fprintf(stderr, "Files to be received must be specified for Xmodem.\n");
return(1);
}
}
if ((p_cfg.attr & CFG_ESC_CTRL || p_cfg.attr & CFG_ESC_MINIMAL) &&
p_cfg.protocol_type != PROTOCOL_Z)
printf("-escape option ignored. Only Zmodem supports it.\n");
if (p_cfg.attr & CFG_ALTERNATIVE_CHECKING &&
p_cfg.protocol_type == PROTOCOL_G)
printf("-alternative option ignored. Ymodem-g does not support it.\n");
if (p_cfg.attr & CFG_1K_BLOCKS) {
if (p_cfg.protocol_type == PROTOCOL_Z)
printf("-kilo option ignored. Has no meaning to Zmodem transfers.\n");
else if (p_cfg.transfer_direction == DIR_RECV)
printf("-kilo option ignored. Sender will define the block size.\n");
}
if (p_cfg.attr & CFG_SEND_RZ_CR && p_cfg.protocol_type != PROTOCOL_Z)
printf("-automatic option ignored. Only Zmodem supports it.\n");
if (p_cfg.attr & CFG_QUERY_SERIAL_NUM && p_cfg.protocol_type != PROTOCOL_Z)
printf("-serial option ignored. Only Zmodem supports it.\n");
if (p_cfg.attn_seq != NULL && p_cfg.protocol_type != PROTOCOL_Z)
printf("-attention option ignored. Only Zmodem supports it.\n");
if (opt_mileage && p_cfg.protocol_type == PROTOCOL_X)
printf("-mileage option ignored. Xmodem does not support it.\n");
if (opt_options && p_cfg.protocol_type != PROTOCOL_Z)
printf("-options option ignored. Only Zmodem supports it.\n");
if (opt_headers && p_cfg.protocol_type != PROTOCOL_Z)
printf("-headers option ignored. Only Zmodem supports it.\n");
if (opt_frameends && p_cfg.protocol_type != PROTOCOL_Z)
printf("-frameends option ignored. Only Zmodem supports it.\n");
if (opt_resume && p_cfg.protocol_type != PROTOCOL_Z)
printf("-resume option ignored. Only Zmodem supports it.\n");
if (opt_management & Z_MANAGEMENT_UPDATE &&
p_cfg.protocol_type == PROTOCOL_X)
printf("-update option ignored. Xmodem does not support it.\n");
if (opt_management & Z_MANAGEMENT_NEWER &&
p_cfg.protocol_type == PROTOCOL_X)
printf("-newer option ignored. Xmodem does not support it.\n");
if (opt_management & Z_MANAGEMENT_DIFFERENT &&
p_cfg.protocol_type == PROTOCOL_X)
printf("-different option ignored. Xmodem does not support it.\n");
return(0);
}
U32 main(U32 argc, U8 *argv[]) {
U32 argi;
U32 idx;
U32 priority_class;
U32 priority_delta;
U32 rc;
if (argc < 2) {
printf(usage, argv[0]);
return(1);
}
/* Put default values to p_cfg */
memset(&p_cfg, '\0', sizeof(P_CFG));
p_cfg.inbuf_size = 2048;
p_cfg.outbuf_size = 2048;
p_cfg.blk_size = 0;
p_cfg.version = P_INTERFACE_VERSION;
p_cfg.attr = CFG_WATCH_CARRIER;
p_cfg.dev_type = DEV_TYPE_ASYNC;
p_cfg.protocol_type = PROTOCOL_Z;
p_cfg.serial_num = SERIAL_NUM;
p_cfg.attn_seq = NULL; /* By default, we don't */
/* use attention sequence */
/* Parse the command-line */
argi = 1;
while (argi < argc) {
if (argv[argi][0] == '-') {
if (argv[argi][1] == '\0') /* It's a plain "-" */
break;
for (idx = 0; idx < CFG_ENTRIES; idx++) {
if (strnicmp(&argv[argi][1],
cfg_entry[idx].str,
strlen(&argv[argi][1])) == 0)
break;
}
if (idx == CFG_ENTRIES) {
fprintf(stderr, "Unknown option \"%s\"\n", argv[argi]);
return(1);
}
argi++;
if (argc - argi < cfg_entry[idx].num_of_args) {
fprintf(stderr,
"Insufficient number of arguments for -%s option\n",
cfg_entry[idx].str);
return(1);
}
switch (idx) {
case CFG_ENTRY_TYPE:
for (idx = 0; idx < 3; idx++) {
if (strnicmp(argv[argi],
dev_type_str[idx],
strlen(argv[argi])) == 0)
break;
}
if (idx == 3) {
fprintf(stderr, "Unknown device type \"%s\"\n", argv[argi]);
return(1);
}
p_cfg.dev_type = idx + 1;
argi++;
break;
case CFG_ENTRY_DEVICE:
p_cfg.dev_path = argv[argi];
argi++;
break;
case CFG_ENTRY_HANDLE:
p_cfg.dev_handle = atol(argv[argi]);
argi++;
break;
case CFG_ENTRY_RECEIVE:
p_cfg.transfer_direction = DIR_RECV;
break;
case CFG_ENTRY_SEND:
p_cfg.transfer_direction = DIR_SEND;
break;
case CFG_ENTRY_SERVER:
p_cfg.attr |= CFG_DEV_SERVER;
break;
case CFG_ENTRY_PROTOCOL:
for (idx = 0; idx < 4; idx++)
if (strnicmp(argv[argi],
protocol_str[idx],
strlen(argv[argi])) == 0) {
break;
}
if (idx == 4) {
fprintf(stderr, "Unknown protocol \"%s\"\n", argv[argi]);
return(1);
}
p_cfg.protocol_type = idx + 1;
argi++;
break;
case CFG_ENTRY_COMMBUFS:
p_cfg.inbuf_size = p_cfg.outbuf_size = atol(argv[argi]);
argi++;
break;
case CFG_ENTRY_COMMINBUF:
p_cfg.inbuf_size = atol(argv[argi]);
argi++;
break;
case CFG_ENTRY_COMMOUTBUF:
p_cfg.outbuf_size = atol(argv[argi]);
argi++;
break;
case CFG_ENTRY_FILEBUF:
opt_filebuf = atol(argv[argi]);
argi++;
break;
case CFG_ENTRY_HOST:
p_cfg.socket_host = argv[argi];
argi++;
break;
case CFG_ENTRY_PORT:
p_cfg.socket_port = atol(argv[argi]);
argi++;
break;
case CFG_ENTRY_SPEED:
opt_speed = atol(argv[argi]);
argi++;
break;
case CFG_ENTRY_ESCAPE:
for (idx = 0; idx < 2; idx++)
if (strnicmp(argv[argi],
escaping_str[idx],
strlen(argv[argi])) == 0) {
break;
}
if (idx == 2) {
fprintf(stderr, "Unknown escaping \"%s\"\n", argv[argi]);
return(1);
}
switch (idx) {
case 0:
p_cfg.attr |= CFG_ESC_CTRL;
break;
case 1:
p_cfg.attr |= CFG_ESC_MINIMAL;
break;
}
argi++;
break;
case CFG_ENTRY_ALTERNATIVE:
p_cfg.attr |= CFG_ALTERNATIVE_CHECKING;
break;
case CFG_ENTRY_LOOSE:
if (p_cfg.attr & CFG_WATCH_CARRIER)
p_cfg.attr ^= CFG_WATCH_CARRIER;
break;
case CFG_ENTRY_DSZLOG:
opt_dszlog = argv[argi];
argi++;
break;
case CFG_ENTRY_KILO:
p_cfg.attr |= CFG_1K_BLOCKS;
break;
case CFG_ENTRY_PAUSE:
atexit(wait_for_keypress);
break;
case CFG_ENTRY_RESUME:
opt_resume = 1;
break;
case CFG_ENTRY_SHARE:
p_cfg.attr |= CFG_SHARED_DEVICE;
break;
case CFG_ENTRY_CLEAN:
opt_clean = 1;
break;
case CFG_ENTRY_PATHS:
opt_paths = 1;
break;
case CFG_ENTRY_DIRECTORY:
opt_directory = argv[argi];
argi++;
break;
case CFG_ENTRY_AUTOMATIC:
p_cfg.attr |= CFG_SEND_RZ_CR;
break;
case CFG_ENTRY_WAIT:
opt_wait = atol(argv[argi]);
argi++;
break;
case CFG_ENTRY_HEADERS:
opt_headers = 1;
break;
case CFG_ENTRY_FRAMEENDS:
opt_frameends = 1;
break;
case CFG_ENTRY_NOTE:
opt_note = argv[argi];
argi++;
break;
case CFG_ENTRY_WINDOW:
p_cfg.blk_size = atol(argv[argi]);
if (p_cfg.blk_size) {
if (p_cfg.blk_size < 256 || p_cfg.blk_size > 65472) {
printf("Window size must be between 256 and 65472 bytes!\n");
return(1);
}
if (p_cfg.blk_size % 64) {
printf("Window size must a multiple of 64 bytes\n");
return(1);
}
}
argi++;
break;
case CFG_ENTRY_PRIORITY:
priority_class = atol(argv[argi++]);
priority_delta = atol(argv[argi++]);
set_priority(priority_class, priority_delta);
break;
case CFG_ENTRY_SERIAL:
p_cfg.attr |= CFG_QUERY_SERIAL_NUM;
break;
case CFG_ENTRY_ATTENTION:
p_cfg.attn_seq = argv[argi++];
break;
case CFG_ENTRY_TEXT:
opt_text = 1;
break;
case CFG_ENTRY_TOUCH:
opt_touch = 1;
break;
case CFG_ENTRY_RECURSIVE:
opt_recursive = 1;
break;
case CFG_ENTRY_CREATE:
opt_create = 1;
break;
case CFG_ENTRY_TELNET:
p_cfg.attr |= CFG_DEV_TELNET;
break;
case CFG_ENTRY_QUIET:
opt_quiet = 1;
break;
case CFG_ENTRY_EXISTING:
opt_existing = 1;
break;
case CFG_ENTRY_UPDATE:
opt_management = Z_MANAGEMENT_UPDATE;
break;
case CFG_ENTRY_APPEND:
opt_management = Z_MANAGEMENT_APPEND;
break;
case CFG_ENTRY_REPLACE:
opt_management = Z_MANAGEMENT_REPLACE;
break;
case CFG_ENTRY_NEWER:
opt_management = Z_MANAGEMENT_NEWER;
break;
case CFG_ENTRY_DIFFERENT:
opt_management = Z_MANAGEMENT_DIFFERENT;
break;
case CFG_ENTRY_PROTECT:
opt_management = Z_MANAGEMENT_PROTECT;
break;
case CFG_ENTRY_RENAME:
opt_management = Z_MANAGEMENT_RENAME;
break;
case CFG_ENTRY_MILEAGE:
opt_mileage = 1;
break;
case CFG_ENTRY_OPTIONS:
opt_options = 1;
break;
}
} else /* Argument does not begin with '-' */
break;
}
p_cfg.status_func = status_func;
p_cfg.r_open_func = r_open_func;
p_cfg.s_open_func = s_open_func;
p_cfg.close_func = close_func;
p_cfg.seek_func = seek_func;
p_cfg.read_func = read_func;
p_cfg.write_func = write_func;
atexit(make_noise); /* Install the beeper */
/* Handles files and listfiles given after the options */
while (argi < argc) {
if (argv[argi][0] == '@')
tl_read_from_list(&tl,
p_cfg.transfer_direction == DIR_RECV ? 0 : 1,
argv[argi]);
else {
if (p_cfg.transfer_direction == DIR_RECV)
tl_add(&tl, argv[argi], 0);
else
tl_expanded_add(&tl, argv[argi]);
}
argi++;
}
if (check_inconsistency())
return(1);
if (p_cfg.transfer_direction == DIR_SEND) {
files_left = tl->cnt;
bytes_left = tl->size;
}
if (p_cfg.dev_type == DEV_TYPE_SOCKET)
load_tcpip();
load_p_dll();
install_interrupt_handler();
msg(MSG_LF, "%s %s is being initiated",
protocol_str[p_cfg.protocol_type - 1],
p_cfg.transfer_direction == DIR_RECV ? "receiving" : "sending");
rc = p_transfer(&p_cfg);
if (we_aborted)
msg(MSG_LF, "Transfer aborted");
unload_p_dll();
if (p_cfg.dev_type == DEV_TYPE_SOCKET)
unload_tcpip();
return(rc);
}