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." >