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