ek@tilt.FUN (Eleftherios Koutsofios) (04/13/86)
I saw a couple of postings this last week, about having a
terminal emulator that can speak as well as print incomming text.
I had the same idea some time ago, so I modified the terminal
program that I use, to include that.
The following is a terminal emulation program for the amiga.
Its features are:
ANSI protocol (25 lines x 80 columns)
XMODEM file transfer
graphics mode,
where you can draw something on the amiga from a host machine.
speech mode,
where you can have the amiga speak as well as print incomming
text.
Since I only got my ROM Kernel Manuals this week, I had to play
with other peoples' programs, to do what I wanted. This is the
reason why the source looks a bit strange. It consists of parts
from other programs. So, please, no comments on style :-).
The program is far from finished. There are many more options
that can be added. Maybe you can help.
This program compiles and links under the Lattice 3.02 C. If you
have any problems, send me mail.
------
Lefteris Koutsofios (princeton!tilt!ek)
------
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
# README
# makefile
# term.c
# gr.c
# speech.c
# termcap
# say.c
# This archive created: Sun Apr 13 04:22:20 1986
export PATH; PATH=/bin:$PATH
echo shar: extracting "'README'" '(7880 characters)'
if test -f 'README'
then
echo shar: will not over-write existing file "'README'"
else
cat << \SHAR_EOF > 'README'
term - a terminal emulator.
A few comments
--------------
The files term.c gr.c and speech.c contain the sources for a
terminal emulator for the amiga.
This terminal emulator has several features. This a sort
description:
1) ANSI protocol. This terminal uses the amiga's ANSI
capabilities (see Developer's manual for details). It gives you
25 lines by 80 columns. A unix termcap entry can be found in the
file termcap (in this posting). It assumes 1200 baud and it has
no problem of keeping up with this rate (it does buffered I/O, in
that it doesn't print anything, as long as the host keeps
sending).
2) XMODEM file transfer. You can send a file to a host or get one
from the host using the XMODEM protocol. It works ok, and I have
seen it recovering from line noise. I have only tried it with
text files (not with binaries).
3) Graphics. You can get a picture from your host to your amiga.
You need of course a program on the host to send the appropriate
sequences. The program understands only 3 commands: set color,
draw line, and terminate :-). There are many more that can be
added (most notably mouse commands). In fact what I use has one
more command: draw polygon (possibly filled). The reason I have
removed it is that the source I used for that belongs to
Princeton University. I guess you can add your own code (I have
left the part of the source that understands the polygon command,
so all you need to do is add your own. See function Graphics at
the end of file term.c). The reason I didn't do it yet, is
because my source does some clipping and I don't know how to do
this yet (remember I just got my manuals and they are BIG! :-)).
The program as it is assumes high resolution - interlaced mode
(640 x 400) pixels.
4) Speech. Well, the speech option is simple: it 'reads out loud'
everything between a control A and the first non-printable
character. So, to make it read a file, preceed every line by a
control A. You can switch the speech option on and off. What I
really like is to play hack with this!! It's fun! To do this
instead of the the amiga entry, use the amiga-s entry. Then you
will get to hear things like: you hit the kobolt, or you die!! It
slows down the game but its fun, and you can always turn the
speech option off. I have included a file called say.c that you
can install on your host and then use it to make your amiga talk.
How to use the program
----------------------
To create the executable do a cc term.c gr.c speech.c -o term, or
use the makefile supplied. Under Lattice 3.02 everything should
work ok, (but you will of course get the usual warnings!! :-) ).
To run the program type term (or whatever you want to call it).
The program should start by opening a window, with no borders.
The borders are there, but by printing the appropriate escapes I
get to use the whole screen for text. The prompt term: should
appear. You are in the offline mode. press the help key to get a
listing of all the commands. Type on. You are now in the online
mode. If everything is ok, you should now be able to talk to
whatever is at the other end of the serial port. To return to the
offline mode, press the function key 7 (don't ask why 7, I don't
have a logical explanation :-)). You should get an offline
message, but note that this is temporary. You can only execute
one command on the amiga, then the program will automatically
return you to the online mode. This is useful for executing
commands like sb or rb that transfer files. To stay to the
offline mode type off. To exit the program, first get to offline
mode (f7 then type off) and then type end. You should note that
you can give any command from offline. The program 'executes'
them (this of course does not work with cd). There is one bug, in
that the program may crash when you try to go to offline mode,
but this happens very very rarely.
To use the XMODEM commands, get to online mode, give the
appropriate command to your host, then press f7 and give the
corresponding command to the amiga. So, if say that you want to
send something to the host, get to online, type rb filename, then
press f7 and type sb df1:filename or whatever. The program should
then start transfering your file. At the same time it will print
a count of blocks transfered. You do need of course XMODEM
commands on your host. There are a couple of bugs. When receiving
a file, the last line contains garbage. You need to edit the file
and remove it. When sending a file, the file contains some nulls.
If your host runs unix, just enter vi and do a w!.
The graphics option works like this: to draw a picture on the
amiga, first send an escape G. This gets you in graphics mode.
Everything that comes after this must be a graphics sequence. The
implemented sequences are: T0 which exits the graphics mode, C %d
%d %d %d\n that sets the color (C pennum r g b, where pennum the
pen number, and r g b the rgb coefficients), and L %d %d %d %d
%d\n to draw a line (L x1 y1 x2 y2 pennum, where pennum the pen
number). The parser understands also the command P %d %d %d %d
%d %d %d\n that draws a polygon possibly filled (P num_of_points
pennum clip xmin ymin xmax ymax, where clip is a flag of whether
to clip or not and xmin .. are the clip boundaries). After this
command you must supply the points on the polygon, each on a
separate line (%d %d\n. I didn't include the source for this
routine, for the reasons I mentioned before.
When the escG is received the program opens a screen (640 x 400),
and starts drawing on it according to the incomming commands.
When it finishes, the menu strip that wasn't visible up to now
comes up. To return to the text window, drag this screen down or
send it back. What I chose to do is not to delete the screen when
it finishes. Instead it stays around until you try to end the
program. This way you can keep your picture for as long as you
want, and maybe print it out using a screen dump program that was
posted some time ago. If you want draw a new picture however, and
since I forgot to add a clear screen command :-), you must go to
offline mode and type gfxoff which will delete the screen. If
while in graphics mode you want to abort the drawing, press the
menu button on the mouse and then select the quit option from the
menu. The menu still works even when not visible. Then get back
to the text screen and do whatever necessary to stop the host
from sending the graphics sequences. Since the program does
handshaking you'll probably need to press control Q first, to get
your host to continue. You should make sure that the host sends
the correct sequences, although a character out of place (line
noise) will usually destroy just a small part of the picture. (My
problem is that the graphics packages I use initialize the screen
even when I give a command like: foo | amiga, where amiga is my
filter and foo is a non-existent command. In this case the
program will hung.
The sound option is easy. Just preceed everything you want 'read'
by a control A.
Acknowledgments
---------------
As I mentioned before, this program uses parts (and bugs :-))
from a few other programs. The basic program comes from the myCLI
program of Mike Schwartz. I modified that to get a 25 x 80
screen. I then added the XMODEM transfer routines that were
posted by Michael Mounier, as part of his terminal program. I
used the sparks demo by Scott Ballantyne to get an idea of how
the graphics work. Finally I used Rob Peck's program speech, to
add the speech option. Thanks for the help! (If only it hadn't
taken Commodore all these months to give me my manuals! :-( ).
SHAR_EOF
if test 7880 -ne "`wc -c < 'README'`"
then
echo shar: error transmitting "'README'" '(should have been 7880 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'makefile'" '(146 characters)'
if test -f 'makefile'
then
echo shar: will not over-write existing file "'makefile'"
else
cat << \SHAR_EOF > 'makefile'
term : term.o gr.o speech.o
cc term.o gr.o speech.o
term.o : term.c
cc -c term.c
gr.o : gr.c
cc -c gr.c
speech.o : speech.c
cc -c speech.c
SHAR_EOF
if test 146 -ne "`wc -c < 'makefile'`"
then
echo shar: error transmitting "'makefile'" '(should have been 146 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'term.c'" '(21608 characters)'
if test -f 'term.c'
then
echo shar: will not over-write existing file "'term.c'"
else
cat << \SHAR_EOF > 'term.c'
#include <stdio.h>
#include <exec/types.h>
#include <exec/exec.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <devices/serial.h>
#define MAX_CHARS 102
#define SECSIZ 0x80
#define TTIME 30
#define BufSize 0x1000
#define ERRORMAX 10
#define RETRYMAX 10
#define SOH 1
#define EOT 4
#define ACK 6
#define CTRLQ (char)17
#define CTRLS (char)19
#define NAK 21
static char bufr[BufSize];
static int fd, timeout = FALSE;
static long bytes_xferred;
static int oktosay = 1;
/*
* External functions
*/
extern unsigned char *stpblk();
extern unsigned char *AllocMem();
extern struct MsgPort *CreatePort();
extern struct FileHandle *Open();
/*
* forward references
*/
int define_function_key(), end(), help(), offline(), online(), sb(), rb(),
gfxoff(), speechon(), speechoff();
/*
* Tables
*/
struct {
unsigned char *cmdname;
int (*cmdfunc)();
} command_table[] = {
(unsigned char *)"define", &define_function_key,
(unsigned char *)"def", &define_function_key,
(unsigned char *)"end", &end,
(unsigned char *)"help", &help,
(unsigned char *)"online", &online,
(unsigned char *)"on", &online,
(unsigned char *)"offline", &offline,
(unsigned char *)"off", &offline,
(unsigned char *)"gfxoff", &gfxoff,
(unsigned char *)"sb", &sb,
(unsigned char *)"rb", &rb,
(unsigned char *)"speechon", &speechon,
(unsigned char *)"speechoff", &speechoff,
(unsigned char *)"\0", &help,
};
unsigned char *help_messages[] = {
"sb = send file using Xmodem",
"rb = receive file using Xmodem",
"def = define a function key",
"define = define a function key",
"end = exit the program",
"help = print this list",
"online = enter or re-enter terminal mode",
"offline = terminate communication",
"gfxoff = terminate graphics",
"speechon = permit speech",
"speechoff = forbid speech",
0};
unsigned char *function_key_definitions[20] = {
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0
};
/*
* Globals
*/
unsigned char work[512];
unsigned char buf[512];
unsigned char iobuf[1024];
int num_of_chars, no_io;
/*
* Terminal globals
*/
struct FileHandle *terminal_infp;
struct FileHandle *terminal_outfp;
/*
* Terminal emulator stuff
*/
struct Message *mymessage;
struct IOExtSer *ModemReadRequest;
struct IOExtSer *ModemWriteRequest;
unsigned char *WelcomeMessage = "Entering Terminal Mode\nUse ^C for command mode\n";
unsigned char *GoodbyeMessage = "Disconnected\n";
unsigned char *OfflineMessage = "--- Offline ---\n";
unsigned char *OnlineMessage = "--- Online ---\n";
unsigned char rs_in[2], rs_out[2];
int bdoneflag = 0;
int TermEcho = 0;
int modem_online = 0;
static int gfx_flag;
main(argc, argv)
int argc;
unsigned char *argv[];
{
gfx_flag = 0;
num_of_chars = 0;
no_io = 0;
sprintf(work, "Raw:0/0/640/200/Terminal");
terminal_infp = Open(work, MODE_NEWFILE);
if (terminal_infp == 0) {
printf("Can't open window\n");
exit(1);
}
terminal_outfp = terminal_infp;
sprintf(work, "\033[0x\033[0y\033[25t\033[80u\014");
WriteWork();
while (1) {
Write(terminal_outfp, "\033[7mterm:\033[m ", 13);
getcommand(buf);
CommandInterpreter(buf);
}
}
WriteWork() {
Write(terminal_outfp, work, strlen(work));
}
CommandInterpreter(command)
unsigned char *command;
{
int i;
command = stpblk(command);
/*
* Scan through the command table for the string and invoke the function
* to do the actual work of the command. Each of these commands is
* defined below, and the functions each take a pointer to the
* string containing the arguments passed the command line.
*/
for (i=0; command_table[i].cmdname[0] != '\0'; i++)
if (strncmp(command, command_table[i].cmdname,
strlen(command_table[i].cmdname)) == 0) {
(*command_table[i].cmdfunc)
(stpblk(&command[strlen(command_table[i].cmdname)]));
goto FinishedCommand;
}
/*
* Not found, so look for it on the disk.
*/
executive(stpblk(&command[0]));
FinishedCommand:
}
executive(s)
unsigned char *s;
{
if (!Execute(s, 0, terminal_outfp))
printf("%d\n", IoErr());
}
define_function_key(s)
unsigned char *s;
{
int i;
if (s[0] == '\0')
for (i=0; i<20; i++) {
if (function_key_definitions[i]) {
sprintf(work, "F%-2d = %s\n", i+1, function_key_definitions[i]);
WriteWork();
}
}
else if (s[0] == 'f' || s[0] == 'F') {
s++;
i = atoi(s);
if (i < 1 || i > 20) {
sprintf(work, "%c[36mInvalid function key%c[0m\n", 0x1b, 0x1b);
WriteWork();
} else {
i--;
if (function_key_definitions[i])
FreeMem(function_key_definitions[i], strlen(function_key_definitions[i])+1);
while (isdigit(*s))
s++;
s = stpblk(s);
if (*s != '\0') {
function_key_definitions[i] = AllocMem(strlen(s)+1, MEMF_PUBLIC|MEMF_CLEAR);
if (function_key_definitions[i] == 0) {
sprintf(work, "%c[36mDefine Error: not enough memory%c[0m\n",
0x1b, 0x1b);
WriteWork();
} else
strcpy(function_key_definitions[i], s);
}
}
} else {
sprintf(work,
"%c[36mDefine Error: invalid function key specified%c[0m\n",
0x1b, 0x1b);
WriteWork();
}
}
end(s)
unsigned char *s;
{
if (modem_online) {
sprintf(work, "%c[36mTerminal Mode Error: Modem still online%c[0m\n",
0x1b, 0x1b);
WriteWork();
} else {
if (gfx_flag == 1)
terminate();
Close(terminal_outfp);
exit(0);
}
}
help(s)
unsigned char *s;
{
int i;
sprintf(work,"%c[7m MyCli Help %c[0m\n", 0x1b, 0x1b);
WriteWork();
for (i=0; help_messages[i]; i++) {
sprintf(work, "%s\n", help_messages[i]);
WriteWork();
}
sprintf(work, "%c[7m End of Help %c[0m\n", 0x1b, 0x1b);
WriteWork();
}
gfxoff()
{
if (gfx_flag == 1)
terminate();
gfx_flag = 0;
}
speechon()
{
oktosay = 1;
}
speechoff()
{
oktosay = 0;
}
offline(s)
unsigned char *s;
{
modem_online = 0;
say_string((char*)0, 1);
}
online(s)
unsigned char *s;
{
modem_online = !0; /* signal that modem is live !!! */
if (initialize()) { /* set baud rate, etc. */
Write(terminal_outfp, WelcomeMessage, strlen(WelcomeMessage));
while (modem_online) {
bdoneflag = 0; /* terminal mode on flag */
Write(terminal_outfp, OnlineMessage, strlen(OnlineMessage));
while (!bdoneflag) {
check_keyboard();
check_modem();
if (bdoneflag || num_of_chars > MAX_CHARS || no_io > 0) {
if (num_of_chars > 0) {
Write(terminal_outfp, iobuf, num_of_chars);
num_of_chars = 0;
}
}
}
Write(terminal_outfp, OfflineMessage, strlen(OfflineMessage));
Write(terminal_outfp, "\033[7mterm:\033[m ", 13);
getcommand(buf);
CommandInterpreter(buf);
}
cleanup();
}
modem_online = 0;
}
getcommand(s)
unsigned char *s;
{
unsigned char c;
unsigned col;
col = 0;
while (1) {
Read(terminal_infp, &c, 1);
switch(c) {
case 8:
if (col) {
c = 8;
Write(terminal_outfp, &c, 1);
c = ' ';
Write(terminal_outfp, &c, 1);
c = 8;
Write(terminal_outfp, &c, 1);
col--;
}
continue;
case 10:
case 13:
sprintf(work, "\n");
WriteWork();
s[col++] = '\0';
break;
case 0x1b:
case 24:
while (col) {
c = 8;
Write(terminal_outfp, &c, 1);
c = ' ';
Write(terminal_outfp, &c, 1);
c = 8;
Write(terminal_outfp, &c, 1);
col--;
}
continue;
case 0x9b:
if (process_event(&s[col])) {
strcat(s, "\n");
Write(terminal_outfp, &s[col], strlen(&s[col]));
break;
}
continue;
default:
s[col++] = c;
Write(terminal_outfp, &c, 1);
continue;
}
break;
}
}
/*
* this function converts an incoming ANSI escape sequence
* and processes it. A buffer is passed where any function
* key expansion is to take place. If the buffer is modified
* for any reason, this function returns true.
*/
process_event(cmd_line)
unsigned char *cmd_line;
{
int i;
unsigned char c;
char event_buffer[32];
i = 0;
while (1) {
Read(terminal_infp, &c, 1);
event_buffer[i] = c;
if (c == '~' || c == '|' || c == 'A' || c == 'B' || c == 'C' || c == 'D')
break;
i++;
}
event_buffer[i+1] = '\0';
if (event_buffer[i] == '~') {
if (event_buffer[0] == '?') {
strcpy(cmd_line, "help");
return !0;
} else if (isdigit(event_buffer[0])) {
if (function_key(atoi(event_buffer), cmd_line))
return !0;
else if (atoi(event_buffer) == 6)
bdoneflag = !0;
}
} else if (i == 0 && (event_buffer[0] >= 'A' && event_buffer[0] <= 'D')) {
cmd_line[0] = '\033';
cmd_line[1] = event_buffer[0];
cmd_line[2] = '\000';
return !0;
}
return 0;
}
/*
* if a definition for the function key fkey exists (0-19), then
* the translation for the function key is copied to the string
* s, and this function returns !0. Otherwise, now translation
* exists, and this function returns 0.
*/
function_key(fkey, s)
int fkey;
unsigned char *s;
{
int i;
if (function_key_definitions[fkey] != 0) {
for (i=0; function_key_definitions[fkey][i] != '\0'; i++)
s[i] = function_key_definitions[fkey][i];
s[i] = '\0';
return !0;
}
return 0;
}
initialize() {
ModemReadRequest = (struct IOExtSer *)AllocMem(sizeof(*ModemReadRequest),
MEMF_PUBLIC | MEMF_CLEAR);
ModemReadRequest->io_SerFlags = SERF_SHARED | SERF_XDISABLED;
ModemReadRequest->IOSer.io_Message.mn_ReplyPort =
CreatePort("Read_RS",0);
if (OpenDevice(SERIALNAME, NULL, ModemReadRequest, NULL)) {
sprintf(work, "%c[36mCan't open serial read device%c[0m\n",
0x1b, 0x1b);
WriteWork();
DeletePort(ModemReadRequest->IOSer.io_Message.mn_ReplyPort);
FreeMem(ModemReadRequest, sizeof(*ModemReadRequest));
return 0;
}
ModemReadRequest->IOSer.io_Command = CMD_READ;
ModemReadRequest->IOSer.io_Length = 1;
ModemReadRequest->IOSer.io_Data = (APTR) &rs_in[0];
ModemWriteRequest = (struct IOExtSer *)AllocMem(sizeof(*ModemWriteRequest),
MEMF_PUBLIC | MEMF_CLEAR);
ModemWriteRequest->io_SerFlags = SERF_SHARED | SERF_XDISABLED;
ModemWriteRequest->IOSer.io_Message.mn_ReplyPort =
CreatePort("Write_RS",0);
if (OpenDevice(SERIALNAME, NULL, ModemWriteRequest, NULL)) {
sprintf(work, "%c[36mCan't open serial write device%c[0m\n",
0x1b, 0x1b);
WriteWork();
DeletePort(ModemReadRequest->IOSer.io_Message.mn_ReplyPort);
FreeMem(ModemReadRequest, sizeof(*ModemReadRequest));
DeletePort(ModemWriteRequest->IOSer.io_Message.mn_ReplyPort);
FreeMem(ModemWriteRequest, sizeof(*ModemWriteRequest));
return 0;
}
ModemWriteRequest->IOSer.io_Command = CMD_WRITE;
ModemWriteRequest->IOSer.io_Length = 1;
ModemWriteRequest->IOSer.io_Data = (APTR) &rs_out[0];
ModemReadRequest->io_SerFlags = SERF_SHARED | SERF_XDISABLED;
ModemReadRequest->io_Baud = 1200;
ModemReadRequest->io_ReadLen = 8;
ModemReadRequest->io_WriteLen = 8;
ModemReadRequest->io_CtlChar = 1L;
ModemReadRequest->IOSer.io_Command = SDCMD_SETPARAMS;
DoIO(ModemReadRequest);
ModemReadRequest->IOSer.io_Command = CMD_READ;
BeginIO(ModemReadRequest);
return !0;
}
cleanup() {
CloseDevice(ModemReadRequest);
DeletePort(ModemReadRequest->IOSer.io_Message.mn_ReplyPort);
FreeMem(ModemReadRequest, sizeof(*ModemReadRequest));
CloseDevice(ModemWriteRequest);
DeletePort(ModemWriteRequest->IOSer.io_Message.mn_ReplyPort);
FreeMem(ModemWriteRequest, sizeof(*ModemWriteRequest));
Write(terminal_outfp, GoodbyeMessage, strlen(GoodbyeMessage));
}
check_keyboard()
{
unsigned char *pc;
if (WaitForChar(terminal_infp, 1)) {
Read(terminal_infp, &rs_out[0], 1);
switch ((unsigned char)rs_out[0]) {
case 0x9b: /* ANSI keyboard stuff */
if (process_event(&buf[0])) { /* send the translation */
pc = &buf[0];
while (*pc != '\0') {
rs_out[0] = *pc++;
if (TermEcho)
Write(terminal_outfp, &rs_out[0], 1);
DoIO(ModemWriteRequest);
check_modem();
}
}
break;
case 0x05: /* toggle keystroke echo */
TermEcho = !TermEcho;
sprintf(work, "%c[36mEcho %s%c[0m\n", 0x1b, TermEcho?"ON":"OFF",
0x1b);
WriteWork();
break;
default:
if (TermEcho)
Write(terminal_outfp, &rs_out[0], 1);
DoIO(ModemWriteRequest);
}
}
}
/*
* Check to see if the Read Request IO has completed from the modem.
*/
check_modem()
{
static int sayflag = 0;
static char saystring[133];
static int sayind = 0;
static int escape_sequence = 0;
if (CheckIO(ModemReadRequest)) {
WaitIO(ModemReadRequest);
rs_in[0] &= 0x7f;
if (rs_in[0] == '\001' && oktosay == 1) {
sayflag = 1;
BeginIO(ModemReadRequest);
return;
}
if (oktosay == 1 && sayflag) {
if (rs_in[0] >= ' ' && rs_in[0] < (char)127) {
saystring[sayind++] = rs_in[0];
} else {
Write(terminal_outfp, iobuf, num_of_chars);
rs_out[0] = CTRLS;
DoIO(ModemWriteRequest);
num_of_chars = 0;
saystring[sayind++] = (char)0;
say_string(saystring,0);
sayind = 0;
sayflag = 0;
rs_out[0] = CTRLQ;
DoIO(ModemWriteRequest);
}
}
if (rs_in[0] == '\033') {
escape_sequence = 1;
} else if (escape_sequence == 1) {
if (rs_in[0] == 'G') {
Graphics();
} else {
iobuf[num_of_chars++] = '\033';
iobuf[num_of_chars++] = rs_in[0];
no_io = 0;
}
escape_sequence = 0;
} else {
iobuf[num_of_chars++] = rs_in[0];
no_io = 0;
}
BeginIO(ModemReadRequest);
} else {
no_io++;
}
}
sendchar(ch)
int ch;
{
rs_out[0] = ch;
DoIO(ModemWriteRequest);
}
readchar()
{
unsigned char c;
int rd,ch;
rd = FALSE;
while (rd == FALSE) {
if(CheckIO(ModemReadRequest)) {
WaitIO(ModemReadRequest);
ch=rs_in[0];
rd = TRUE;
BeginIO(ModemReadRequest);
}
}
if (rd == FALSE) {
timeout = TRUE;
emits("\nTimeout Waiting For Character\n");
}
c = ch;
return(c);
}
rb(file)
char *file;
{
int firstchar, sectnum, sectcurr, sectcomp, errors, errorflag;
unsigned int checksum, j, bufptr,i;
char numb[10];
bytes_xferred = 0L;
i = 10;
if ((fd = creat(file, 0)) < 0) {
emits("Cannot Open File\n");
return FALSE;
} else
emits("Receiving File\n");
timeout=FALSE;
sectnum = errors = bufptr = 0;
sendchar(NAK);
firstchar = 0;
while (firstchar != EOT && errors != ERRORMAX) {
errorflag = FALSE;
do {
firstchar = readchar();
if (timeout == TRUE)
return FALSE;
}
while (firstchar != SOH && firstchar != EOT);
if (firstchar == SOH) {
emits("Getting Block ");
stci_d(numb,sectnum,i);
emits(numb);
emits("...");
sectcurr = readchar();
if (timeout == TRUE)
return FALSE;
sectcomp = readchar();
if (timeout == TRUE)
return FALSE;
if ((sectcurr + sectcomp) == 255) {
if (sectcurr == (sectnum + 1 & 0xff)) {
checksum = 0;
for (j = bufptr; j < (bufptr + SECSIZ); j++) {
bufr[j] = readchar();
if (timeout == TRUE)
return FALSE;
checksum = (checksum + bufr[j]) & 0xff;
}
if (checksum == readchar()) {
errors = 0;
sectnum++;
bufptr += SECSIZ;
bytes_xferred += SECSIZ;
emits("verified\n");
if (bufptr == BufSize) {
bufptr = 0;
if (write(fd, bufr, BufSize) == EOF) {
emits("\nError Writing File\n");
return FALSE;
};
};
sendchar(ACK);
} else {
errorflag = TRUE;
if (timeout == TRUE)
return FALSE;
}
} else {
if (sectcurr == (sectnum & 0xff)) {
emits("\nReceived Duplicate Sector\n");
sendchar(ACK);
} else
errorflag = TRUE;
}
} else
errorflag = TRUE;
}
if (errorflag == TRUE) {
errors++;
emits("\nError\n");
sendchar(NAK);
}
};
if ((firstchar == EOT) && (errors < ERRORMAX)) {
sendchar(ACK);
write(fd, bufr, bufptr);
write(fd, "\n", 1);
close(fd);
return TRUE;
}
return FALSE;
}
sb(file)
char *file;
{
int sectnum, bytes_to_send, size, attempts, c, i;
unsigned checksum, j, bufptr;
char numb[10];
timeout=FALSE;
bytes_xferred = 0;
i = 10;
if ((fd = open(file, 1)) < 0) {
emits("Cannot Open Send File\n");
return FALSE;
} else
emits("Sending File\n");
attempts = 0;
sectnum = 1;
j=1;
while (((c = readchar()) != NAK) && (j++ < ERRORMAX));
if (j >= (ERRORMAX)) {
emits("\nReceiver not sending NAKs\n");
return FALSE;
};
while ((bytes_to_send = read(fd, bufr, BufSize)) && attempts != RETRYMAX)
{
if (bytes_to_send == EOF) {
emits("\nError Reading File\n");
return FALSE;
};
bufptr = 0;
while (bytes_to_send > 0 && attempts != RETRYMAX) {
attempts = 0;
do {
sendchar(SOH);
sendchar(sectnum);
sendchar(~sectnum);
checksum = 0;
size = SECSIZ <= bytes_to_send ? SECSIZ : bytes_to_send;
bytes_to_send -= size;
for (j = bufptr; j < (bufptr + SECSIZ); j++)
if (j < (bufptr + size)) {
sendchar(bufr[j]);
checksum += bufr[j];
} else {
sendchar(0);
}
sendchar(checksum & 0xff);
attempts++;
c = readchar();
if (timeout == TRUE)
return FALSE;
} while ((c != ACK) && (attempts != RETRYMAX));
bufptr += size;
bytes_xferred += size;
emits("Block ");
stci_d(numb,sectnum,i);
emits(numb);
emits(" sent\n");
sectnum++;
}
}
close(fd);
if (attempts == RETRYMAX) {
emits("\nNo Acknowledgment Of Sector, Aborting\n");
return FALSE;
} else {
attempts = 0;
do {
sendchar(EOT);
attempts++;
} while ((readchar() != ACK) && (attempts != RETRYMAX) && (timeout == FALSE));
if (attempts == RETRYMAX)
emits("\nNo Acknowledgment Of End Of File\n");
};
return TRUE;
}
emits(embuf)
char *embuf;
{
Write(terminal_outfp, embuf, strlen(embuf));
}
Graphics()
{
char buf[82], *gr_buf;
int gr_len, r, g, b, color, x1, y1, x2, y2;
int polx[256], poly[256], n, clip, xmin, ymin, xmax, ymax;
int i;
if (gfx_flag == 0) {
gfx_flag = 1;
initialise();
} else
get_screen();
rs_out[0] = CTRLS;
DoIO(ModemWriteRequest);
BeginIO(ModemReadRequest);
for(;;) {
gr_len = 0;
buf[0] = (char)0;
gr_buf = &(buf[1]);
while(gr_buf[gr_len-1] != '\015') {
if (CheckIO(ModemReadRequest)) {
WaitIO(ModemReadRequest);
rs_in[0] &= 0x7f;
if (rs_in[0] != '\012') {
gr_buf[gr_len++] = rs_in[0];
}
BeginIO(ModemReadRequest);
} else {
rs_out[0] = CTRLQ;
DoIO(ModemWriteRequest);
}
}
rs_out[0] = CTRLS;
DoIO(ModemWriteRequest);
gr_buf[gr_len-1] = (char)0;
switch (gr_buf[0]) {
case 'T':
/* terminate(); */
put_screen();
rs_out[0] = CTRLQ;
DoIO(ModemWriteRequest);
return;
case 'C':
sscanf(&(gr_buf[1]), "%d%d%d%d", &color, &r, &g, &b);
define_color(color, r, g, b);
if (check_user_action() == -1) {
put_screen();
return;
}
break;
case 'L':
sscanf(&(gr_buf[1]), "%d%d%d%d%d", &x1, &y1, &x2, &y2, &color);
draw(x1, y1, x2, y2, color);
if (check_user_action() == -1) {
put_screen();
return;
}
break;
case 'P':
sscanf(&(gr_buf[1]), "%d%d%d%d%d%d%d", &n, &color, &clip,
&xmin, &ymin, &xmax, &ymax);
for (i=0; i<n; i++) {
gr_len = 0;
buf[0] = (char)0;
gr_buf = &(buf[1]);
while(gr_buf[gr_len-1] != '\015') {
if (CheckIO(ModemReadRequest)) {
WaitIO(ModemReadRequest);
rs_in[0] &= 0x7f;
if (rs_in[0] != '\012') {
gr_buf[gr_len++] = rs_in[0];
}
BeginIO(ModemReadRequest);
} else {
rs_out[0] = CTRLQ;
DoIO(ModemWriteRequest);
}
}
gr_buf[gr_len-1] = (char)0;
sscanf(gr_buf,"%d%d", &(polx[i]), &(poly[i]));
}
rs_out[0] = CTRLS;
DoIO(ModemWriteRequest);
/* poly_draw(polx, poly, n, color, clip, xmin, ymin, xmax, ymax); */
if (check_user_action() == -1) {
put_screen();
return;
}
break;
}
}
}
SHAR_EOF
if test 21608 -ne "`wc -c < 'term.c'`"
then
echo shar: error transmitting "'term.c'" '(should have been 21608 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'gr.c'" '(5005 characters)'
if test -f 'gr.c'
then
echo shar: will not over-write existing file "'gr.c'"
else
cat << \SHAR_EOF > 'gr.c'
#include <exec/types.h>
#include <exec/exec.h>
#include <exec/execbase.h>
#include <hardware/blit.h>
#include <graphics/copper.h>
#include <graphics/regions.h>
#include <graphics/rastport.h>
#include <graphics/gfxbase.h>
#include <graphics/gfxmacros.h>
#include <graphics/gels.h>
#include <graphics/display.h>
#include <intuition/intuition.h>
struct IntuitionBase *IntuitionBase = NULL;
struct GfxBase *GfxBase = NULL;
#define MAXX 640
struct NewScreen MyScreen =
{ 0,0,MAXX,400,4,0,1,HIRES | INTERLACE, CUSTOMSCREEN, NULL, "Graphics", 0,0,};
struct NewWindow DrawWindow = {
0,0,MAXX,400,
0,1,
MENUPICK,
BORDERLESS | BACKDROP | ACTIVATE,
NULL,
NULL,
NULL,
NULL,
NULL,
0,0,0,0,
CUSTOMSCREEN,
};
struct Screen *Screen = NULL;
struct Window *Backdrop = NULL;
struct RastPort *DrawRP;
struct ViewPort *DrawVP;
struct IntuiMessage *message;
struct MenuItem OnlyMenuItems[3];
struct IntuiText OnlyMenuText[3];
struct Menu OnlyMenu[1];
#define MAXLINES 125
#define ERASE 0
initialise()
{
if (!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0)))
exit(1);
if(!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0))) {
cleanitup();
exit(2);
}
if(!(Screen = (struct Screen *)OpenScreen(&MyScreen))) {
cleanitup();
exit(3);
}
DrawWindow.Screen = Screen;
if(!(Backdrop = (struct Window *)OpenWindow(&DrawWindow))) {
cleanitup();
exit(4);
}
DrawRP = Backdrop->RPort; /* Draw into backdrop window */
DrawVP = &Screen->ViewPort; /* Set colors in Screens VP */
initmenuitems();
initmenu();
SetMenuStrip(Backdrop, &OnlyMenu[0]);
ShowTitle(Screen,FALSE);
define_color( 0, 0, 0, 0);
define_color( 1, 15, 15, 15);
define_color( 2, 15, 0, 0);
define_color( 3, 7, 0, 0);
define_color( 4, 0, 15, 0);
define_color( 5, 0, 7, 0);
define_color( 6, 0, 0, 15);
define_color( 7, 0, 0, 7);
define_color( 8, 15, 15, 0);
define_color( 9, 7, 7, 0);
define_color(10, 15, 0, 15);
define_color(11, 7, 0, 7);
define_color(12, 0, 15, 15);
define_color(13, 0, 7, 7);
define_color(14, 7, 7, 7);
define_color(15, 3, 3, 3);
}
terminate()
{
ShowTitle(Screen,TRUE);
/* while(check_user_action() != -1); */
cleanitup();
}
cleanitup() /* release allocated resources */
{
if (Backdrop)
CloseWindow(Backdrop);
if (Screen)
CloseScreen(Screen);
if (GfxBase)
CloseLibrary(GfxBase);
if (IntuitionBase)
CloseLibrary(IntuitionBase);
}
draw(x1, y1, x2, y2, color)
int x1, x2;
int y1, y2;
BYTE color;
{
SetAPen(DrawRP, color);
SetDrMd(DrawRP, JAM1);
Move(DrawRP, x1, y1);
Draw(DrawRP, x2, y2);
}
define_color(color, r, g, b)
int color, r, g, b;
{
SetRGB4(DrawVP, color, r, g, b);
}
initmenuitems()
{
short n;
for(n = 0; n < 3; n++) { /* One struct for each item */
OnlyMenuItems[n].NextItem = &OnlyMenuItems[n + 1]; /* next item */
OnlyMenuItems[n].LeftEdge = 0;
OnlyMenuItems[n].TopEdge = 10 * n;
OnlyMenuItems[n].Width = 112;
OnlyMenuItems[n].Height = 10;
OnlyMenuItems[n].Flags = ITEMTEXT | ITEMENABLED | HIGHCOMP;
OnlyMenuItems[n].MutualExclude = 0;
OnlyMenuItems[n].ItemFill = (APTR)&OnlyMenuText[n];
OnlyMenuItems[n].SelectFill = NULL;
OnlyMenuItems[n].Command = 0;
OnlyMenuItems[n].SubItem = NULL;
OnlyMenuItems[n].NextSelect = 0;
OnlyMenuText[n].FrontPen = 0;
OnlyMenuText[n].BackPen = 1;
OnlyMenuText[n].DrawMode = JAM2;
OnlyMenuText[n].LeftEdge = 0;
OnlyMenuText[n].TopEdge = 1;
OnlyMenuText[n].ITextFont = NULL;
OnlyMenuText[n].NextText = NULL;
}
OnlyMenuItems[2].NextItem = NULL; /* Last item */
OnlyMenuText[0].IText = (UBYTE *)"Hide Title Bar";
OnlyMenuText[1].IText = (UBYTE *)"Show Title Bar";
OnlyMenuText[2].IText = (UBYTE *)"QUIT!";
}
initmenu()
{
OnlyMenu[0].NextMenu = NULL; /* No more menus */
OnlyMenu[0].LeftEdge = 0;
OnlyMenu[0].TopEdge = 0;
OnlyMenu[0].Width = 85;
OnlyMenu[0].Height = 10;
OnlyMenu[0].Flags = MENUENABLED; /* All items selectable */
OnlyMenu[0].MenuName = "Actions";
OnlyMenu[0].FirstItem = &OnlyMenuItems[0]; /* Pointer to first item */
}
check_user_action()
{
ULONG class;
USHORT code, ItemNum;
int action;
action = 0;
while(message = (struct IntuiMessage *)GetMsg(Backdrop->UserPort)) {
class = message->Class;
code = message->Code;
ReplyMsg(message);
if (class == MENUPICK && code != MENUNULL) {
ItemNum = ITEMNUM( code );
switch (ItemNum) {
case 0:
ShowTitle(Screen, FALSE);
break;
case 1:
ShowTitle(Screen, TRUE);
break;
case 2:
/* ClearMenuStrip(Backdrop); */
action = -1;
return(action);
}
}
}
return (action);
}
put_screen()
{
/* ScreenToBack(Screen); */
ShowTitle(Screen,TRUE);
}
get_screen()
{
ScreenToFront(Screen);
ShowTitle(Screen,TRUE);
}
SHAR_EOF
if test 5005 -ne "`wc -c < 'gr.c'`"
then
echo shar: error transmitting "'gr.c'" '(should have been 5005 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'speech.c'" '(8123 characters)'
if test -f 'speech.c'
then
echo shar: will not over-write existing file "'speech.c'"
else
cat << \SHAR_EOF > 'speech.c'
/* Here is a sample speech demo program that compiles on
* Amiga (Lattice) C. It can be thought of as a stripped
* down version of the speechtoy (lucas). I haven't
* provided the graphics for the drawing of the mouth,
* but the access to the mouth variables is shown here.
*
* It is the sample program from the rev 1.1 ROM KERNEL
* manual, now at the printers.
*
* Rob Peck.
*
* This code may be freely utilized to create programs for the Amiga.
*/
#include "exec/types.h"
#include "exec/exec.h"
#include "exec/nodes.h"
#include "exec/lists.h"
#include "exec/memory.h"
#include "exec/interrupts.h"
#include "exec/ports.h"
#include "exec/libraries.h"
#include "exec/io.h"
#include "exec/tasks.h"
#include "exec/execbase.h"
#include "devices/narrator.h"
#include "libraries/translator.h"
struct MsgPort *readport=0;
struct MsgPort *writeport=0;
extern struct MsgPort *CreatePort();
extern struct IORequest *CreateExtIO();
struct narrator_rb *writeNarrator=0;
struct mouth_rb *readNarrator=0;
struct Library *TranslatorBase=0;
UBYTE outputstring[500]; /* place to put the translation */
SHORT rtnCode; /* return code from function */
SHORT readError;
SHORT writeError;
SHORT error;
BYTE audChanMasks[4] = { 3,5,10,12 }; /* which channels to use */
#define CANT_OPEN_TRANSLATOR -100
#define CANT_OPEN_NARRATOR -200
#define CREATE_PORT_PROBLEMS -300
#define CREATE_IO_PROBLEMS -400
#define CANT_PERFORM_WRITE -500
#define REVISION 1
extern struct Library *OpenLibrary();
say_string(Txt,done)
UBYTE *Txt;
int done;
{
static FirstTime = 1;
if (FirstTime) {
FirstTime = 0;
TranslatorBase = OpenLibrary("translator.library",REVISION);
if(TranslatorBase == NULL) exit (CANT_OPEN_TRANSLATOR);
rtnCode = Translate(Txt,strlen(Txt)+1,outputstring,500);
error = rtnCode + 100;
if(rtnCode != 0) goto cleanup0;
writeport = CreatePort(0,0);
if(writeport == NULL) { error=CREATE_PORT_PROBLEMS; goto cleanup1; }
readport = CreatePort(0,0);
if(readport == NULL) { error=CREATE_PORT_PROBLEMS; goto cleanup2; }
writeNarrator = (struct narrator_rb *)CreateExtIO(writeport,
sizeof(struct narrator_rb));
if(writeNarrator == NULL) { error=CREATE_IO_PROBLEMS; goto cleanup3; }
readNarrator = (struct mouth_rb *)CreateExtIO(readport,
sizeof(struct mouth_rb));
if(readNarrator == NULL) { error=CREATE_IO_PROBLEMS; goto cleanup4; }
/* SET UP THE PARAMETERS FOR THE WRITE-MESSAGE TO THE NARRATOR DEVICE */
/* show where to find the channel masks */
writeNarrator->ch_masks = (audChanMasks);
/* and tell it how many of them there are */
writeNarrator->nm_masks = sizeof(audChanMasks);
/* tell it where to find the string to speak */
writeNarrator->message.io_Data = (APTR)outputstring;
/* tell it how many characters the translate function returned */
writeNarrator->message.io_Length = strlen(outputstring);
/* if nonzero, asks that mouths be calculated during speech */
writeNarrator->mouths = 1;
/* tell it this is a write-command */
writeNarrator->message.io_Command = CMD_WRITE;
/* select rate of 165 words/min. */
writeNarrator->rate = (UWORD)165;
/* Open the device */
error = OpenDevice("narrator.device", 0, writeNarrator, 0);
if(error != 0) goto cleanup4;
/* SET UP THE PARAMETERS FOR THE READ-MESSAGE TO THE NARRATOR DEVICE */
/* tell narrator for whose speech a mouth is to be generated */
readNarrator->voice.message.io_Device =
writeNarrator->message.io_Device;
readNarrator->voice.message.io_Unit =
writeNarrator->message.io_Unit;
readNarrator->width = 0;
readNarrator->height = 0; /* initial mouth parameters */
readNarrator->voice.message.io_Command = CMD_READ;
/* initial error value */
readNarrator->voice.message.io_Error = 0;
/* Send an asynchronous write request to the device */
writeError = SendIO(writeNarrator);
if(writeError != NULL) { error=CANT_PERFORM_WRITE; goto cleanup5; }
/* return immediately, run tasks concurrently */
/* keep sending reads until it comes back saying "no write in progress" */
while((readError = readNarrator->voice.message.io_Error) !=
ND_NoWrite)
{
DoIO(readNarrator);
/* put task to sleep waiting for a different
* mouth shape or return of the message block
* with the error field showing no write in
* process
*/
}
Delay(30);
return;
}
if ( !done ) {
rtnCode = Translate(Txt,strlen(Txt)+1,outputstring,500);
/* writeNarrator->sex = FEMALE;
writeNarrator->pitch = MAXPITCH; /* raise pitch from default value */
writeNarrator->message.io_Data = (APTR)outputstring;
writeNarrator->message.io_Length = strlen(outputstring);
DoIO(writeNarrator);
Delay(30);
return;
}
cleanup5:
if(writeNarrator != 0)
CloseDevice(writeNarrator);
/* terminate access to the device */
/* now return system memory to the memory allocator */
cleanup4:
if(readNarrator != 0)
DeleteExtIO(readNarrator,sizeof(struct mouth_rb));
cleanup3:
if(writeNarrator != 0)
DeleteExtIO(writeNarrator,sizeof(struct narrator_rb));
cleanup2:
if(readport != 0)
DeletePort(readport);
cleanup1:
if(writeport != 0)
DeletePort(writeport);
cleanup0:
if(TranslatorBase != 0)
CloseLibrary(TranslatorBase);
/* terminate access to the library */
if(error != 0) exit(error);
} /* end of test */
/***********************************************************************
*
* Exec Support Function -- Extended IO Request
*
***********************************************************************/
extern APTR AllocMem();
/****** exec_support/CreateExtIO **************************************
*
* NAME
* CreateExtIO() -- create an Extended IO request
*
* SYNOPSIS
* ioReq = CreateExtIO(ioReplyPort,size);
*
* FUNCTION
* Allocates memory for and initializes a new IO request block
* of a user-specified number of bytes.
*
* INPUTS
* ioReplyPort - a pointer to an already initialized
* message port to be used for this IO request's reply port.
*
* RESULT
* Returns a pointer to the new block. Pointer is of the type
* struct IORequest.
*
* 0 indicates inability to allocate enough memory for the request block
* or not enough signals available.
*
* EXAMPLE
* struct IORequest *myBlock;
* if( (myBlock = CreateExtIO(myPort,sizeof(struct IOExtTD)) == NULL)
* exit(NO_MEM_OR_SIGNALS);
*
* example used to allocate space for IOExtTD (trackdisk driver
* IO Request block for extended IO operations).
*
* SEE ALSO
* DeleteExtIO
*
***********************************************************************/
struct IORequest *CreateExtIO(ioReplyPort,size)
struct MsgPort *ioReplyPort;
LONG size;
{
struct IORequest *ioReq;
if (ioReplyPort == 0)
return ((struct IORequest *) 0);
ioReq = (struct IORequest *)AllocMem (size, MEMF_CLEAR | MEMF_PUBLIC);
if (ioReq == 0)
return ((struct IORequest *) 0);
ioReq -> io_Message.mn_Node.ln_Type = NT_MESSAGE;
ioReq -> io_Message.mn_Node.ln_Pri = 0;
ioReq -> io_Message.mn_ReplyPort = ioReplyPort;
ioReq -> io_Message.mn_Length = (size - sizeof(struct Message));
/* new (rap) */
return (ioReq);
}
/****** exec_support/DeleteExtIO **************************************
*
* NAME
* DeleteExtIO() - return memory allocated for extended IO request
*
* SYNOPSIS
* DeleteExtIO(ioReq,size);
*
* FUNCTION
* See summary line at NAME. Also frees the signal bit which
* had been allocated by the call to CreateExtIO.
*
* INPUTS
* A pointer to the IORequest block whose resources are to be freed.
*
* RESULT
* Frees the memory. Returns (no error conditions shown)
*
* EXAMPLE
* struct IORequest *myBlock;
* DeleteExtIO(myBlock,(sizeof(struct IOExtTD)));
*
* example shows that CreateExtIO had been used to create a trackdisk
* (extended) IO Request block.
*
* SEE ALSO
* CreateExtIO
*
**************************************************************************/
DeleteExtIO(ioExt,size)
struct IORequest *ioExt;
LONG size;
{
ioExt -> io_Message.mn_Node.ln_Type = 0xff;
ioExt -> io_Device = (struct Device *) -1;
ioExt -> io_Unit = (struct Unit *) -1;
FreeMem (ioExt, size);
}
SHAR_EOF
if test 8123 -ne "`wc -c < 'speech.c'`"
then
echo shar: error transmitting "'speech.c'" '(should have been 8123 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'termcap'" '(532 characters)'
if test -f 'termcap'
then
echo shar: will not over-write existing file "'termcap'"
else
cat << \SHAR_EOF > 'termcap'
#normal amiga entry
am|amiga:\
:al=\E[L:bs:cd=\E[J:ce=\E[K:cl=^L:cm=\E[%i%d;%dH:co#80:cr=^M:\
:dc=\E[P:do=\E[B:kd=\EB:kl=\ED:kr=\EC:ku=\EA:li#25:nd=\E[C:\
:sf=\E[S:sr=\E[T:up=\E[A:bw:nl=\E[B:am:so=\E[7m:se=\E[m:bl=^G:\
:dl=\E[M:us=\E[4m:ue=\E[0m:ic=\E[@:
#hack amiga entry
sm|amiga-s:\
:al=\E[L:bs:cd=\E[J:ce=\E[K:cl=^L^A:cm=\E[%i%d;%dH:co#80:cr=^M:\
:dc=\E[P:do=\E[B:kd=\EB:kl=\ED:kr=\EC:ku=\EA:li#25:nd=\E[C:\
:sf=\E[S:sr=\E[T:up=\E[A:bw:nl=\E[B:am:so=\E[7m:se=\E[m:bl=^G:\
dl=\E[M:us=\E[4m:ue=\E[0m:ic=\E[@:ho=\E[H^A:
SHAR_EOF
if test 532 -ne "`wc -c < 'termcap'`"
then
echo shar: error transmitting "'termcap'" '(should have been 532 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'say.c'" '(527 characters)'
if test -f 'say.c'
then
echo shar: will not over-write existing file "'say.c'"
else
cat << \SHAR_EOF > 'say.c'
# include <stdio.h>
main(argc,argv)
int argc;
char *argv[];
{
char x[133];
int i;
FILE *in;
if (argc == 1) {
while (gets(x) != NULL) {
printf("%c%s\n",'\001',x);
}
} else {
for (i=1; i<argc; i++) {
if (strcmp(argv[i],"-")==0) {
in = stdin;
} else {
if ((in = fopen(argv[i],"r"))==NULL) {
fprintf(stderr,"Can't open %s\n", argv[i]);
continue;
}
}
while (fgets(x,sizeof(x),in) != NULL) {
printf("%c%s",'\001',x);
}
fclose(in);
}
}
}
SHAR_EOF
if test 527 -ne "`wc -c < 'say.c'`"
then
echo shar: error transmitting "'say.c'" '(should have been 527 characters)'
fi
fi # end of overwriting check
# End of shell archive
exit 0
--
------
Lefteris (princeton!tilt!kyrimis)
------kyrimis@tilt.FUN (Kriton Kyrimis) (04/13/86)
In article <408@tilt.FUN> tilt!ek (Eleftherios Koutsofios) writes: >------ > Lefteris (princeton!tilt!kyrimis) >------ -----------------------------------^ He obviously means princeton!tilt!ek Although I did help by typing parts of the program and by con- stantly nagging until it was perfect, this is Lefteris' work, so I don't think this is the correct place for an acknowledgement. :-) -- Kriton (princeton!tilt!kyrimis) ------ "Is it you, timelord?" "As far as I know, there is no one except you and me here, so it *must* be me!" ------