mrr@softie.UUCP (09/26/87)
# This is a shell archive. Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file"
# Created Fri Sep 25 07:26:48 1987
#
# This archive contains:
# FormatDisk.c
# sendpkt.c
# Speech.c
# unixwild.c
echo "Creating FormatDisk.c"
cat > FormatDisk.c <<"***EOF FormatDisk.c***"
/* Format a floppy disk (880k drive).
* Author: Mark R. Rinfret
* Date: 06/28/87
* Description:
* This set of routines may be incorporated into a program which
* has need of formatting a floppy disk. I wrote it to support my
* hard disk backup utility.
*
* History: (most recent change first)
*
* 08/26/87 -MRR- Modified FormatDisk to delay 5 seconds after
* uninhibiting the drive. This should give enough time
* for the validator to do its thing and prevent the
* "Insert disk..." requester from rearing its ugly head
* if the application attempts to access the disk as
* soon as we return.
*/
#include <exec/types.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 <exec/devices.h>
#include <devices/trackdisk.h>
#include <libraries/dosextens.h>
#include <intuition/intuition.h>
#include <functions.h>
extern struct IOExtTD *CreateExtIO();
static int CkIOErr();
/* #define DEBUG */
#define MAX_NAME 30L
#define TD_WRITE CMD_WRITE
#define TRACKSIZE NUMSECS * TD_SECTOR
/* Format a floppy disk - hardwired for the 3.5" 880k floppy drives.
* Called with:
* drivename: device name (DF0, etc.)
* name: new volume name
* Returns:
* Zero on success, 1 on failure
* Note:
* This routine does not currently perform a verification, as
* recommended by the RKM. Perhaps later...
* I also discovered that there's some erroneous crap in
* "The Amiga Programmer's Workbook, Vol. II", by
* Eugene P. Mortimore. On page 339, he states that only 512
* bytes of track data are required for formatting. The RKM
* correctly states that a "track's worth of data" is required.
* It took some playing with DiskEd to discover this error.
*/
int
FormatDisk(drivename,name)
char *drivename; char *name;
{
long checksum;
char *dos_id = "DOS";
long dosword = 0;
SHORT error;
struct MsgPort *diskport = NULL;
struct IOExtTD *diskreq = NULL;
ULONG diskchangecount;
struct Process *myprocess;
struct Window *mywindow;
USHORT status = 0, i, retry, track;
int unit;
char *volname;
char *diskbuffer;
ULONG *diskblock; /* alias for diskbuffer, ULONG type */
if (strlen(name) >= MAX_NAME) {
#ifdef DEBUG
printf("Disk name is too long!\n");
#endif
status = ERROR_INVALID_COMPONENT_NAME;
goto cleanup;
}
if ((unit = (drivename[2]-'0')) < 0 || unit >= NUMUNITS) {
#ifdef DEBUG
printf("FormatDisk: invalid drive specification!\n");
#endif
status = ERROR_INVALID_COMPONENT_NAME;
goto cleanup;
}
if (!(diskbuffer =
AllocMem((long) TRACKSIZE, MEMF_PUBLIC | MEMF_CHIP))) {
status = ERROR_NO_FREE_STORE;
goto cleanup;
}
/* Store DOS "magic word" in disk block to be written during
* formatting.
*/
diskblock = (ULONG *) diskbuffer;/* we'll need this later */
for (i = 0; i < 3; ++i)
dosword = (dosword << 8) | dos_id[i];
dosword = dosword << 8;
#ifdef DEBUG
printf("dosword is %lx\n",dosword);
#endif
for (i = 0; i < TRACKSIZE / 4; ++i)
diskblock[i] = (dosword | (long) (i & 0xff));
if ((diskport = CreatePort(0L, 0L)) == NULL) {
#ifdef DEBUG
printf("FormatDisk can't create port!\n");
#endif
status = 1; /* is there a better error code? */
goto cleanup;
}
if (!(diskreq = (struct IOExtTD *)
CreateExtIO(diskport, (long) sizeof(struct IOExtTD)))) {
status = 1;
goto cleanup;
}
if (status = OpenDevice(TD_NAME, (long) unit, diskreq, 0L)) {
#ifdef DEBUG
printf("FormatDisk: OpenDevice error: %d\n",error);
#endif
goto cleanup;
}
if (status = Inhibit(drivename, 1)) {
#ifdef DEBUG
printf("FormatDisk: unable to inhibit drive!\n");
#endif
goto cleanup;
}
/* Get the current disk change count. This allows the trackdisk
* driver to detect unwanted disk changes later on.
*/
diskreq->iotd_Req.io_Command = TD_CHANGENUM;
DoIO(diskreq);
/* Save a copy of the disk change count. */
diskchangecount = diskreq->iotd_Req.io_Actual;
#ifdef DEBUG
printf("Current disk change count is %ld\n", diskchangecount);
#endif
/* Format the disk, one track at a time. */
for (track = 0; track < NUMTRACKS; ++track) {
diskreq->iotd_Req.io_Command = TD_FORMAT;
diskreq->iotd_Req.io_Flags = 0;
diskreq->iotd_Req.io_Data = (APTR) diskbuffer;
diskreq->iotd_Count = diskchangecount;
diskreq->iotd_Req.io_Length = NUMSECS * TD_SECTOR;
diskreq->iotd_Req.io_Offset = track * NUMSECS * TD_SECTOR;
DoIO(diskreq);
if (status = CkIOErr(diskreq,"Formatting error")) {
#ifdef DEBUG
printf(" Track: %d\n",track);
#endif
goto cleanup;
}
}
/* Now comes some real KLUDGING. Fill in the root block and the
* first hash block. The information for this was gathered from
* the "AmigaDos Technical Reference Manual" and some sleuthing
* with DiskEd.
*/
for (i = 0; i < 128; ++i)
diskblock[i] = 0;
diskblock[0] = 2; /* T.SHORT (type) */
diskblock[3] = 128 - 56; /* hashtable size */
diskblock[78] = 0xffffffff; /* BMFLAG */
diskblock[79] = 881; /* first bitmap block */
DateStamp(&diskblock[105]); /* volume last altered date/time */
DateStamp(&diskblock[121]); /* volume creation date/time */
volname = (char *) &diskblock[108];
/* convert input name to BSTR */
*volname = strlen(name);
for (i = 0; i < *volname; ++i)
*(volname + 1 + i) = *(name + i);
diskblock[127] = 1; /* ST.ROOT (secondary type) */
checksum = 0;
for (i = 0; i < 128; ++i)
checksum += diskblock[i];
diskblock[5] = - checksum;
/* Write the root block out to the disk. */
diskreq->iotd_Req.io_Command = TD_WRITE;
diskreq->iotd_Req.io_Length = TD_SECTOR;
diskreq->iotd_Req.io_Offset = TD_SECTOR * 880L;
DoIO(diskreq);
if (status = CkIOErr(diskreq, "Error writing root block")) {
goto cleanup;
}
/* Write the first bitmap block. */
for (i = 0; i < 56; ++i)
diskblock[i] = 0xffffffff;
for (i = 56; i < 128; ++i)
diskblock[i] = 0;
diskblock[0] = 0xc000c037; /* hint: x37 = 55 (last word of map?) */
diskblock[28] = 0xffff3fff; /* blocks 880, 881 used */
diskblock[55] = 0x3fffffff; /* blocks 1760, 1761 used? */
diskreq->iotd_Req.io_Length = TD_SECTOR;
diskreq->iotd_Req.io_Offset = 881L * TD_SECTOR;
DoIO(diskreq); /* write out the bitmap */
if (status = CkIOErr(diskreq, "Error writing bitmap")) {
goto cleanup;
}
diskreq->iotd_Req.io_Command = ETD_UPDATE;
diskreq->iotd_Req.io_Flags = 0;
DoIO(diskreq);
/* Turn the disk motor off. */
diskreq->iotd_Req.io_Command = TD_MOTOR;
diskreq->iotd_Req.io_Length = 0;
DoIO(diskreq);
Inhibit(drivename, 0); /* enable disk validator */
Delay(3L * TICKS_PER_SECOND); /* Give it a chance */
cleanup:
CloseDevice(diskreq);
if (diskbuffer) FreeMem(diskbuffer, (long) TRACKSIZE);
if (diskreq) DeleteExtIO(diskreq, (long) sizeof(*diskreq));
if (diskport) DeletePort(diskport);
return status;
}
/* Check the disk request block for an error code. If an error
* occurred, print the argument string.
* Called with:
* req: pointer to I/O request structure
* msg: error message string
* Returns:
* error code from request structure
*/
static int CkIOErr(req, msg)
struct IOStdReq *req; char *msg;
{
register int code;
if (code = req->io_Error) {
#ifdef DEBUG
printf("%s, code: %d\n",msg,code);
#endif
}
return code;
}
#ifdef DEBUG
main(argc, argv)
int argc; char *argv[];
{
char *diskname;
char *volname;
int unit;
if (argc < 3)
volname = "GoodJob!";
else
volname = argv[2];
if (argc < 2)
diskname = "DF1:";
else {
diskname = argv[1];
if (strlen(diskname) != 4 ||
(strncmp(diskname,"df",2) && strncmp(diskname,"DF",2))) {
bad_drive:
printf("Drive name may only be df0: through df3:!\n");
exit(1);
}
if ((unit = (diskname[2] - '0')) < 0 || unit > 3)
goto bad_drive;
}
printf("Insert disk in %s, then hit return\n",diskname);
while (getchar() != '\n');
if (FormatDisk(diskname,volname))
printf("FormatDisk failed\n");
else {
printf("FormatDisk succeeded\n");
}
}
#endif
***EOF FormatDisk.c***
echo "Creating sendpkt.c"
cat > sendpkt.c <<"***EOF sendpkt.c***"
/* Filename: sendpkt.c
* Authors: Andy Finkel, Phil Lindsay, Commodore-Amiga
* Date: 06/29/87
*
* This package was derived from "touch.c", written by Andy Finkel
* and Phil Lindsay of Commodore-Amiga.
*/
#include "exec/types.h"
#include "exec/ports.h"
#include "exec/io.h"
#include "exec/memory.h"
#include "libraries/dos.h"
#include "libraries/dosextens.h"
#ifdef AZTEC_C
#include <functions.h>
#endif
LONG
sendpkt(id,type,args,nargs)
struct MsgPort *id; /* process indentifier ... (handler's
message port ) */
LONG type, /* packet type ... (what you want
handler to do ) */
args[], /* a pointer to argument list */
nargs; /* number of arguments in list */
{
struct MsgPort *replyport;
struct StandardPacket *packet;
LONG count,*pargs,res1=NULL;
if (!(replyport = (struct MsgPort *) CreatePort(NULL,NULL)))
return(NULL);
packet = (struct StandardPacket *)
AllocMem((LONG)sizeof(*packet),MEMF_PUBLIC|MEMF_CLEAR);
if (packet) {
packet->sp_Msg.mn_Node.ln_Name = &(packet->sp_Pkt);/* link packet */
packet->sp_Pkt.dp_Link = &(packet->sp_Msg);/* to message */
packet->sp_Pkt.dp_Port = replyport;/* set-up reply port */
packet->sp_Pkt.dp_Type = type;/* what to do... */
/* move all the arguments to the packet */
pargs = &(packet->sp_Pkt.dp_Arg1);/* address of first argument */
for (count=0; (count < nargs) && (count < 7); count++)
pargs[count] = args[count];
PutMsg(id,packet); /* send packet */
WaitPort(replyport); /* wait for packet to come back */
GetMsg(replyport); /* pull message */
res1 = packet->sp_Pkt.dp_Res1;/* get result */
FreeMem(packet,(LONG)sizeof(*packet));
}
DeletePort(replyport);
return(res1);
}
***EOF sendpkt.c***
echo "Creating Speech.c"
cat > Speech.c <<"***EOF Speech.c***"
/* Minimal-capability speech support package.
* Author: Mark R. Rinfret
* Date: 07/30/87
* Description:
*
* This package provides a quick and dirty means for adding
* speech to C language programs. In order to use it, observe
* the following:
*
* 1. Call SpeechOn - return parameter of 0 => success.
* 2. Call Say(<your message in English>) as often as the
* application requires.
* 3. Call SpeechOff to close libraries/ports/devices.
*/
#include <exec/types.h>
#include <exec/exec.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <devices/narrator.h>
#include <libraries/translator.h>
#include <functions.h>
/*#define DEBUG */
#define PHONEME_MAX 1024L /* size of phoneme buffer */
/* Which audio channels to use */
BYTE audio_chan[] = {3, 5, 10, 12};
struct Library *TranslatorBase = NULL;
struct narrator_rb voice_io; /* Narrator I/O request block */
struct MsgPort *voice_port = NULL;
ULONG narrator_status = -1L,translate_error;
UBYTE Phonemes[PHONEME_MAX]; /* Phoneme text buffer */
/******************
* ROUTINES *
******************/
/* Enable speech capability. */
SpeechOn(on)
int on;
{
if (!(TranslatorBase = (struct Library *)
OpenLibrary("translator.library", (long) LIBRARY_VERSION))) {
#ifdef DEBUG
DebugWrite("Can't open the translator library!\n");
#endif
fail:
SpeechOff(); /* close whatever's open */
return 1;
}
/* Open a reply port for the narrator. */
if (!(voice_port = CreatePort(0L, 0L))) {
#ifdef DEBUG
DebugWrite("Can't create narrator reply port!\n");
#endif
goto fail;
}
voice_io.message.io_Message.mn_ReplyPort = voice_port;
/* Open the device */
if ((narrator_status =
OpenDevice("narrator.device", 0L, &voice_io, 0L))) {
#ifdef DEBUG
DebugWrite("Can't open the Narrator device!\n");
#endif
goto fail;
}
return 0;
}
SpeechOff()
{
if (voice_port)
DeletePort(voice_port);
if (!narrator_status)
CloseDevice(&voice_io);
if (TranslatorBase)
CloseLibrary(TranslatorBase);
return(0);
}
Say(English)
char *English;
{
if (!TranslatorBase) {
if (SpeechOn()) return 1;
}
if (translate_error =
Translate(English, (long) strlen(English),
Phonemes, PHONEME_MAX)) {
#ifdef DEBUG
DebugWrite("Translator error!\n");
#endif
}
/* Set up the write channel information */
voice_io.ch_masks = (UBYTE *) (audio_chan);
voice_io.nm_masks = sizeof(audio_chan);
voice_io.mouths = 0;
voice_io.message.io_Command = CMD_WRITE;
voice_io.message.io_Offset = 0;
voice_io.message.io_Data = (APTR)Phonemes;
voice_io.message.io_Message.mn_Length = sizeof(voice_io);
voice_io.message.io_Length = strlen(Phonemes);
DoIO(&voice_io);
}
#ifdef DEBUG
DebugWrite(msg)
char *msg;
{
puts(msg);
}
main()
{
short i;
char *s;
static char *text[] = {
"I am an Amiga computer. I am currently testing my voice ability.",
"This is pretty incredible, don't you agree? I thought you would.",
"This package is really a set of routines to be used by an application.",
"All you have to do is call Speech On first, ",
"then call Say as often as you like.",
NULL
};
SpeechOn();
for (i = 0;s = text[i]; ++i) {
Say(s);
Delay(30L);
}
SpeechOff();
}
#endif
***EOF Speech.c***
echo "Creating unixwild.c"
cat > unixwild.c <<"***EOF unixwild.c***"
/* unixwild.c
* Unix (tm) wildcard support routines.
* Created on 08/07/87
*/
/* Text a filename for wildcard content.
* Called with:
* name: pathname
* Returns:
* 0 => no wild characters
* 1 => 1 or more wild characters
*/
int
iswild(name)
char *name;
{
register char c, *s;
for (s = name; c = *s++; )
if (c == '*' || c == '?') return 1;
return 0;
}
/*
* Compare a wild card name with a normal name.
* Called with:
* wild: name with "wild" content
* name: "normal" name
* Returns:
* 0 => names don't match
* 1 => names match
*
* This source was lifted from Steve Drew's version of Matt Dillon's
* shell, version 2.06m.
*
*/
#define MAXB 8
int
wildcmp(wild,name)
char *wild,*name;
{
register char *w = wild;
register char *n = name;
char *back[MAXB][2];
register char s1,s2;
int bi = 0;
while (*n || *w){
switch (*w){
case '*':
if (bi == MAXB){
#ifdef DEBUG
printf("Too many levels of '*'\n");
#endif
return (0);
}
back[bi][0]= w;
back[bi][1]= n;
++bi;
++w;
continue;
goback:
--bi;
while (bi >= 0 && *back[bi][1]== '\0')
--bi;
if (bi < 0)
return (0);
w = back[bi][0]+ 1;
n = ++back[bi][1];
++bi;
continue;
case '?':
if (!*n){
if (bi)
goto goback;
return (0);
}
break;
default:
s1 = (*n >= 'A' && *n <= 'Z')?*n - 'A' + 'a' :*n;
s2 = (*w >= 'A' && *w <= 'Z')?*w - 'A' + 'a' :*w;
if (s1 != s2){
if (bi)
goto goback;
return (0);
}
break;
}
if (*n)
++n;
if (*w)
++w;
}
return (1);
}
#ifdef DEBUG
char normal[81], wild[81];
main()
{
puts("Terminate this program by entering 'quit'");
for (;;) {
puts("Enter the non-wild pathname:");
gets(normal);
if (!strcmp(normal,"quit")) break;
if (iswild(normal)) {
puts("No, idiot! Enter a non-wild filename!");
continue;
}
puts("Enter a wild pathname:");
gets(wild);
if (wildcmp(wild,normal))
puts("Yup, they match.");
else
puts("No match here.");
}
}
#endif
***EOF unixwild.c***
--
< Mark R. Rinfret, mrr@softie, ..rayssd!unisec!softie!mrr >
< SofTech, Inc. Home: 401-846-7639 >
< 1 Silva Lane, Work: 401-849-4174 >
< Middletown, RI 02840 "The name has changed but I'm still guilty." >