Initial commit

This commit is contained in:
root@procul
2021-04-15 13:31:59 -05:00
commit 278a90f7ce
57951 changed files with 34606208 additions and 0 deletions
@@ -0,0 +1,171 @@
/*
Fido13 -- main function
3 Sep 93
Tom Jennings
tomj@wps.com
(31 Aug 93)
copyright 1993
*/
#include <stdio.h>
#include "fido.h"
/* Global static nonsense. */
int output_line = 0; /* lines output so far (reset at pause
and input) */
int output_col = 0; /* chars since a newline */
struct _state *current_state; /* ptr to state we're executing */
struct _state *bliss; /* the top of the state-machine */
/* Main state machine execution. */
main() {
char c;
struct _state *s;
unsigned menu; /* current menu (menu) */
char *input();
unsigned load_machine();
bliss= (struct _state *) NULL; /* flag as unallocated */
if (load_machine("fido.dat")) /* load up Fido */
exit(1); /* ERROR! */
current_state= bliss; /* just so I could say that */
while (1) {
c= *input(); c= tolower(c); /* get command, */
for (s= current_state, menu= s-> menu; s-> menu == menu; ++s) {
if (c == tolower(*s-> input)) { /* (check only first character) */
execute(s-> action); /* it's ours! do it */
current_state= s-> next; /* change state (maybe ourself) */
c= NULL; /* mark input as used */
break;
}
if (c) output("\"%s\" is not a command\n",c);
}
}
}
/* Execute a state; if there is an action exec it. */
execute(a)
char *a;
{
char buff[200];
char *args[64];
parse(a, buff, sizeof(buff), args); /* break it up, */
fork_u(args); /* execute it. */
}
/* Parse the command string, for example:
Set ptr args[n]: 0 1 2 3 4
| | | | |
v v v v v
/bin/mail -s "arg with spaces" user@domain.com
The last arg[] is a NULL ptr. parse() modifies the input string. */
parse(in, buff, len, args)
char *in; /* text we're parsing */
char *buff; /* processed strings... */
unsigned len; /* max. length of string */
char **args; /* ... at these pointers */
{
unsigned n;
while (*in && (len > 1)) {
*args++= buff; /* point to where arg will go */
n= copyqstr(&in, buff, len); /* copy one arg */
buff += n; /* where next one goes */
len -= n; /* how much room left */
}
*args= NULL; /* terminate w/ null ptr */
}
/* Execute the command. */
fork_u(args)
char **args;
{
int pid, status;
if ((pid= fork()) < 0) { /* oops! */
perror("fido: fork:");
exit(1);
}
if (pid == 0) { /* if child... */
execv(*args, args);
perror(*args);
exit(1);
}
while (wait(&status) != pid); /* ... parent */
}
/* Get input from the user, returning a pointer to the next token. If
none, generate a prompt from the current state table, input a line of
text. */
char *
input() {
char *strtok();
static char linebuff[256] = ""; /* human-input line buffer */
static char *lp = linebuff; /* ptr into it */
char *cp;
struct _state *s;
while (1) {
cp= strtok(lp, ", \t;"); /* see if there's more */
lp= NULL; /* (for 1 -- Nth calls) */
if (cp != NULL) return(cp); /* yup */
display_states(); /* generate the prompt */
output_line= 0; /* reset page pause */
fgets(linebuff, (size_t)sizeof(linebuff), stdin);
lp= linebuff; /* repeat, with new input */
}
}
/* Output text to the console. */
output(s)
char *s;
{
while (*s) switch (*s) {
case '\n': output_col= 0;
default: fputs(s, stdout); ++output_col;
}
fflush(stdout);
}
/* Output all the state names, ie. the prompt. current_state points to the first state in
this menu, output all state names in this menu. */
display_states() {
struct _state *t;
unsigned menu;
for (t= current_state, menu= t-> menu;; ) {
if (output_col + strlen(t-> name) > 40) /* narrow prompt */
output("\n");
output(t-> name); /* state name */
if (++t-> menu != menu) break; /* if the last one, stop */
output(", "); /* else a comma and space for the next */
}
}
@@ -0,0 +1,40 @@
#
# Fido/FidoNet 12t user interface
#
#statename:
# name (prompt) input action next state
#
# Main section. Just palms off to other states, mostly.
#
main:
"M)essage-Section" M messages
"F)ile-Section" F files
"B)ulletins" B bulletins
"S)tatistics" S df main
"C)hange-settings" C change
"V)ersion" V echo "Fido version 13"
"G)oodbye" G logout
#
# Message section. Stubbed for now.
#
messages:
"E)LM" E elm
"G)oodbye" G logout
"M)ain-Menu" M main
#
# Files section. Stubbed also.
#
files:
"F)iles" F less files.bbs
"D)ownload" D less notyet
"U)pload" U less notyet
"A)rea-change" A less notyet
"S)tatistics" S df
"G)oodbye" G logout
"M)ain-menu" M main
@@ -0,0 +1,26 @@
/*
Fido13 -- main include file
3 Sep 93
Tom Jennings
tomj@wps.com
(3 Sep 93)
copyright 1993
*/
#include <string.h>
/* State machine data structure. */
struct _state {
unsigned menu; /* which group this state belongs to */
char *name; /* name of state, also prompt */
char *input; /* input character */
char *action; /* command to execute */
struct _state *next; /* next state to switch to */
};
extern struct _state *current_state, *bliss;
Binary file not shown.
@@ -0,0 +1,21 @@
# UNIX_VERSION
Files from the Uncompleted UNIX Version of FidoNet by Tom Jennings
## FILES
=> gemini://informis.land/textfiles/bbs/FIDONET/JENNINGS/PROGRAMS/UNIX_VERSION/fido.c.txt [ 3881] FidoNet Version 13 (Unix Version): Main Function (September 3, 1993)
=> gemini://informis.land/textfiles/bbs/FIDONET/JENNINGS/PROGRAMS/UNIX_VERSION/fido.dat.txt [ 697] FidoNet Version 13 (Unix Version): Fidonet User Interface Data File
=> gemini://informis.land/textfiles/bbs/FIDONET/JENNINGS/PROGRAMS/UNIX_VERSION/fido.h.txt [ 463] FidoNet Version 13 (Unix Version): Main Include File (September 3, 1993)
=> gemini://informis.land/textfiles/bbs/FIDONET/JENNINGS/PROGRAMS/UNIX_VERSION/fido.txt [ 42462] BINARY: Fidonet Executable
=> gemini://informis.land/textfiles/bbs/FIDONET/JENNINGS/PROGRAMS/UNIX_VERSION/load_machine.c.txt [ 7134] FidoNet Version 13 (Unix Version): Load/Initialize State Machine (September 3, 1993)
=> gemini://informis.land/textfiles/bbs/FIDONET/JENNINGS/PROGRAMS/UNIX_VERSION/makefile.txt [ 399] FidoNet Version 13 (Unix Version): Makefile
=> gemini://informis.land/textfiles/bbs/FIDONET/JENNINGS/PROGRAMS/UNIX_VERSION/menu_control.c.txt [ 4285] FidoNet Version 13 (Unix Version): Menu Control Routines (April 24, 1991)
=> gemini://informis.land/textfiles/bbs/FIDONET/JENNINGS/PROGRAMS/UNIX_VERSION/string.c.txt [ 3162] FidoNet Version 13 (Unix Version): Command Argument and DOS Path Manipulation Functions (June 7, 1983)
@@ -0,0 +1,239 @@
/*
Fido13 -- load/initialize state machine
3 Sep 93
Tom Jennings
tomj@wps.com
(3 Sep 93)
copyright 1993
*/
#include <stdio.h>
#include "fido.h"
/* State machine string sizes, limited for space/performance reasons, to mamimum... */
#define MAXLABEL 16 /* ...of state label */
#define MAXNAME 30 /* ...of state name */
#define MAXINPUT 1 /* ...of user input */
#define MAXACTION 80 /* ...of action */
/* Symbol table, holding defined menu names (groups, flagged with ':label') */
struct _symtbl { /* state label table */
char name[MAXLABEL + 1];/* name of label */
struct _state *state; /* ptr to state it references */
};
static struct _symtbl *symtbl; /* our symbol table */
static unsigned symtbln; /* number of entries (for size calc) */
unsigned staten; /* number of states loaded (size calc, etc) */
unsigned group; /* group of states (making up a menu), 1 - N */
struct _state *find_state();
/* Load states into memory from a text file; return 0 if error. */
load_machine(fn)
char *fn;
{
FILE *f;
short foo; /* error detector */
int i;
char *cp,buff[400]; /* line buffer, etc */
unsigned lineno; /* input file line number */
if ((f= fopen(fn,"r")) == NULL) {
fprintf(stderr, "Can't find config file \"fido.conf\"\n");
return(0);
}
current_state= bliss= (struct _state *) malloc(0);/* set a ptr anyways */
staten= 0; /* no states yet */
group= 1; /* start group with 1 */
symtbl= (struct _symtbl *) malloc(0); /* empty symbol table */
symtbln= 0;
for (lineno= 0, foo= 1; foo;) {
if (fgets(buff, sizeof(buff), f) == NULL) break;
++lineno; /* count another line */
for (cp= buff; *cp; ++cp) /* strip newlines */
if (*cp == '\n') *cp= '\0';
if (! buff[0]) continue; /* ignore blank lines */
if (buff[0] == '#') continue; /* and comments */
if (buff[0] == ':') { /* if a label definition */
foo= add_label(&buff[1], lineno); /* remember this label */
++group; /* new group/menu number */
continue;
}
foo= add_state(buff, lineno, group); /* add state, check errors */
}
fclose(f);
return(foo);
}
/* Add a new label to the symbol table; return 0 if it already exists. */
add_label(name, lineno)
char *name;
unsigned lineno;
{
unsigned i;
char buff[MAXLABEL + 1];
name[MAXLABEL + 1]= '\0'; /* possibly truncate */
cpyarg(buff, name); /* clean copy */
for (i= 0; i < symtbln; i++) {
if (strcmp(symtbl[i].name, buff) == 0) {
fprintf(stderr,"fido: label \"%s\" previously defined\n",
symtbl[i].name);
return(0); /* return error */
}
} /* else add a new one */
symtbl= (struct _symtbl *) realloc((void *) symtbl, (++symtbln * sizeof(struct _symtbl)));
strcpy(symtbl[symtbln].name, buff); /* add a new table entry */
symtbl[symtbln].state= current_state; /* refers to this state */
return(1); /* return no-error */
}
/* Given a label name, return a pointer to the associated state or 0 for error */
struct _state *
find_state(name)
char *name;
{
int i;
char buff[MAXLABEL + 1];
name[MAXLABEL + 1]= '\0'; /* truncate it */
cpyarg(buff, name); /* clean copy */
for (i= 0; i < symtbln; i++)
if (strcmp(buff, symtbl[i].name) == 0) return(symtbl[i].state);
return((struct _state *) 0); /* not found! */
}
/* Add a new state to the in-memory state machine; if error return 0. */
add_state(s, lineno, group)
char *s;
unsigned lineno; /* line number, for error reports */
unsigned group; /* group/menu number */
{
char buff[MAXLABEL + 1];
struct _state *t;
bliss= (struct _state *) realloc((void *) bliss, (++staten * sizeof(struct _state)));
if (bliss == NULL) {
fprintf(stderr,"Fido: realloc in add_state sez we're outa memory!");
return(0);
}
current_state-> next= current_state; /* assume no "next" */
current_state-> menu= group; /* which menu group */
if (add_field(&s, &current_state-> name, 1, MAXNAME, "state name", lineno))
return(0);
if (add_field(&s, &current_state-> input, 1, MAXINPUT, "input character", lineno))
return(0);
if (add_field(&s, &current_state-> action, 0, MAXACTION, "action", lineno))
return(0);
if (add_field(&s, &buff, 0, MAXLABEL, "next state", lineno))
return(0);
/* 'next state' is optional; if given find the target state, return error if not found.
If not specified this state points to itself. */
if (*buff) current_state-> next= t= find_state(buff);
current_state= &bliss[staten]; /* new "current" state */
return((int) t); /* return 0 if error */
}
/* Given a ptr to the line read from the input file, fill out one field in a structure,
allocating space for it as necessary, and error-checking its length. Returns 0 if OK. */
add_field(s, field, minimum, maximum, what, lineno)
char **s; /* ptr to input string ptr */
char **field; /* ptr to field string ptr */
unsigned minimum, maximum; /* min, max field lengths */
char *what; /* name of field, for error reports */
unsigned lineno; /* line number, for error reports */
{
unsigned n;
char buff[101];
n= copyqstr(s, buff, sizeof(buff)); /* process string */
if (error_check(n, minimum, maximum, what, lineno)) /* check length */
return(1);
*field= (char *) malloc(n + 1); /* allocate space for string */
if (*field == NULL) {
fprintf(stderr, "malloc (%s) sez we're outa memory!\n", what);
return(1);
}
strcpy(*field, buff); /* copy into place */
return(0);
}
/* Error-check the string length. Return 0 if OK. */
error_check(n, minimum, maximum, what, lineno)
unsigned n, minimum, maximum;
char *what; /* name of field, for error reports */
unsigned lineno; /* line number, for error reports */
{
if (n < minimum) fprintf(stderr, "%s is too short in line #%u\n", what, lineno);
else if (n > maximum) fprintf(stderr, "%s is too long (missing quote?) in line #%u\n", what, lineno);
else return(0);
return(1); /* get that? */
}
/* Copy a (possibly) quoted string, up to the closing quote or terminating comma. Returns
the number of characters stored in the output string, and leaves the input pointer pointing
to the character following the last one used. This accepts quoted strings (if the firs
tnon-blank character is a ") or single, isolated words. */
copyqstr(s, dp, len)
char **s; /* ptr to input pointer */
char *dp; /* dest. pointer */
unsigned len; /* max. string length */
{
char run, q, *ip;
unsigned l; /* chars stored so far */
ip= *s; /* get string ptr */
l= 0;
while (*ip) {
if ((*ip != ' ') && /* skip leading blanks, */
(*ip != '\t')) /* and tabs */
break;
}
if ((q= *ip) == '"') ++ip; else q= ','; /* if " skip, else set to , */
while (*ip) {
if (*ip == '\\') { /* if a literal */
if (*(ip + 1)) *dp++= *++ip; /* copy anything */
}
if (*ip == q) break; /* stop on comma/quote */
if ((q != '"') && (*ip == ' ')) break; /* stop on trailing space if not quoted */
if (l < len) *dp++= *ip++; /* copy the character */
if (l < len) ++l; /* count it */
}
*dp= '\0'; /* terminate it */
while (*ip) if (*ip++ == ',') break; /* skip anything before comma */
*s= ip; /* set new ptr */
return(l);
}
@@ -0,0 +1,26 @@
# makefile for Fido
#
CFLAGS= -O
CC = cc -c
LD = cc # Link command
LDFLAGS =
CPP = $(CC) -E
DBG = -O
ASM = $(CC) -c # Assembler command
# Duh sore-ces
OBJS = fido.o load_machine.o string.o
default: $(OBJS)
$(LD) -o fido $(OBJS) $(LDFLAGS)
fido.o : fido.c fido.h
$(CC) fido.c
load_machine.o : load_machine.c fido.h
$(CC) load_machine.c
string.o : string.c
$(CC) string.c
@@ -0,0 +1,131 @@
#include "autotrak.h"
#include <ascii.h>
#include "function.h"
#include "extmem.h"
/*
Tom Jennings
Communitree Group
1047 Sutter St
San Francisco CA 94109
(415)-441-3088
mru: 24 Apr 91
new: 25 Jun 90
Menu execution engine.
*/
extern MENU initscrn; /* top of the tree -- defined in MENU.C */
static MENU *last_menu = NOMENU; /* last menu drawn */
static WINDOW *top_window; /* first window inited this menu */
static short first_time; /* flag first execution */
/* This is the high level state machine engine. */
void engine() {
int i;
/* These windows are drawn before all others, and are never removed, since
they are in common with all menus. (The simulate and debug windows overwrite
them, but are restored upon their returns.) (Oh yeah -- upon exit to DOS,
we brute-force restore the original 'screen' data. */
init_window(&screen); /* clear the screen */
init_window(&fkeyback); /* draw the Fkey background */
init_window(&menust); /* menu name */
for (i= 0; i < FKEYS; i++) { /* draw all the Fkey boxes */
init_window(fkeys[i]);
}
top_window= fkeys[--i]; /* point to last window */
/* Draw the main menu now, then fall into the main menu execution loop. */
current_menu= &initscrn; /* set as new current menu */
/* Poll for a keyboard character. If there is a function for this menu, execute
it, passing it the keystroke. (If it has a use within that function, it's
returned as 0. It also allows the menu function to 'lookahead' to see
if it is about to be closed (ie. keystroke == F7.)) Check to see if its
a change-menu key (ie. an Fkey), if so, change menus (and return the
character as 0.) If after all that the key isnt used, it was an illegal key.
Also gives the function (if any) a first-time flag, to do one time
initialization. */
while (1) {
draw_menu(); /* (possibly) draw the menu */
current_char= keyhit(); /* get a kbd char (else 0) */
switch (current_char) { /* some are global */
case KEY_CTL_F10:
case KEY_CTL_F11:
exitdos(); break;
case KEY_F12: /* help */
notsimulated();
current_char= NUL;
}
if ((int)(current_menu-> func)) /* if a function defined, */
(*current_menu-> func)(first_time); /* execute it */
first_time= 0; /* then clear it */
switch_state(); /* possibly switch state */
if (current_char != NUL) beep(); /* unused (illegal) character */
}
}
/* Given the current keystroke (or 0) and the current menu definition,
change to another menu as indicated. When we switch menus, the millisecond
clock is cleared (used by functions to do "processing") and zaps the
last-day and second counters so that the clock will update immediately,
if it is used. */
switch_state() {
int i;
switch (current_char) {
case KEY_F1: i= 0; break; /* convert Fkeys */
case KEY_F2: i= 1; break; /* to indices */
case KEY_F3: i= 2; break;
case KEY_F4: i= 3; break;
case KEY_F5: i= 4; break;
case KEY_F6: i= 5; break;
case KEY_F7: i= 6; break;
default: return; /* (no change) */
}
if (current_menu-> fk[i].next != NOMENU) { /* if Fkey defined */
current_menu= current_menu-> fk[i].next;/* change states */
draw_menu();
current_char= NUL; /* keystroke eaten */
}
}
/* Given a menu structure, fill in the screen to match. Unlink any
previous screen (there will be except the first time). */
static draw_menu() {
int i;
if (current_menu == last_menu) /* if no change, */
return; /* do nothing */
cursoroff(); /* dont need this */
if (top_window-> next_window) /* if there is one, */
unlinkchain(top_window-> next_window); /* unlink previous windows */
w_fill(&menust,current_menu-> title); /* display menu name */
status(current_menu-> stat); /* fill the status box */
for (i= 0; i < FKEYS; i++) { /* draw all the Fkey boxes */
w_fill(fkeys[i],current_menu-> fk[i].text);
}
for (i= 0; current_menu-> window_list[i] != NOWINDOW; i++) {
init_window(current_menu-> window_list[i]); /* init all the optional windows */
}
for (i= 0; i < sizeof(current_menu-> data); i++)
current_menu-> data[i]= 0; /* initialize the data area */
millisec= 0L; /* reset the timer */
last_sec= -1; /* trigger clock display */
first_time= 1; /* flag the first execution */
last_menu= current_menu; /* remember it */
}
@@ -0,0 +1,155 @@
#include <ctype.h>
char *next_arg();
char *skip_delim();
char *strip_path();
/*
Command argument and DOS path manipulation functions.
T. Jennings 7 June 83
--------------- Command Tail Processing Functions ---------------
This next set of functions are meant to be used together. Examples
on their use follows.
int num_args(string) Returns the number of args in the string, seperated
by delims (see delim(), below). Leading delimiters
are ignored.
char *next_arg(string) Returns a pointer to the next arg, delimited
by a delim, skipping over the current arg. Use via
ptr= nextarg(ptr) to skip to each argument. All
switches at the end of the current arg are skipped.
char *skip_delim(string) Skips leading delims in a string. returns a pointer.
cpyarg(to,from) Copies a string, up to the next delim or switch.
Leading and trailing delimiters are stripped (from
the output string) and a null terminator is added.
after cpyarg() FROM: foo/b foobar fipple
TO: foo
delim(c) Returns true if the character is a delimiter.
Nulls are not considered a delimiter. The list of
delimiters is contained in the array '_dlmlst', and
can be changed via newdelim().
newdelim(s) Replace the list of delimiters. The string 's' must
be less than 20 chars. (Not checked.)
stolower(s) Convert a string to all lower or upper case.
stoupper(s)
*/
/* Return the number of args left in the string. */
short num_args(string)
char *string;
{
int count;
count= 0;
string= skip_delim(string); /* skip leading blanks, */
while (*string) {
++count; /* count one, */
string= next_arg(string); /* find next, */
}
return(count);
}
/* Return a pointer to the next argument in the string. */
char *
next_arg(string)
char *string;
{
while ((!delim(*string)) && *string) /* skip this one, */
++string; /* up to delim, */
string= skip_delim(string); /* then skip delims, */
return(string);
}
/* Skip over the leading delimiters in a string. */
char *
skip_delim(string)
char *string;
{
while (delim(*string) && *string) {
++string;
}
return(string);
}
/* Copy the string to the destination array, stopping if we find one
of our delimiters. */
void
cpyatm(to,from)
char *to;
char *from;
{
while ( (!delim(*from)) && *from)
*to++= *from++;
*to= '\0';
}
/* Copy the string to the destination array, stopping if we find one
of our delimiters or switches. */
void
cpyarg(to,from)
char *to;
char *from;
{
while ( (!delim(*from)) && (*from != '/') && *from)
*to++= *from++;
*to= '\0';
}
/* ----- List of legal delimiters. This is the default list ----- */
static char _dlmlst[20] = {" \t,"}; /* space, tab, comma */
/* Return true if the character is a delimiter from the list above. */
delim(c)
char c;
{
char *cp;
for (cp= _dlmlst; *cp;) if (c == *cp++) return(1);
return(0);
}
/* Change the list of delimiters. */
void newdelim(s)
char *s;
{
strcpy(_dlmlst,s);
}
/* Convert a string to lower case. */
stolower(s)
char *s;
{
while (*s) {
*s= tolower(*s);
++s;
}
}
/* Convert a string to upper case. */
stoupper(s)
char *s;
{
while (*s) {
*s= toupper(*s);
++s;
}
}