mark@s.cc.purdue.edu.UUCP (09/17/87)
!!!!! Note: If you are using my unshar program, at this point in time, !!!!! You MUST create the directory 'misc' before unshar'ing this !!!!! file! # This is a shell archive. # Remove everything above and including the cut line. # Then run the rest of the file through sh. #----cut here-----cut here-----cut here-----cut here----# #!/bin/sh # Xshar: Extended Shell Archiver. # This archive created: Wed Sep 16 20:52:10 1987 # By: Craig Norborg (Purdue University Computing Center) # Run the following text with /bin/sh to create: # misc # misc/CopyFile.c # misc/DateRequest.c # misc/Dates.c # misc/DiskMisc.c # misc/FileMisc.c # misc/RenameDisk.c # misc/Speech.c # misc/formatdisk.c # misc/sendpkt.c mkdir misc cat << \SHAR_EOF > misc/CopyFile.c /* * Copy file, preserving date. * Depends upon file date routines in FileMisc.c * Original author: Jeff Lydiatt, Vancouver, Canada */ #include <stdio.h> #include <exec/types.h> #include <libraries/dos.h> #include <exec/memory.h> #include <functions.h> #define BUFMAX 32768 #define MAXSTR 127 extern char *malloc(); extern long Chk_Abort(); extern BOOL GetFileDate(), SetFileDate(); extern long IoErr(); /* Copy the last modified date from one file to another. * Called with: * from: name of source file * to: name of destination file * Returns: * 0 => success, 1 => failure * Note: * Dynamic memory allocation of the DateStamp struction is * necessary to insure longword alignment. */ BOOL CopyFileDate(from,to) char *from, *to; { struct DateStamp *date; int status = 1; /* default is fail code */ if (date = (struct DateStamp *) AllocMem((long) sizeof(struct DateStamp), MEMF_PUBLIC)) { if (GetFileDate(from,date)) if (SetFileDate(to,date)) status = 0; FreeMem(date,(long) sizeof(struct DateStamp)); } return status; } int CopyFile(from,to) char *from,*to; { char *buffer; char errmsg[256]; long status,count,bufsize; struct FileHandle *fin,*fout; static char *errfmt = "I/O error %ld, file %s"; if ((fin = Open(from,MODE_OLDFILE ))== NULL ){ status = IoErr(); #ifdef DEBUG sprintf(errmsg,errfmt,status, from); print_err: puts(errmsg); #endif return status; } if ((fout = Open(to,MODE_NEWFILE ))== NULL ){ status = IoErr(); Close(fin ); #ifdef DEBUG sprintf(errmsg,errfmt,IoErr(),to); goto print_err; #endif return status; } for (bufsize = BUFMAX; bufsize > 2048; bufsize -= 2048 ) if ((buffer = malloc((unsigned int)bufsize))!= NULL ) break; if (bufsize <= 2048 ){ Close(fin ); Close(fout ); #ifdef DEBUG puts("CopyFile: Not enough memory." ); #endif return ERROR_NO_FREE_STORE; } status = 1; while(status > 0 && (count = Read(fin,buffer,bufsize ))== bufsize ) if (Chk_Abort()) status = -1; else status = Write(fout,buffer,count ); if (status > 0 && count > 0 ) status = Write(fout,buffer,count ); Close(fin ); Close(fout); free(buffer); if (status < 0 || count < 0 ){ unlink(to); return 1; } return CopyFileDate(from, to); } SHAR_EOF cat << \SHAR_EOF > misc/DateRequest.c /* Date Requester Package * Author: Mark R. Rinfret * Description: * This source file contains a canned date requester routine which * supports time and date entry in MM/DD/YY HH:MM:SS notation (time is * optional) to a DateStamp structure. This package is dependent upon * the package "dates.c" (same author) for DateStamp/string conversions. * * History: (most recent change first) * * 07/20/87 -MRR- Created this file. */ #include <intuition/intuition.h> #include <intuition/intuitionbase.h> #include <libraries/dosextens.h> #include <graphics/gfxbase.h> #include <graphics/gfx.h> #include <graphics/display.h> #include <graphics/text.h> #include <functions.h> #include <ctype.h> /********************************************************************** * Gadget Structure Definitions * * The following structures were defined using EGAD! (by the Programmer's * Network) and further modified by the author. * **********************************************************************/ /* Definitions for Gadget ID numbers */ #define DATEGAD 0 /********************************************************************** * Text attribute structures used in rendering IntuiTexts **********************************************************************/ static char def_font[] ="topaz.font"; static struct TextAttr TxtAt_Plain = { (UBYTE *)def_font, 8, FS_NORMAL, FPF_ROMFONT }; /********************************************************************** * Border Definitions for dategad gadget **********************************************************************/ static SHORT dategad_Pairs_1[] = { 0, 0, 150, 0, 150, 9, 0, 9, 0, 0 }; /********************************************************************** * String information for the dategad string gadget. **********************************************************************/ static UBYTE dategad_sbuf_1[19] = "00/00/00 00:00:00"; static UBYTE dategad_ubuf_1[19]; static struct StringInfo dategad_txstr_1 = { dategad_sbuf_1, dategad_ubuf_1, /* Buffer, UndoBuffer */ 0, 18, 0, /* BufferPos, MaxChars, DispPos */ 0, 18, /* UndoPos, NumChars */ 0, 0, 0, /* DispCount, CLeft, CTop */ 0x0, 0, /* LayerPtr, LongInt */ 0x0 /* AltKeyMap */ }; /********************************************************************** * Gadget Structure definition for the dategad gadget. **********************************************************************/ static struct Gadget dategad = { NULL, /* NextGadget pointer */ 64, 40, /* LeftEdge, TopEdge */ 150, 9, /* Width, Height */ /* Gadget Flags */ GADGHCOMP, /* Activation Flags */ RELVERIFY /* | ENDGADGET */, /* GadgetType */ REQGADGET | STRGADGET, /* string gadget belongs to requester */ NULL, /* GadgetRender - no border */ NULL, /* SelectRender */ NULL, /* GadgetText */ 0x0, /* MutualExclude */ (APTR)&dategad_txstr_1, /* SpecialInfo */ DATEGAD, /* GadgetID */ NULL /* UserData Pointer */ }; static struct Requester daterequest; /* requester for the date */ static SHORT datereq_pairs1[] = { 30, 10, 230, 10, 250, 30, 250, 50, 230, 70, 30, 70, 10, 50, 10, 30, 30, 10 }; static struct Border datereq_bord1 = { -1, -1, /* LeftEdge, TopEdge */ 2, 1, JAM2, /* FrontPen, BackPen, DrawMode*/ 9, /* Count of XY pairs */ (SHORT *)&datereq_pairs1, /* XY pairs */ NULL /* Next Border */ }; static struct IntuiText datereqtext = { 2, 1, /* FrontPen / BackPen */ JAM2, /* DrawMode */ 20, /* LeftEdge */ 30, /* TopEdge */ &TxtAt_Plain, /* ITextFont */ (UBYTE *) "Enter date:", /* IText */ NULL /* NextText */ }; static initialized = 0; /* set to 1 after initialization */ static InitDateRequest() { InitRequester(&daterequest); daterequest.LeftEdge = 60; daterequest.TopEdge = 10; daterequest.Width = 260; daterequest.Height = 80; daterequest.ReqGadget = &dategad; daterequest.ReqText = &datereqtext; daterequest.ReqBorder = &datereq_bord1; daterequest.BackFill = 0; ++initialized; } /* Request a date from the user. * Called with: * window: pointer to window structure * prompt: string to be used as the prompt text * default_date: pointer to default date or NULL * date: pointer to date result (returned) * Returns: * status code: 0 => success, 1 => failure * (actually, always returns 0 - can't leave without good date) */ DateRequest(window,prompt,default_date,date) struct Window *window; char *prompt; struct DateStamp *default_date,*date; { ULONG class; /* message class */ USHORT code; /* message code */ USHORT gadgid; /* gadget ID */ APTR Iadr; /* address field from message */ struct IntuiMessage *msg; /* Intuition message pointer */ SHORT x,y; /* mouse x and y position */ if (!initialized) InitDateRequest(); datereqtext.IText = prompt; if (default_date) /* write default date in requester? */ DS2Str(dategad_sbuf_1,"%02m/%02d/%02y %02h:%02n:%02s", default_date); else *dategad_sbuf_1 = '\0'; Request(&daterequest, window); for (;;) { Wait(1L << window->UserPort->mp_SigBit); while (msg = GetMsg(window->UserPort)) { class = msg->Class; code = msg->Code; Iadr = (APTR) msg->IAddress; x = msg->MouseX; y = msg->MouseY; ReplyMsg(msg); /* acknowledge the message */ switch (class) { case REQSET: ActivateGadget(&dategad,window,&daterequest); break; case GADGETUP: if ( ! Str2DS(dategad_sbuf_1, date) ) { EndRequest(&daterequest, window); return 0; } else DisplayBeep(window->WScreen); /* bad conversion */ break; default: break; /* ignore the rest */ } /* end switch(class) */ } } } /* #define DEBUG */ #ifdef DEBUG /* --- Only compiled in the debug version --- */ #include <exec/memory.h> /* New window structure */ struct NewWindow newwindow = { 0,0,640,200,0,1, /* IDCMP Flags */ MOUSEMOVE | MENUPICK | MOUSEBUTTONS | CLOSEWINDOW | GADGETDOWN | GADGETUP | REQSET, /* Flags */ WINDOWCLOSE | WINDOWDEPTH | ACTIVATE | RMBTRAP | REPORTMOUSE, NULL, /* First gadget */ NULL, /* Checkmark */ (UBYTE *)"Date Requester Test Program", /* Window title */ NULL, /* No custom streen */ NULL, /* Not a super bitmap window */ 0,0,640,200, /* Not used, but set up anyway */ WBENCHSCREEN }; struct IntuitionBase *IntuitionBase; struct Window *mywindow; struct DateStamp *ds; static struct IntuiText MoreText = { AUTOFRONTPEN, /* FrontPen */ AUTOBACKPEN, /* BackPen */ JAM2, /* DrawMode */ AUTOLEFTEDGE, /* LeftEdge */ AUTOTOPEDGE, /* TopEdge */ AUTOITEXTFONT, /* ITextFont */ (UBYTE *) "Want to play some more?", /* IText */ NULL /* NextText */ }; static struct IntuiText YesText = { AUTOFRONTPEN, /* FrontPen */ AUTOBACKPEN, /* BackPen */ AUTODRAWMODE, /* DrawMode */ AUTOLEFTEDGE, /* LeftEdge */ AUTOTOPEDGE, /* TopEdge */ AUTOITEXTFONT, /* ITextFont */ (UBYTE *) "Sure!", /* IText */ NULL /* NextText */ }; static struct IntuiText NoText = { AUTOFRONTPEN, /* FrontPen */ AUTOBACKPEN, /* BackPen */ JAM2, /* DrawMode */ AUTOLEFTEDGE, /* LeftEdge */ AUTOTOPEDGE, /* TopEdge */ AUTOITEXTFONT, /* ITextFont */ (UBYTE *) "Nope!", /* IText */ NULL /* NextText */ }; main() { short keep_going; if (!(IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library",33L))) { puts("Failed to open Intuition library!"); exit(1); } ds = (struct DateStamp *) AllocMem((long) sizeof(struct DateStamp), MEMF_PUBLIC); DateStamp(ds); /* get current date/time */ mywindow = OpenWindow(&newwindow); do { DateRequest(mywindow, "Enter date and time", ds, ds); keep_going = AutoRequest(mywindow, &MoreText, &YesText, &NoText, NULL, NULL, 220L, 50L); } while (keep_going); if (mywindow) CloseWindow(mywindow); if (IntuitionBase) CloseLibrary(IntuitionBase); } #endif SHAR_EOF cat << \SHAR_EOF > misc/Dates.c /* General routines to provide date support for the DateStamp * date format. * * Author: Mark R. Rinfret (mark@unisec.usi.com) * Date: 07/18/87 * * This source is released to the public domain by the author, without * restrictions. However, it is requested that you give credit where * credit is due and share any bug fixes or enhancements with the author. */ #include <libraries/dos.h> #include <exec/memory.h> #include <ctype.h> #include <functions.h> /* #define DEBUG */ typedef struct { unsigned short year,month,day,hour,minute,second; } unpacked_date; static char *daynames[] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }; static USHORT monthdays[12] = {0,31,59,90,120,151,181,212,243,273,304,334}; static char *monthnames[12] = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" }; /* Compare two DateStamp values. * Called with: * d1,d2: pointers to DateStamp structs * * Returns: * < 0 => d1 < d2 * 0 => d1 == d2 * > 0 => d1 > d2 * * Note: * This routine makes an assumption about the DateStamp structure, * specifically that it can be viewed as an array of 3 long integers * in days, minutes and ticks order. */ int CompareDS(d1, d2) long *d1, *d2; { USHORT i; long compare; for (i = 0; i < 3; ++i) { if (compare = (d1[i] - d2[i])) { if (compare < 0) return -1; return 1; } } return 0; /* dates match */ } /* Convert a DateStamp to a formatted string. * Called with: * fmt: format string * The format of the format string is very similar to that * for printf, with the exception that the following letters * have special significance: * y => year minus 1900 * Y => full year value * m => month value as integer * M => month name * d => day of month (1..31) * D => day name ("Monday".."Sunday") * h => hour in twenty-four hour notation * H => hour in twelve hour notation * i => 12 hour indicator for H notation (AM or PM) * I => same as i * n => minutes (sorry...conflict with m = months) * N => same as n * s => seconds * S => same as s * * All other characters are passed through as part of the normal * formatting process. The following are some examples with * Saturday, July 18, 1987, 13:53 as an input date: * * "%y/%m/%d" => 87/7/18 * "%02m/%02d/%2y" => 07/18/87 * "%D, %M %d, %Y" => Saturday, July 18, 1987 * "%02H:%02m i" => 01:53 PM * "Time now: %h%m" => Time now: 13:53 * * str: string to write date on * d: pointer to DateStamp structure * */ void DS2Str(str,fmt,d) char *str, *fmt; struct DateStamp *d; { unpacked_date date; char fc,*fs,*out; USHORT ivalue; char new_fmt[256]; /* make it big to be "safe" */ USHORT new_fmt_lng; char *svalue; UnpackDS(d, &date); /* convert DateStamp to unpacked format */ *str = '\0'; /* insure output is empty */ out = str; fs = fmt; /* make copy of format string pointer */ while (fc = *fs++) { /* get format characters */ if (fc == '%') { /* formatting meta-character? */ new_fmt_lng = 0; new_fmt[new_fmt_lng++] = fc; /* copy width information */ while (isdigit(fc = *fs++) || fc == '-') new_fmt[new_fmt_lng++] = fc; switch (fc) { /* what are we trying to do? */ case 'y': /* year - 1980 */ ivalue = date.year - 1900; write_int: new_fmt[new_fmt_lng++] = 'd'; new_fmt[new_fmt_lng] = '\0'; sprintf(out,new_fmt,ivalue); out = str + strlen(str); break; case 'Y': /* full year value */ ivalue = date.year; goto write_int; case 'm': /* month */ ivalue = date.month; goto write_int; case 'M': /* month name */ svalue = monthnames[date.month - 1]; write_str: new_fmt[new_fmt_lng++] = 's'; new_fmt[new_fmt_lng] = '\0'; sprintf(out,new_fmt,svalue); out = str + strlen(str); break; case 'd': /* day */ ivalue = date.day; goto write_int; case 'D': /* day name */ svalue = daynames[d->ds_Days % 7]; goto write_str; case 'h': /* hour */ ivalue = date.hour; goto write_int; case 'H': /* hour in 12 hour notation */ ivalue = date.hour; if (ivalue >= 12) ivalue -= 12; goto write_int; case 'i': /* AM/PM indicator */ case 'I': if (date.hour >= 12) svalue = "PM"; else svalue = "AM"; goto write_str; case 'n': /* minutes */ case 'N': ivalue = date.minute; goto write_int; case 's': /* seconds */ case 'S': ivalue = date.second; goto write_int; default: /* We are in deep caca - don't know what to do with this * format character. Copy the raw format string to the * output as debugging information. */ new_fmt[new_fmt_lng++] = fc; new_fmt[new_fmt_lng] = '\0'; strcat(out, new_fmt); out = out + strlen(out); /* advance string pointer */ break; } } else *out++ = fc; /* copy literal character */ } *out = '\0'; /* terminating null */ } /* Convert a string to a DateStamp. * Called with: * str: string containing date in MM/DD/YY format * d: pointer to DateStamp structure * Returns: * status code (0 => success, 1 => failure) */ int Str2DS(str, d) char *str; struct DateStamp *d; { register char c; int count; int i, item; char *s; int values[3]; int value; int years,months,days,hours,minutes,seconds; s = str; for (item = 0; item < 2; ++item) { /* item = date, then time */ for (i = 0; i < 3; ++i) values[i] = 0; count = 0; while (c = *s++) { /* get date value */ if (c <= ' ') break; if (isdigit(c)) { value = 0; do { value = value*10 + c - '0'; c = *s++; } while (isdigit(c)); if (count == 3) { bad_value: #ifdef DEBUG puts("Error in date-time format.\n"); printf("at %s: values(%d) = %d, %d, %d\n", s, count, values[0], values[1], values[2]); #endif return 1; } values[count++] = value; if (c <= ' ') break; } } /* end while */ if (item) { /* getting time? */ hours = values[0]; minutes = values[1]; seconds = values[2]; } else { /* getting date? */ if (count != 3) goto bad_value; months = values[0]; days = values[1]; years = values[2]; } } /* end for */ SetDateStamp(d,years,months,days,hours,minutes,seconds); return 0; } /* Set a DateStamp structure, given the date/time components. * Called with: * d: pointer to DateStamp * years: may be 19xx or just xx * months: 1..12 * days: 1..31 * minutes: 0..59 * seconds: 0..59 */ SetDateStamp(d,years,months,days,hours,minutes,seconds) struct DateStamp *d; int years,months,days,hours,minutes,seconds; { USHORT leapyear; if (years > 1900) years = years - 1900; leapyear = (years % 4 ? 0 : 1); years = years - 78; if (months < 1 || months > 12) /* somebody goofed? */ months = 1; days = days - 1 + monthdays[months-1]; if (leapyear && (months > 2)) ++days; d->ds_Days = years * 365 + (years + 1) / 4 + days ; d->ds_Minute = hours * 60 + minutes; d->ds_Tick = seconds * TICKS_PER_SECOND; } /* Unpack a DateStamp structure into an unpacked_date structure. * Called with: * ds: pointer to DateStamp structure * du: pointer to unpacked_date structure */ UnpackDS(ds, du) struct DateStamp *ds; unpacked_date *du; { USHORT i, leap_years, leap, temp, test_value; du->year = ds->ds_Days / 365 + 1978; /* is current year a leapyear? */ leap = ( (du->year % 4) == 0); /* how many leap years since "beginning of time"? */ leap_years = (du->year - 1976 - 1) / 4; /* get days remaining in year */ temp = ds->ds_Days % 365 - leap_years; /* find month */ du->month = 0; du->day = 0; for (i = 11; i >= 0; --i) { test_value = monthdays[i]; if (i > 2) test_value += leap; if (temp >= test_value) { du->month = i + 1; du->day = temp - test_value + 1; break; } } du->hour = ds->ds_Minute / 60; du->minute = ds->ds_Minute % 60; du->second = ds->ds_Tick / TICKS_PER_SECOND; } #ifdef DEBUG main() { int compflag; char datestr[81], instr[81]; struct DateStamp *ds, *now; unpacked_date du; now = (struct DateStamp *) AllocMem((long) sizeof(struct DateStamp), MEMF_PUBLIC); ds = (struct DateStamp *) AllocMem((long) sizeof(struct DateStamp), MEMF_PUBLIC); puts("Enter a date string and I will convert it. To quit, hit RETURN"); while (1) { DateStamp(now); UnpackDS(now, &du); printf("\nCurrent date and time: %02d/%02d/%02d %02d:%02d:%02d\n", du.month,du.day,du.year,du.hour,du.minute,du.second); puts("\nEnter the date [and time]:"); gets(instr); if (*instr == '\0') break; if (Str2DS(instr,ds)) puts("Error encountered in input string"); else { DS2Str(datestr, "%02m/%02d/%02y %02h:%02n:%02s", ds); puts(datestr); DS2Str(datestr, "%D, %M %d, %Y", ds); puts(datestr); DS2Str(datestr, "The time entered is %02H:%02N %i", ds); puts(datestr); compflag = CompareDS(ds,now); printf("The date input is "); if (compflag < 0) printf("earlier than"); else if (compflag == 0) printf("the same as"); else printf("later than"); puts(" the current date."); } } FreeMem(ds, (long) sizeof(struct DateStamp)); FreeMem(now, (long) sizeof(struct DateStamp)); } #endif SHAR_EOF cat << \SHAR_EOF > misc/DiskMisc.c /* DiskMisc.c - miscellaneous disk support routines. * Mark Rinfret (et al), 1987 */ /*#define DEBUG*/ #include <exec/types.h> #include <exec/memory.h> #include <exec/ports.h> #include <exec/io.h> #include <libraries/dosextens.h> #include <functions.h> extern LONG sendpkt(); /* This routine returns the number of disk blocks remaining on the * drive specified by 'name'. Though 'name' would typically be the * drive name or volume name, it can also be the name of any file * on the disk drive. * Called with: * name: disk device or volume name * Returns: * > 0 => number of blocks available * < 0 => error status */ long DiskBlocks(name) char *name; { struct FileLock *lock = NULL; struct InfoData *info = NULL; long int blocks = -1L; long IoErr(); if (lock = (struct FileLock *) Lock(name,ACCESS_READ)) { if (info = AllocMem((long)sizeof(struct InfoData),MEMF_PUBLIC)) { if (Info(lock,info)) { blocks = info->id_NumBlocks - info->id_NumBlocksUsed; } else { blocks = -IoErr(); #ifdef DEBUG printf("DiskBlocks: can't get Info on %s; error %ld\n", name, blocks); #endif } } else { blocks = -ERROR_NO_FREE_STORE; #ifdef DEBUG puts("DiskBlocks: no memory!"); #endif } } else { blocks = -IoErr(); #ifdef DEBUG printf("DiskBlocks: can't lock %s; error %ld\n",name,blocks); #endif } if (lock) UnLock(lock); if (info) FreeMem(info,(long)sizeof(struct InfoData)); return blocks; /* bad status indicator */ } /* Disk ACTION_INHIBIT support routine. * Author: Mark R. Rinfret * Date: 06/29/87 * * This routine provides support for user-written disk formatting, copy * operations which benefit from suppressing/restoring disk validation. */ int Inhibit(drivename, code) char *drivename; int code; { struct MsgPort *task; LONG arg[2]; LONG rc; if (!(task=(struct MsgPort *) DeviceProc(drivename))) return 1; /* fail, darn it! */ arg[0] = code; /* Now, cross all your fingers and toes... */ return ( !sendpkt(task,ACTION_INHIBIT,arg,1)); } #ifdef DEBUG main() { long blocks; blocks = DiskBlocks("df0:"); if (blocks == -1L) puts("Bad status from DiskBlocks()"); else printf("Disk blocks left on df0: %ld\n",blocks); } #endif SHAR_EOF cat << \SHAR_EOF > misc/FileMisc.c /* File date routines. * Filename: FileDates.c */ #include "exec/types.h" #include "exec/ports.h" #include "exec/io.h" #include "exec/memory.h" #include "libraries/dosextens.h" #include <stdio.h> #define AZTEC 1 #ifdef AZTEC #include "functions.h" /* aztec C include */ #endif #define ACTION_SETDATE_MODE 34L /* Set creation date on file */ #define DOSTRUE -1L /* AmigaDos TRUE */ #define MAXARGS 7L /* limit in packet structure (dosextens.h) */ #define NARGS 4L /* Number of args for setdate */ long sendpkt(); ^L /*---------------------------------------------------------------------*/ /* GetFileDate: get the datestamp the given file. */ /*---------------------------------------------------------------------*/ BOOL GetFileDate(name, date) char *name; register struct DateStamp *date; { struct FileInfoBlock *Fib; ULONG FLock; int result; register struct DateStamp *d; if ((FLock = (ULONG)Lock(name,(long)(ACCESS_READ)))== NULL) return FALSE; Fib = (struct FileInfoBlock *) AllocMem((long)sizeof(struct FileInfoBlock), (long)(MEMF_CHIP|MEMF_PUBLIC)); if (Fib == NULL ) result = FALSE; else{ if (!Examine(FLock,Fib )) result = FALSE; else if (Fib->fib_DirEntryType > 0 ) result = FALSE; /* It's a directory */ else{ d = &Fib->fib_Date; date->ds_Days = d->ds_Days; date->ds_Minute = d->ds_Minute; date->ds_Tick = d->ds_Tick; result = TRUE; } FreeMem((void *)Fib,(long)sizeof(struct FileInfoBlock)); } UnLock(FLock); return result; } ^L /* Examine a pathname to determine if it is a device or directory name. * Called with: * name: pathname specification * Returns: * 0 => no * 1 => yes * <0 => -<system error number> */ int IsDir(name) char *name; { struct FileInfoBlock *FIB = NULL; struct Lock *lock = NULL; int status; if (!(FIB = AllocMem((long)sizeof(struct FileInfoBlock), MEMF_CHIP|MEMF_CLEAR))) { return -ERROR_NO_FREE_STORE; } if (!(lock=Lock(name,SHARED_LOCK))) { status = -IoErr(); goto done; } if ((Examine(lock,FIB))==0){ status = -IoErr(); goto done; } status = (FIB->fib_DirEntryType > 0); done: if (FIB) FreeMem(FIB, (long) sizeof(struct FileInfoBlock)); UnLock(lock); return status; } ^L /*---------------------------------------------------------------------*/ /* SetFileDate: datestamp the given file with the given date. */ /*---------------------------------------------------------------------*/ BOOL SetFileDate(name,date ) char *name; struct DateStamp *date; { struct MsgPort *task; /* for process id handler */ ULONG arg[4]; /* array of arguments */ char *bstr, *strcpy(); /* of file to be set */ long rc; char *strchr(); int strlen(); rc = 0; if (!(bstr = (char *)AllocMem(68L,(long)(MEMF_PUBLIC)))) goto exit2; if (!(task = (struct MsgPort *)DeviceProc(name ))) goto exit1; /* Dos Packet needs the filename in Bstring format */ (void)strcpy(bstr+1,name ); *bstr = strlen(name ); arg[0]= (ULONG)NULL; arg[1]= (ULONG)IoErr(); /* lock on parent director set by DeviceProc() */ arg[2]= (ULONG)bstr >> 2; arg[3]= (ULONG)date; rc = sendpkt(task,ACTION_SETDATE_MODE,arg,4L ); exit1: if (bstr ) FreeMem((void *)bstr,68L ); exit2: if (rc == DOSTRUE ) return TRUE; else return FALSE; } SHAR_EOF cat << \SHAR_EOF > misc/RenameDisk.c /* Rename a disk. * Author: Mark R. Rinfret * Date: 06/27/87 * * This package was derived from "touch.c", written by Andy Finkel * and Phil Lindsay of Commodore-Amiga. I wrote RenameDisk as a * support routine for my hard disk backup utility. */ /* Enable the next #define if you want to do testing. This will cause * generation of a main program. For practical use, the RELABEL command * in the C: directory is much more efficient. */ /* #define STAND_ALONE */ #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 extern LONG sendpkt(); #ifndef AZTEC_C extern int strcpy(); extern int strlen(); #endif #define DOSTRUE -1 #define MAX_NAME 30L #ifdef STAND_ALONE main(argc,argv) int argc; char *argv[]; { unsigned code = 0; if(argc!=3){ puts("Bad arguments\n"); } else if (RenameDisk(argv[1], argv[2])) code = 20; exit(code); } #endif int RenameDisk(oldname, newname) char *oldname, *newname; { struct MsgPort *task; LONG arg[4]; LONG rc; USHORT fail = 0; ULONG lock; ULONG plock; UBYTE *pointer; if (strlen(newname) >= MAX_NAME) /* name too long? */ return 1; if(!(pointer= (UBYTE *) AllocMem(MAX_NAME,MEMF_PUBLIC))) { ++fail; goto cleanup; } if (!(task=(struct MsgPort *) DeviceProc(oldname))) { ++fail; goto cleanup; } /* Make sure that the old name is valid. */ if(!(lock = (ULONG) Lock(oldname,SHARED_LOCK))) { ++fail; goto cleanup; } UnLock(lock); /* Convert the nice C string to an ugly BSTR :-) */ strcpy((pointer + 1),newname); *pointer = strlen(newname); arg[0]= (ULONG) &pointer[0]>> 2; /* BSTR of filename */ /* Now, cross all your fingers and toes... */ rc = sendpkt(task,ACTION_RENAME_DISK,arg,1); if(!rc) ++fail; cleanup: if (pointer) FreeMem(pointer, MAX_NAME); return fail; } /* This is the actual workhorse which tells DOS what to do. Aztec C * has a new function, "dos_packet", but I prefer this one. Thanks, * Phil and Andy! */ 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); } /* Functions strcpy, strlen are defined by Aztec C library. */ #ifndef AZTEC_C int strcpy(to,from ) register char *to,*from; { do { *to++= *from; }while(*from++); } int strlen(s ) register char *s; { register i = 0; while(*s++) i++; return(i ); } #endif /* eof */ SHAR_EOF cat << \SHAR_EOF > misc/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; ULONG narrator_status,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_Message.mn_ReplyPort = NULL;*/ 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 SHAR_EOF cat << \SHAR_EOF > misc/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) */ #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 <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: * unit: drive number (0 - NUMUNITS-1) * 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; USHORT fail = 0, i, 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 fail = ERROR_INVALID_COMPONENT_NAME; goto cleanup; } if ((unit = (drivename[2]-'0')) < 0 || unit >= NUMUNITS) { #ifdef DEBUG printf("FormatDisk: invalid drive specification!\n"); #endif fail = ERROR_INVALID_COMPONENT_NAME; goto cleanup; } if (!(diskbuffer = AllocMem((long) TRACKSIZE, MEMF_PUBLIC | MEMF_CHIP))) { fail = 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 fail = 1; /* is there a better error code? */ goto cleanup; } if (!(diskreq = (struct IOExtTD *) CreateExtIO(diskport, (long) sizeof(struct IOExtTD)))) { fail = 1; goto cleanup; } if (fail = OpenDevice(TD_NAME, (long) unit, diskreq, 0L)) { #ifdef DEBUG printf("FormatDisk: OpenDevice error: %d\n",error); #endif goto cleanup; } if (fail = 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 (fail = 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 (fail = 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 (fail = 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 */ cleanup: CloseDevice(diskreq); if (diskbuffer) FreeMem(diskbuffer, (long) TRACKSIZE); if (diskreq) DeleteExtIO(diskreq, (long) sizeof(*diskreq)); if (diskport) DeletePort(diskport); return fail; } /* 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 SHAR_EOF cat << \SHAR_EOF > misc/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); } SHAR_EOF