home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
rtsi.com
/
2014.01.www.rtsi.com.tar
/
www.rtsi.com
/
OS9
/
OSK
/
TELECOM
/
OSKBox.lzh
/
MAILBOX
/
CC
/
host.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-10-20
|
17KB
|
719 lines
#include <stdio.h>
#include <sgstat.h>
#include <signal.h>
#include <setjmp.h>
#include <errno.h>
#define ESC 27
#define MAX_CHANNEL 12
#define MAXPAC 236 /* anything bigger and NET/ROM will split it */
/* channel status values */
#define DISCONNECTED 0
#define DISCONNECTING 1
#define TERMINATE 2
#define CONNECTED 3
#define MANUAL 4
/* responses from G command */
#define OK 0
#define OK_MSG 1
#define BAD_MSG 2
#define STATUS 3
#define MON_HDR1 4
#define MON_HDR2 5
#define MON_INFO 6
#define CON_INFO 7
int modem;
struct sgbuf modem_opt, oldm_opt;
unsigned char outbuff[300], inbuff[300];
int signalman(), quit = 0;
int monitor, beacon, command;
struct {
int status;
int process;
int path_in, path_out;
int cpath_in, cpath_out;
int o_buffsize;
unsigned char o_linebuff[MAXPAC];
int i_buffsize;
unsigned char i_linebuff[MAXPAC];
} tasks[MAX_CHANNEL + 1];
int channelnum;
jmp_buf resync;
char portstr[33];
main (argc, argv)
char *argv[];
{
int i, cnum, type, len, active;
unsigned char *p;
int status_disp, data_disp, data_send, data_ack, tries, state;
char str[40];
int foo;
if (argc < 2) {
printf ("No modem specified\n");
exit (0);
}
if ((modem = open (argv[1], 3)) <= 0) exit (errno);
_gs_opt (modem, &oldm_opt);
if (oldm_opt.sg_class != 0) {
printf ("%s not an SCF-type device\n", argv[1]);
exit (0);
}
close (0); dup (modem); /* redirect standard I/O to TNC */
close (1); dup (modem); /* allows procs to show proc's port */
close (2); dup (modem);
modem_opt.sg_parity = oldm_opt.sg_parity;
modem_opt.sg_baud = oldm_opt.sg_baud;
modem_opt.sg_tbl = oldm_opt.sg_tbl;
_ss_opt (modem, &modem_opt);
_ss_enrts (modem);
intercept (signalman);
strcpy (portstr, argv[1]+1);
strcpy (str, "/pipe/monitor.");
strcat (str, portstr);
if ((monitor = create (str, 043, 013, 512)) == -1)
monitor = open (str, 3);
_ss_size (monitor, 0);
strcpy (str, "/pipe/beacon.");
strcat (str, portstr);
if ((beacon = create (str, 043, 013, 512)) == -1)
beacon = open (str, 3);
_ss_size (beacon, 0);
strcpy (str, "/pipe/command.");
strcat (str, portstr);
if ((command = create (str, 043, 013, 512)) == -1)
command = open (str, 3);
_ss_size (command, 0);
setpr (getpid (), 100);
setjmp (resync);
sync ();
put_command (0, "MN");
put_command (0, "Y3");
for (channelnum = 1; put_command (channelnum, "L") < 2; channelnum++)
;
channelnum--;
log ("initialization complete, %d channels", channelnum);
while (!quit) {
/* check for monitored packets */
active = 0;
while ((type = put_command (0, "G")) != OK) {
active = 1;
if (type == MON_HDR1 || type == MON_HDR2)
writemon (monitor, inbuff + 2, strlen (inbuff + 2));
else
writemon (monitor, inbuff + 3, inbuff[2] + 1);
}
if ((len = _gs_rdy (beacon)) > 0) {
/* assemble and send UI beacon packet */
active = 1;
len = min (len, 255);
outbuff[0] = 0;
outbuff[1] = 0;
outbuff[2] = len - 1;
read (beacon, outbuff + 3, len);
write (modem, outbuff, outbuff[2] + 4);
gethost (inbuff);
}
if (_gs_rdy (command) > 0)
check_command ();
for (cnum = channelnum; cnum > 0; cnum--)
if (tasks[cnum].process) break;
for (i = 1; i <= min (channelnum, cnum+1); i++) {
foo = 0;
/* check for packets on other channels */
while (1) {
if (foo++ > 99) {
log ("Too long in loop, type=%d, status=%d, proc=%d, paths=%d %d, ibsize=%d",
type, tasks[i].status, tasks[i].process,
tasks[i].path_in, tasks[i].path_out, tasks[i].i_buffsize);
tasks[i].i_buffsize = 0;
break;
}
if (tasks[i].i_buffsize && tasks[i].process)
type = CON_INFO; /* try to write previously received data */
else {
type = put_command (i, "G");
if (type == OK) break;
if (type == CON_INFO) {
/* put incomming data in buffer (may not fit yet) */
tasks[i].i_buffsize = inbuff[2] + 1;
movmem (inbuff+3, tasks[i].i_linebuff,
tasks[i].i_buffsize);
}
}
active = 1;
if (tasks[i].status == MANUAL) {
if (type == CON_INFO) {
if (_gs_size (tasks[i].path_in) -
_gs_rdy (tasks[i].path_in) < tasks[i].i_buffsize)
break; /* not enough space yet */
write (tasks[i].path_in, tasks[i].i_linebuff,
tasks[i].i_buffsize);
tasks[i].i_buffsize = 0;
}
else {
write (tasks[i].cpath_in, inbuff + 2,
strlen (inbuff + 2));
write (tasks[i].cpath_in, "\n", 1);
}
}
else if (tasks[i].status != DISCONNECTED) {
if (type == STATUS)
check_status (i);
else if (type == CON_INFO && tasks[i].process != 0) {
if (_gs_size (tasks[i].path_in) -
_gs_rdy (tasks[i].path_in) < tasks[i].i_buffsize)
break; /* not enough space yet */
write (tasks[i].path_in, tasks[i].i_linebuff,
tasks[i].i_buffsize);
for (p = tasks[i].i_linebuff;
p - tasks[i].i_linebuff < tasks[i].i_buffsize; p++)
if (*p == '\003')
kill (tasks[i].process, SIGINT);
tasks[i].i_buffsize = 0;
}
}
else
check_connect (i);
}
if (tasks[i].status > DISCONNECTING) {
put_command (i, "L");
scan_status (&status_disp, &data_disp, &data_send,
&data_ack, &tries, &state);
}
if (tasks[i].status == TERMINATE && data_ack == 0) {
log ("%d empty, disconnecting", i);
put_command (i, "D");
tasks[i].status = DISCONNECTING;
}
/* check for data from processes */
if (tasks[i].process != 0 &&
((len = _gs_rdy (tasks[i].path_out)) > 0 || tasks[i].o_buffsize) &&
data_send <= 8) {
int tlen;
if (len == -1) len = 0;
len = min (len, MAXPAC-tasks[i].o_buffsize);
tlen = len + tasks[i].o_buffsize;
outbuff[0] = i;
outbuff[1] = 0;
outbuff[2] = tlen - 1;
movmem (tasks[i].o_linebuff, outbuff + 3, tasks[i].o_buffsize);
if (len)
read (tasks[i].path_out, outbuff + 3 + tasks[i].o_buffsize, len);
for (p = outbuff + 3 + tlen - 1; p > outbuff + 3; p--)
if (*p == '\n') break;
if (*p == '\n') {
/* Send up to newline, save the rest for later */
tasks[i].o_buffsize = tlen - ((p - (outbuff + 3)) + 1);
movmem (p+1, tasks[i].o_linebuff, tasks[i].o_buffsize);
outbuff[2] -= tasks[i].o_buffsize;
write (modem, outbuff, outbuff[2] + 4);
if (gethost (inbuff) == 2) {
log ("%d: %s", inbuff[0], inbuff + 2);
goto full;
}
active = 1;
}
else if (tasks[i].o_buffsize > 0 && len == 0) {
/* No newline, no new data, send saved data */
write (modem, outbuff, outbuff[2] + 4);
if (gethost (inbuff) == 2) {
log ("%d: %s", inbuff[0], inbuff + 2);
goto full;
}
tasks[i].o_buffsize = 0;
active = 1;
}
else {
/* No newline, save the data for next time */
full: tasks[i].o_buffsize = tlen;
movmem (outbuff + 3, tasks[i].o_linebuff, tlen);
}
}
if (tasks[i].process != 0 && tasks[i].status == MANUAL &&
(len = _gs_rdy (tasks[i].cpath_out)) > 0) {
char str[80];
readln (tasks[i].cpath_out, str, 80);
str[len - 1] = '\0';
if (put_command (i, str) != 0) {
write (tasks[i].cpath_in, inbuff + 2,
strlen (inbuff + 2));
write (tasks[i].cpath_in, "\n", 1);
}
}
}
check_children ();
if (!active)
sleep (1);
}
log ("terminating host mode");
put_command (0, "MN");
put_command (0, "Y0");
put_command (0, "JHOST0");
_ss_size (monitor, 0);
close (monitor);
_ss_size (beacon, 0);
close (beacon);
_ss_opt (modem, &modem_opt);
_ss_dsrts (modem);
exit (0);
}
check_connect (channel)
{
char *p;
char w[20];
char sta[10];
char digi[8][10];
char *argv[10];
int i, d = 0;
int std_in, std_out, std_err;
extern int os9fork();
extern char **environ;
if (inbuff[1] != 3) return;
p = (char *)inbuff + 2;
p += scanword (p, w);
p += scanword (p, w);
if (strcmp (w, "CONNECTED") != 0) return;
p += scanword (p, w);
if (strcmp (w, "to") != 0) return;
p += scanword (p, sta);
if (*p) {
p += scanword (p, w);
if (strcmp (w, "via") != 0) return;
for (d = 0; *p; d++)
p += scanword (p, digi[d]);
}
log ("%s on channel %d", sta, channel);
argv[0] = "mailbox"; /* APPLICATION SPECIFIC: Substitute appropriate program */
argv[1] = sta;
argv[2] = portstr;
for (i = 0; i < d; i++)
argv[i+3] = digi[i];
argv[i+3] = NULL;
std_in = dup (0);
close (0);
if (create ("/pipe", 043, 013, 2048) == -1) {
tasks[channel].status = TERMINATE;
log ("error %d creating pipe (1)", errno);
return;
}
std_out = dup (1);
close (1);
if (create ("/pipe", 043, 013, 2048) == -1) {
tasks[channel].status = TERMINATE;
log ("error %d creating pipe (2)", errno);
return;
}
std_err = dup (2);
close (2);
dup (1);
tasks[channel].process =
os9exec (os9fork, argv[0], argv, environ, 0, 128, 3);
tasks[channel].path_in = dup (0);
tasks[channel].path_out = dup (1);
tasks[channel].status = CONNECTED;
tasks[channel].cpath_in = tasks[channel].cpath_out = 0;
close (0); dup (std_in); close (std_in);
close (1); dup (std_out); close (std_out);
close (2); dup (std_err); close (std_err);
if (tasks[channel].process <= 0) {
/* fork didn't succeed */
log ("fork failed");
closepaths (channel);
tasks[channel].process = 0;
tasks[channel].status = TERMINATE;
}
if (strncmp (sta, "KB6GOZ", 6) == 0) { /* FOO */
put_command (channel, "W64");
}
}
check_status (channel)
{
char *p, w[20];
p = (char *)inbuff + 2;
p += scanword (p, w);
p += scanword (p, w);
if (strcmp (w, "LINK") == 0) {
p += scanword (p, w);
if (strcmp (w, "FAILURE") != 0)
return;
}
else if (strcmp (w, "DISCONNECTED") != 0)
return;
log ("disconnect %d", channel);
tasks[channel].status = DISCONNECTED;
if (tasks[channel].process != 0) {
if (tasks[channel].path_in) {
close (tasks[channel].path_in);
tasks[channel].path_in = 0;
}
tasks[channel].i_buffsize = 0;
tasks[channel].o_buffsize = 0;
}
}
scan_status (a, b, c, d, x, f)
int *a, *b, *c, *d, *x, *f;
{
char *p, w[20];
p = (char *)inbuff + 2;
p += scanword (p, w);
*a = atoi (w);
p += scanword (p, w);
*b = atoi (w);
p += scanword (p, w);
*c = atoi (w);
p += scanword (p, w);
*d = atoi (w);
p += scanword (p, w);
*x = atoi (w);
p += scanword (p, w);
*f = atoi (w);
}
check_children ()
{
int i, j, k;
start:
for (i = 1; i <= channelnum; i++)
if (tasks[i].process != 0 && _gs_eof (tasks[i].path_out) == 1 &&
tasks[i].status != MANUAL) {
log ("process %d eof", tasks[i].process);
j = wait (0);
if (j == -1) return;
for (k = 0; k < channelnum; k++)
if (tasks[k].process == j) {
tasks[k].process = 0;
if (tasks[k].status > TERMINATE)
tasks[k].status = TERMINATE;
closepaths (k);
}
goto start;
}
}
check_command ()
{
char str[40], *p;
int len, pid, channel;
len = readln (command, str, 40);
str[len - 1] = '\0';
pid = atoi (str + 1);
if (*str == 'o') {
/* open a manual control channel for this process */
for (channel = channelnum; channel > 0; channel--)
if (tasks[channel].process == 0) break;
if (channel == 0) return;
sprintf (str, "/pipe/data_in.%d", pid);
if ((tasks[channel].path_in = create (str, 043, 013, 2048)) == -1)
goto error;
sprintf (str, "/pipe/data_out.%d", pid);
if ((tasks[channel].path_out = create (str, 043, 013, 2048)) == -1)
goto error;
sprintf (str, "/pipe/ctl_in.%d", pid);
if ((tasks[channel].cpath_in = create (str, 043, 013, 2048)) == -1)
goto error;
sprintf (str, "/pipe/ctl_out.%d", pid);
if ((tasks[channel].cpath_out = create (str, 043, 013, 2048)) == -1)
goto error;
tasks[channel].process = pid;
tasks[channel].status = MANUAL;
return;
}
else if (*str == 'c') {
/* close a previously opened control channel */
for (channel = 1; channel <= channelnum; channel++)
if (tasks[channel].process == pid) break;
if (channel > channelnum) return;
if (tasks[channel].status != MANUAL) return;
closepaths (channel);
tasks[channel].status = DISCONNECTED;
tasks[channel].process = 0;
return;
}
else if (*str == 'm') {
put_command (0, str);
return;
}
else if (*str == 'u') {
*str = 'c';
put_command (0, str);
return;
}
else
return;
error:
closepaths (channel);
log ("error %d creating pipe (3)", errno);
return;
}
closepaths (channel)
{
if (tasks[channel].path_in) {
close (tasks[channel].path_in);
tasks[channel].path_in = 0;
}
if (tasks[channel].path_out) {
close (tasks[channel].path_out);
tasks[channel].path_out = 0;
}
if (tasks[channel].cpath_in) {
close (tasks[channel].cpath_in);
tasks[channel].cpath_in = 0;
}
if (tasks[channel].cpath_out) {
close (tasks[channel].cpath_out);
tasks[channel].cpath_out = 0;
}
tasks[channel].i_buffsize = 0;
tasks[channel].o_buffsize = 0;
}
scanword (s, d)
char *s, *d;
{
int num = 0;
while (*s && *s == ' ') {
s++;
num++;
}
while (*s && *s != ' ') {
*d++ = *s++;
num++;
}
*d = '\0';
return (num);
}
writemon (path, str, len)
char *str;
{
if (_gs_size (path) - _gs_rdy (path) > len) {
write (path, str, len);
write (path, "\n", 1);
}
}
put_command (channel, cmd)
char *cmd;
{
outbuff[0] = channel;
outbuff[1] = 1;
outbuff[2] = strlen (cmd) - 1;
strcpy (outbuff+3, cmd);
write (modem, outbuff, outbuff[2] + 4);
return (gethost (inbuff));
}
int syncing = 0;
sync ()
{
int i;
char *syncstr = "INVALID COMMAND";
syncing = 1;
if (write (modem, "\021\030\033", 3) == -1) exit (errno);
tsleep ((1<<31) | (3*25));
while (1) {
tsleep ((1<<31) | (25*2));
if ((i = _gs_rdy (modem)) == -1) break;
if (read (modem, inbuff, i) == -1) exit (errno);
}
if (write (modem, "JHOST 1\r", 8) == -1) exit (errno);
while (1) {
tsleep ((1<<31) | (25*2));
if ((i = _gs_rdy (modem)) == -1) break;
if (read (modem, inbuff, i) == -1) exit (errno);
}
while (1) {
while (_gs_rdy (modem) == -1) {
if (write (modem, "\001", 1) == -1) exit (errno);
tsleep ((1<<31) | (25*2));
}
gethost (inbuff);
if (*inbuff == 1 && *(inbuff+1) == 2 &&
strncmp (inbuff+2, syncstr, strlen (syncstr)) == 0)
break;
}
syncing = 0;
}
gethost (buff)
unsigned char *buff;
{
unsigned char *p;
int i;
struct sgbuf errbuf;
/* while (_gs_rdy (modem) < 2)
; */
i = read (modem, buff, 2);
if (!syncing && *buff > MAX_CHANNEL || *(buff+1) > 7) {
log ("resync %d %d", *buff, *(buff+1));
longjmp (resync, 1);
}
if (i != 2)
if (i < 0) {
_gs_opt (modem, &errbuf);
log ("error %d %d", errno, errbuf.sg_err);
}
else log ("%d read %d", 1, i);
if (errno == 2) {
quit = 1;
return 0;
}
if (buff[1] == 0)
return (0);
else if (buff[1] < 6) {
p = buff+2;
while (1) {
i = read (modem, p, 1);
if (i != 1)
if (i < 0) {
_gs_opt (modem, &errbuf);
log ("error %d %d", errno, errbuf.sg_err);
}
else log ("%d read %d", 2, i);
if (i != 1) break;
if (*p == '\0') break;
p++;
}
}
else {
i = read (modem, buff+2, 1);
if (i != 1)
if (i < 0) {
_gs_opt (modem, &errbuf);
log ("error %d %d", errno, errbuf.sg_err);
}
else log ("%d read %d", 3, i);
if (i == 1) i = read (modem, buff+3, buff[2]+1);
if (i != buff[2]+1)
if (i < 0) {
_gs_opt (modem, &errbuf);
log ("error %d %d", errno, errbuf.sg_err);
}
else log ("%d read %d", buff[2]+1, i);
}
if (errno == 2) {
quit = 1;
return 0;
}
return (buff[1]);
}
/* Debugging code. Not used in normal operation.
host ()
{
char line[100], *p;
while (1) {
printf ("> ");
if (!gets (line)) return (0);
p = line;
if (*p == '*') {
outbuff[1] = 1;
p++;
}
else
outbuff[1] = 0;
if (*p <'0' || *p > '4') {
printf ("Illegal channel number\n");
continue;
}
outbuff[0] = *p - '0';
p++;
outbuff[2] = strlen (p) - 1;
strcpy (outbuff+3, p);
write (modem, outbuff, outbuff[2] + 4);
gethost (inbuff);
dump (inbuff);
}
}
dump (buff)
char *buff;
{
if (buff[1] == 0)
printf ("%d: <null>\n", buff[0]);
else if (buff[1] < 6)
printf ("%d: <%d> %s\n", buff[0], buff[1], buff+2);
else
printf ("%d: <%d> '%s'\n", buff[0], buff[1], buff+3);
}
*/
signalman (signal)
{
switch (signal) {
case SIGQUIT:
quit = 1;
break;
default:
break;
}
}
min (a, b)
{
return ((a < b) ? a : b);
}
log (s, a, b, c, d, e, f, g, h)
char *s;
{
static int f = 0;
char *name = "/pipe/hostlog.";
char line[80];
strcpy (line, name);
strcat (line, portstr);
if (f == 0) {
if ((f = create (line, 043, 013, 512)) == -1)
f = open (line, 3);
_ss_size (f, 0);
}
sprintf (line, s, a, b, c, d, e, f, g, h);
writemon (f, line, strlen (line));
}
movmem (from, to, count)
register char *from, *to;
register int count;
{
if (from > to)
while (count--)
*to++ = *from++;
else {
from += count;
to += count;
while (count--)
*--to = *--from;
}
}