dict/main.c

392 lines
6.8 KiB
C
Raw Permalink Normal View History

2018-11-13 00:36:34 +00:00
#pragma optimize 79
2018-11-13 00:38:22 +00:00
#pragma lint - 1
2018-11-13 00:36:34 +00:00
#include <Locator.h>
#include <Memory.h>
2018-11-13 00:38:22 +00:00
#include <MiscTool.h>
#include <tcpip.h>
2018-11-13 00:36:34 +00:00
2018-11-13 00:38:22 +00:00
#include <errno.h>
2018-11-13 00:36:34 +00:00
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "connection.h"
2018-11-13 00:38:22 +00:00
#define IncBusy() asm { jsl 0xE10064}
#define DecBusy() asm { jsl 0xE10068}
#define Resched() asm { cop 0x7f}
2018-11-13 00:36:34 +00:00
#define BusyFlag ((byte *)0xE100FFl)
2019-07-07 20:32:31 +00:00
unsigned d_flag = 0;
2018-11-13 00:36:34 +00:00
// startup/shutdown flags.
enum {
kLoaded = 1,
kStarted = 2,
kConnected = 4,
kLoadError = -1,
kVersionError = -2
};
2018-11-13 00:38:22 +00:00
int StartUpTCP(displayPtr fx) {
2018-11-13 00:36:34 +00:00
word status;
word flags = 0;
2018-11-13 00:38:22 +00:00
2018-11-13 00:36:34 +00:00
// TCPIP is an init, not a tool, so it should always
// be loaded.
2018-11-13 00:38:22 +00:00
2018-11-13 00:36:34 +00:00
status = TCPIPStatus();
2018-11-13 00:38:22 +00:00
if (_toolErr) {
2018-11-13 00:36:34 +00:00
LoadOneTool(54, 0x0300);
2018-11-13 00:38:22 +00:00
if (_toolErr == toolVersionErr)
return kVersionError;
if (_toolErr)
return kLoadError;
2018-11-13 00:36:34 +00:00
status = 0;
flags |= kLoaded;
}
2019-07-07 14:59:02 +00:00
// require 3.0b11
if (TCPIPLongVersion() < 0x03006011) {
2018-11-13 00:36:34 +00:00
if (flags & kLoaded)
UnloadOneTool(54);
2018-11-13 00:38:22 +00:00
return kVersionError;
2018-11-13 00:36:34 +00:00
}
2018-11-13 00:38:22 +00:00
if (!status) {
2018-11-13 00:36:34 +00:00
TCPIPStartUp();
2018-11-13 00:38:22 +00:00
if (_toolErr)
return kLoadError;
2018-11-13 00:36:34 +00:00
flags |= kStarted;
}
status = TCPIPGetConnectStatus();
2018-11-13 00:38:22 +00:00
if (!status) {
2018-11-13 00:36:34 +00:00
TCPIPConnect(fx);
flags |= kConnected;
}
return flags;
}
2018-11-13 00:38:22 +00:00
void ShutDownTCP(int flags, Boolean force, displayPtr fx) {
if (flags <= 0)
return;
2018-11-13 00:36:34 +00:00
2018-11-13 00:38:22 +00:00
if (flags & kConnected) {
2018-11-13 00:36:34 +00:00
TCPIPDisconnect(force, fx);
2018-11-13 00:38:22 +00:00
if (_toolErr)
return;
2018-11-13 00:36:34 +00:00
}
2018-11-13 00:38:22 +00:00
if (flags & kStarted) {
2018-11-13 00:36:34 +00:00
TCPIPShutDown();
2018-11-13 00:38:22 +00:00
if (_toolErr)
return;
2018-11-13 00:36:34 +00:00
}
2018-11-13 00:38:22 +00:00
if (flags & kLoaded) {
2018-11-13 00:36:34 +00:00
UnloadOneTool(54);
}
}
// #pragma databank [push | pop] would be nice...
#pragma databank 1
2018-11-13 00:38:22 +00:00
pascal void DisplayCallback(const char *message) {
2018-11-13 00:36:34 +00:00
unsigned length;
2019-07-07 20:32:31 +00:00
if (!d_flag) return;
2018-11-13 00:36:34 +00:00
// message is a p-string.
length = message ? message[0] : 0;
2018-11-13 00:38:22 +00:00
if (!length)
return;
2018-11-13 00:36:34 +00:00
fprintf(stderr, "%.*s\n", length, message + 1);
}
#pragma databank 0
2018-11-13 00:38:22 +00:00
int ConnectLoop(char *host, Word port, Connection *connection) {
2018-11-13 00:36:34 +00:00
LongWord qtick;
ConnectionInit(connection, MMStartUp(), DisplayCallback);
2018-11-13 00:38:22 +00:00
ConnectionOpenC(connection, host, port);
2018-11-13 00:36:34 +00:00
// 30 second timeout.
qtick = GetTick() + 30 * 60;
2018-11-13 00:38:22 +00:00
while (!ConnectionPoll(connection)) {
if (GetTick() >= qtick) {
2019-07-07 20:32:31 +00:00
fputs("Connection timed out.\n", stderr);
2018-11-13 00:36:34 +00:00
IncBusy();
TCPIPAbortTCP(connection->ipid);
2018-11-13 00:38:22 +00:00
TCPIPLogout(connection->ipid);
2018-11-13 00:36:34 +00:00
DecBusy();
2018-11-13 00:38:22 +00:00
2018-11-13 00:36:34 +00:00
return 0;
}
}
2018-11-13 00:38:22 +00:00
if (connection->state != kConnectionStateConnected) {
fprintf(stderr, "Unable to open host: %s:%u\n", host, port);
2018-11-13 00:36:34 +00:00
return 0;
}
return 1;
}
2018-11-13 00:38:22 +00:00
int CloseLoop(Connection *connection) {
ConnectionClose(connection);
2018-11-13 00:36:34 +00:00
2018-11-13 00:38:22 +00:00
while (!ConnectionPoll(connection))
; // wait for it to close.
2018-11-13 00:36:34 +00:00
2018-11-13 00:38:22 +00:00
return 1;
2018-11-13 00:36:34 +00:00
}
static char buffer[512];
int ReadLineSync(word ipid) {
LongWord qtick;
static srBuff sr;
static rlrBuff rlr;
unsigned x;
word terr;
2018-11-13 00:38:22 +00:00
// asm { brk 0xea }
2018-11-13 00:36:34 +00:00
buffer[0] = 0;
qtick = GetTick() + 30 * 60;
2018-11-13 00:38:22 +00:00
for (;;) {
Word terr;
TCPIPPoll();
2018-11-13 00:36:34 +00:00
terr = TCPIPStatusTCP(ipid, &sr);
2018-11-13 00:38:22 +00:00
if (sr.srRcvQueued)
break;
2018-11-13 00:36:34 +00:00
2018-11-13 00:38:22 +00:00
if (terr)
return -1;
2018-11-13 00:36:34 +00:00
if (GetTick() >= qtick) {
2019-07-07 20:32:31 +00:00
fputs("Read timed out.\n", stderr);
2018-11-13 00:36:34 +00:00
return -1;
}
2018-11-13 00:38:22 +00:00
}
for (;;) {
terr = TCPIPReadLineTCP(ipid, "\p\r\n", 0x0000, (Ref)&buffer,
sizeof(buffer) - 1, &rlr);
2019-07-07 14:59:02 +00:00
if (terr) return -1; /* nb - marinetti < 3.0b11 return value inaccurate */
2018-11-13 00:38:22 +00:00
if (!rlr.rlrIsDataFlag) {
if (GetTick() >= qtick) {
2019-07-07 20:32:31 +00:00
fputs("Read timed out.\n", stderr);
2018-11-13 00:38:22 +00:00
return -1;
}
TCPIPPoll();
continue;
}
break;
}
x = rlr.rlrBuffCount;
buffer[x] = 0;
return x;
2018-11-13 00:36:34 +00:00
}
int status(void) {
2018-11-13 00:38:22 +00:00
unsigned x;
if (sscanf(buffer, "%u", &x) == 1) {
2019-07-07 20:32:31 +00:00
if (d_flag) fprintf(stderr, "status: %d\n", x);
2018-11-13 00:38:22 +00:00
return x;
}
return -1;
2018-11-13 00:36:34 +00:00
}
int client(word ipid) {
2018-11-13 00:38:22 +00:00
word terr;
int ok;
2018-11-13 00:36:34 +00:00
2018-11-13 00:38:22 +00:00
/* also checks for 220 header. */
2018-11-13 00:36:34 +00:00
2018-11-13 00:38:22 +00:00
ok = ReadLineSync(ipid);
if (ok < 0)
return ok;
ok = status();
if (ok != 220)
return -1;
2018-11-13 00:36:34 +00:00
2018-11-13 00:38:22 +00:00
terr = TCPIPWriteTCP(ipid, "CLIENT dict-iigs\r\n", 18, 1, 0);
if (terr != 0)
fprintf(stderr, "terr: %04x\n", terr);
2018-11-13 00:36:34 +00:00
2018-11-13 00:38:22 +00:00
ok = ReadLineSync(ipid);
if (ok < 0)
return ok;
2018-11-13 00:36:34 +00:00
2018-11-13 00:38:22 +00:00
/*
3.6.2. Responses
2018-11-13 00:36:34 +00:00
2018-11-13 00:38:22 +00:00
250 ok (optional timing information here)
*/
ok = status();
if (ok != 250)
return -1;
return 0;
2018-11-13 00:36:34 +00:00
}
int quit(word ipid) {
2018-11-13 00:38:22 +00:00
word terr;
int ok;
2018-11-13 00:36:34 +00:00
2018-11-13 00:38:22 +00:00
terr = TCPIPWriteTCP(ipid, "QUIT\r\n", 6, 1, 0);
if (terr != 0)
fprintf(stderr, "terr: %04x\n", terr);
ok = ReadLineSync(ipid);
if (ok < 0)
return ok;
2018-11-13 00:36:34 +00:00
2018-11-13 00:38:22 +00:00
/*
3.9.2. Responses
2018-11-13 00:36:34 +00:00
2018-11-13 00:38:22 +00:00
221 Closing Connection
*/
2018-11-13 00:36:34 +00:00
2018-11-13 00:38:22 +00:00
return 0;
2018-11-13 00:36:34 +00:00
}
int one_def(Word ipid) {
2018-11-13 00:38:22 +00:00
int ok;
for (;;) {
ok = ReadLineSync(ipid);
if (ok < 0)
return ok;
ok = status();
if (ok == 250)
return 0;
if (ok != 151)
return -1;
for (;;) {
ok = ReadLineSync(ipid);
if (ok < 0)
return ok;
if (buffer[0] == '.') {
fputc('\n', stdout);
break;
}
fputs(buffer, stdout);
fputc('\n', stdout);
}
}
fputc('\n', stdout);
return 0;
2018-11-13 00:36:34 +00:00
}
int define(Word ipid, const char *term, const char *dict) {
2018-11-13 00:38:22 +00:00
word terr;
int ok;
unsigned x;
static char buffer[512];
2018-11-13 00:36:34 +00:00
2018-11-13 00:38:22 +00:00
if (!dict || !*dict)
dict = "!";
if (!term || !*term)
return -1;
2018-11-13 00:36:34 +00:00
2018-11-13 00:38:22 +00:00
x = sprintf(buffer, "DEFINE %s \"%s\"\r\n", dict, term);
2018-11-13 00:36:34 +00:00
2018-11-13 00:38:22 +00:00
terr = TCPIPWriteTCP(ipid, buffer, x, 1, 0);
if (terr != 0)
fprintf(stderr, "terr: %04x\n", terr);
2018-11-13 00:36:34 +00:00
2018-11-13 00:38:22 +00:00
/*
3.2.2. Responses
2018-11-13 00:36:34 +00:00
2018-11-13 00:38:22 +00:00
550 Invalid database, use "SHOW DB" for list of databases
552 No match
150 n definitions retrieved - definitions follow
151 word database name - text follows
250 ok (optional timing information here)
*/
2018-11-13 00:36:34 +00:00
2018-11-13 00:38:22 +00:00
ok = ReadLineSync(ipid);
if (ok < 0)
return ok;
2018-11-13 00:36:34 +00:00
2018-11-13 00:38:22 +00:00
ok = status();
switch (status()) {
default:
return -1;
2018-11-13 00:36:34 +00:00
2018-11-13 00:38:22 +00:00
case 550:
2019-07-07 20:32:31 +00:00
fputs("Invalid database.\n", stderr);
2018-11-13 00:38:22 +00:00
return -1;
2018-11-13 00:36:34 +00:00
2018-11-13 00:38:22 +00:00
case 552:
2019-07-07 20:32:31 +00:00
fputs("No match.\n", stderr);
2018-11-13 00:38:22 +00:00
return 0;
2018-11-13 00:36:34 +00:00
2018-11-13 00:38:22 +00:00
case 150:
return one_def(ipid);
}
2018-11-13 00:36:34 +00:00
}
int main(int argc, char **argv) {
Connection connection;
int mf;
int ok;
word terr;
2019-07-07 20:32:31 +00:00
--argc;
++argv;
d_flag = 0;
for (; argc; --argc, ++argv) {
unsigned char c = **argv;
if (c != '-') break;
if (!strcmp(*argv, "-d")) {
d_flag = 1;
continue;
}
}
if (argc < 1) {
fputs("Usage: dict [-d] word...\n", stderr);
2018-11-13 00:38:22 +00:00
exit(1);
2019-07-07 20:32:31 +00:00
}
mf = StartUpTCP(DisplayCallback);
2018-11-13 00:36:34 +00:00
if (mf < 0) {
2019-07-07 20:32:31 +00:00
fputs("Marinetti 3.0b11 or greater is required.\n", stderr);
2018-11-13 00:36:34 +00:00
exit(1);
}
2018-11-13 00:38:22 +00:00
ok = ConnectLoop("dict.org", 2628, &connection);
2018-11-13 00:36:34 +00:00
if (ok) {
2018-11-13 00:38:22 +00:00
unsigned i;
int ok;
ok = client(connection.ipid);
if (ok == 0) {
2019-07-07 20:32:31 +00:00
for (i = 0; i < argc; ++i) {
2018-11-13 00:38:22 +00:00
ok = define(connection.ipid, argv[i], NULL);
if (ok < 0)
break;
}
}
2018-11-13 00:36:34 +00:00
2018-11-13 00:38:22 +00:00
quit(connection.ipid);
CloseLoop(&connection);
}
2018-11-13 00:36:34 +00:00
ShutDownTCP(mf, false, DisplayCallback);
return 0;
}