Path: utzoo!mnetor!uunet!husc6!purdue!i.cc.purdue.edu!j.cc.purdue.edu!ain From: ain@j.cc.purdue.edu (Patrick White) Newsgroups: comp.sources.amiga Subject: MRBackup (part 4 of 4) Message-ID: <6293@j.cc.purdue.edu> Date: 28 Jan 88 16:28:08 GMT Organization: PUCC Land, USA Lines: 2399 Keywords: MRBackup, untested, source, part 4 of 4. Approved: ain@j.cc.purdue.edu (Pat White) Program Name: MRBackup Submitted By: uiucdcs!amanpt1.ZONE1.COM!mrr@ee.ecn.purdue.edu (Mark Rinfret) Summary: A hard disk backup utility. Poster Boy: Pat White (ain@j.cc.purdue.edu) Untested. NOTES: I reshar'ed all of the source to get rid of some explicit path references in where the files get put. Now it will unshar on unix and the Amiga into the current directory. I did *not* change the explicit path references to include files in the .c files. I also included the docs that were sent with the binary version, so these 4 parts are complete source with docs. -- Pat White (co-moderator comp.sources/binaries.amiga) UUCP: j.cc.purdue.edu!ain BITNET: PATWHITE@PURCCVM PHONE: (317) 743-8421 U.S. Mail: 320 Brown St. apt. 406, West Lafayette, IN 47906 ======================================== # 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 # shar: Shell Archiver # Run the following text with /bin/sh to create: # IntuiHandler.c # List.c # MRDates.c # MiscRequest.c # Restore.c # Speech.c # Timer.c # UserPrefs.c # sendpkt.c # unixwild.c # This archive created: Thu Jan 28 11:10:19 1988 # By: Patrick White (PUCC Land, USA) echo shar: extracting IntuiHandler.c '(9716 characters)' cat << \SHAR_EOF > IntuiHandler.c /* Intuition handler for MRBackup * Filename: IntuiHandler.c * Date: 11/21/87 * * History: (most recent change first) * * 11/21/87 -MRR- This file was created for version 2.0. */ #include "MRBackup.h" #include "Screen.c" extern struct GfxBase *GfxBase; extern struct Gadget curVolumeGadget; extern struct Gadget errorGadget; struct Window *OpenPathWindow(); /* Close all Intuition items. */ CloseIntuition() { if ( IntuitionBase ) { if ( mainScreen ) { if ( mainWindow ) { ClearMenuStrip( mainWindow ); CloseWindow( mainWindow ); } if ( pathWindow ) CloseWindow( pathWindow ); CloseScreen( mainScreen ); } if ( progressConsole ) DeleteConsole( progressConsole ); if ( progressWindow ) CloseWindow( progressWindow ); #ifdef DEBUG if ( debugConsole ) DeleteConsole( debugConsole ); if ( debugWindow ) CloseWindow( debugWindow ); #endif if ( GfxBase ) CloseLibrary( GfxBase ); CloseLibrary( IntuitionBase ); } /* end if IntuitionBase */ } ^L /* Handle a gadget action. * Called with: * window: window that gadget is displayed in * class: message class (GADGETUP/GADGETDOWN/?) * addr: pointer to gadget structure */ DoGadget(window, class, addr) struct Window *window; ULONG class; struct Gadget *addr; { USHORT id; /* gadget identifier */ struct Gadget *upGad; ULONG upClass; struct IntuiMessage *upMsg; /* require gadget up to complete */ id = addr->GadgetID; if (class == GADGETUP) { #ifdef DEBUG sprintf(debugMsg,"GADGETUP: %d\n",id); DebugWrite(debugMsg); #endif switch (id) { case HOMEPATH: GetHomePath(addr); break; case BACKPATH: GetBackPath(addr); break; case LISTPATH: GetListPath(addr); break; case XCLDPATH: GetXcldPath(addr); break; case STOP: TypeAndSpeak( "Use the STOP gadget during backup and restore operations.\n"); break; default: #ifdef DEBUG sprintf(conmsg, "Unknown gadget, ID %d. Program error!\n", id); TypeAndSpeak(conmsg); #endif break; } } } int InitIntuition() { struct ViewPort vP; struct RastPort *rpG; IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library", 0L); if ( ! IntuitionBase ) { puts("I can't open Intuition!\n"); return ERR_ABORT; } GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 0L); if ( ! GfxBase ) { puts("I can't open the graphics library!\n"); return ERR_ABORT; } mainScreen = OpenScreen(&NewScreenStructure); if ( ! mainScreen ) { puts("I can't open the screen!\n"); return ERR_ABORT; } vP = mainScreen->ViewPort; LoadRGB4(&vP, &Palette, (long) PaletteColorCount); NewWindowStructure1.Screen = mainScreen; mainWindow = OpenWindow(&NewWindowStructure1); /* open the window */ if ( mainWindow == NULL ) { puts("I can't open the main window!\n"); return ERR_ABORT; } if (!OpenPathWindow()) return ERR_ABORT; rpG = mainWindow->RPort; /* get a rastport pointer for the window */ SetMenuStrip(mainWindow, &MenuList1); /* Open the console(s) and related windows. */ NewWindowStructure4.Screen = mainScreen; if ( ! (progressWindow = OpenWindow( &NewWindowStructure4 ) ) ) { puts("I can't open the progress window!\n"); return ERR_ABORT; } if ( ! (progressConsole = CreateConsole( progressWindow ) ) ) { puts("I can't create the progress window console!\n"); return ERR_ABORT; } #ifdef DEBUG NewWindowStructure5.Screen = mainScreen; if ( ! (debugWindow = OpenWindow( &NewWindowStructure5 ) ) ) { puts("I can't open the debug window!\n"); return ERR_ABORT; } if ( ! (debugConsole = CreateConsole( debugWindow ) ) ) { puts("I can't create the debug window console!\n"); return ERR_ABORT; } #endif #ifdef IntuiTextList1 PrintIText(rpG,&IntuiTextList1,0L,0L); /* Print the text if any. */ #endif #ifdef BorderList1 DrawBorder(rpG,&BorderList1,0L,0L); /* Draw the borders if any */ #endif #ifdef ImageList1 DrawImage(rpG,&ImageList1,0L,0L); /* Draw the images if any. */ #endif return ERR_NONE; } /* Open the pathname specification window. * Returns: * pointer to new window (success) or NULL (failure) * Side-Effects: * sets pathWindow to new window pointer */ struct Window * OpenPathWindow() { if (!pathWindow) { /* only if not already open */ NewWindowStructure3.Screen = mainScreen; if (! ( pathWindow = OpenWindow(&NewWindowStructure3)) ) { TypeAndSpeak( "I can't open the pathname specifications window!\n"); } } return pathWindow; } /* Set the current backup volume name into the curVolumeGadget. */ SetCurVolumeGadget(name) char *name; { long position; char *s; position = RemoveGadget(mainWindow, &curVolumeGadget); s = GadgetString((&curVolumeGadget)); strncpy(s, name, 30); AddGadget(mainWindow, &curVolumeGadget, position); RefreshGList(&curVolumeGadget, mainWindow, NULL, 1L); } ^L /* Set the current errorCount value into the errorGadget. */ SetErrorGadget() { ULONG position; UBYTE *buffer; position = RemoveGadget(mainWindow, &errorGadget); buffer = GadgetString((&errorGadget)); sprintf(buffer, "%4u", errorCount); AddGadget(mainWindow, &errorGadget, position); RefreshGList(&errorGadget, mainWindow, NULL, 1L); } /* Adjust the disk "gauge" to show how full it currently is. * Called with: * current: number of blocks currently in use * maxValue: total number of blocks available */ SetGauge(current, maxValue) LONG current, maxValue; { ULONG hPot; struct PropInfo *oldProp; LONG range, used; #ifdef DEBUG sprintf(debugMsg,"SetGauge(%ld,%ld)\n",current,maxValue); DebugWrite(debugMsg); #endif oldProp = (struct PropInfo *) gaugeGadget.SpecialInfo; range = maxValue + 1; used = maxValue - current; hPot = (used << 16L) / range; ModifyProp( &gaugeGadget, /* gadget pointer */ mainWindow, /* window pointer */ NULL, /* requester */ (ULONG) oldProp->Flags, /* flags */ hPot, /* horizPot */ 0L, /* vertPot */ (ULONG) oldProp->HorizBody, /* horizBody */ (ULONG) oldProp->VertBody /* vertBody */ ); } /* Handle IDCMP messages generated by user actions. */ User() { ULONG class; /* message class */ USHORT code; /* message code */ USHORT gadgetID; /* gadget ID */ APTR Iadr; /* address field from message */ struct IntuiMessage *msg; /* Intuition message pointer */ struct Window *msgWindow; /* window message occurred in */ USHORT quit = 0; SHORT x,y; /* mouse x and y position */ ULONG waitBits; #ifdef DEBUG sprintf(debugMsg,"User: waitBits = %08lx\n", waitBits); DebugWrite(debugMsg); #endif while (!quit) { ActivateWindow(mainWindow); waitBits = (1L << mainWindow->UserPort->mp_SigBit); if (pathWindow) waitBits = waitBits | (1L << pathWindow->UserPort->mp_SigBit); Wait(waitBits); while (!quit) { if (!(msg = (struct IntuiMessage *) GetMsg(mainWindow->UserPort))) if ( ! (pathWindow && (msg = (struct IntuiMessage *) GetMsg(pathWindow->UserPort) ) ) ) break; class = msg->Class; code = msg->Code; Iadr = msg->IAddress; x = msg->MouseX; y = msg->MouseY; msgWindow = msg->IDCMPWindow; ReplyMsg(msg); /* acknowledge the message */ #ifdef DEBUG sprintf(debugMsg,"Message class: 0x%lx, code: 0x%x\n", class, code); #endif switch (class) { case CLOSEWINDOW: if (msgWindow == mainWindow) ++quit; else if (msgWindow == pathWindow) { CloseWindow(pathWindow); pathWindow = NULL; } break; case GADGETUP: case GADGETDOWN: DoGadget(msgWindow, class, Iadr); break; case MENUPICK: quit = UserMenu(code); break; default: break; /* ignore the rest */ } /* end switch(class) */ } } } /* Handle a menu selection. * Called with: * xcode: menu selection code * Returns: * status code (1 => Quit was selected) */ int UserMenu(xcode) USHORT xcode; { USHORT code = xcode; struct MenuItem *item; USHORT itemNum,menuNum; while (code != MENUNULL) { menuNum = MENUNUM(code); itemNum = ITEMNUM(code); item = ItemAddress(&MenuList1, (long) code); #ifdef DEBUG sprintf(debugMsg, "menu = %d, item = %d, flags = %04x\n", menuNum, itemNum, item->Flags); DebugWrite(debugMsg); #endif switch (menuNum) { case MENU_PROJECT: /* Project Menu */ switch (itemNum) { case ITEM_BACKUP: /* Backup */ Backup(); break; case ITEM_RESTORE: /* Restore */ Restore(); break; case ITEM_LOADPREFS: /* Load Preferences */ GetUserPrefs(); break; case ITEM_SAVEPREFS: /* Save Preferences */ PutUserPrefs(); break; case ITEM_ABOUT: /* About */ About(); break; case ITEM_QUIT: /* Quit */ return 1; default: DisplayBeep(NULL); break; } break; case MENU_FLAGS: /* Flags Menu */ switch ( itemNum ) { case ITEM_COMPRESS: /* Compression */ doCompress = IsChecked( item ); break; case ITEM_BIGFILES: /* Do Big Files */ doBigFiles = IsChecked( item ); break; case ITEM_LIST: /* Listing */ doListing = IsChecked( item ); break; case ITEM_SPEECH: /* Speech */ doSpeech = IsChecked( item ); SetSpeech(); break; case ITEM_FORMAT: /* Format output disks */ doFormat = IsChecked( item ); break; default: DisplayBeep(NULL); break; } break; case MENU_WINDOWS: /* Windows Menu */ OpenPathWindow(); /* There's only one item. */ break; } #define EXTENDED_SELECT_WORKS #ifdef EXTENDED_SELECT_WORKS code = item->NextSelect; /* This next line is a kludge. Testing has revealed that * the NextSelect field is returning 0000x. Why? */ if (!code) break; #else break; #endif } return 0; } SHAR_EOF if test 9716 -ne "`wc -c IntuiHandler.c`" then echo shar: error transmitting IntuiHandler.c '(should have been 9716 characters)' fi echo shar: extracting List.c '(3040 characters)' cat << \SHAR_EOF > List.c /* MRBackup: Listing support routines * Filename: List.c * Author: Mark R. Rinfret * Date: 11/27/87 * * History: (most recent changes first) * * 11/27/87 -MRR- This module was created for version 2.0. * */ #define MAIN #include "MRBackup.h" static char listDate[20] = "??/??/?? ??:??:??"; ^L /* Output a new header to the listing file. */ Header() { if (doListing) { if (doFormat) { /* A new disk? */ fprintf(listing, "\f MRBackup Listing of Volume %s created on %s\n\n", destVol, listDate); } else { fprintf(listing, "\f MRBackup Partial Listing of Volume %s updated on %s\n\n", destVol, listDate); } lineCount = 2; } } ^L /* List information about the file or directory we just created. * Called with: * name: destination filename string */ void ListFileInfo(name) char *name; { struct Lock *lock; char dateStr[20], infoLine[255]; if (!doListing) return; if (! (lock = (struct Lock *) Lock(name, SHARED_LOCK))) { sprintf(infoLine, "ListFileInfo: could not lock %s", name); ListLine(infoLine); return; } if (Examine(lock, fibWork)) { if (fibWork->fib_DirEntryType >=0) { NewLine(2); sprintf(infoLine,"Directory: %s", name); NewLine(1); } else { DS2Str(dateStr, "%02m/%02d/%02y %02h:%02n:%02s", &fibWork->fib_Date); /* It is my understanding that the maximum filename length for * a particular node is 30 characters. The following code will * probably never execute but it makes me feel warm and safe. */ if (strlen(fibWork->fib_FileName) > 40) { fibWork->fib_FileName[40] = '*'; fibWork->fib_FileName[41] = '\0'; } sprintf(infoLine," %s %8ld %5ld %s", dateStr, fibWork->fib_Size, fibWork->fib_NumBlocks, fibWork->fib_FileName); } } else { sprintf(infoLine,"ListFileInfo: can't examine %s", name); } UnLock(lock); ListLine(infoLine); } ^L /* Output a line to the listing file. Start a new line if necessary. * The output string is assumed to have no form control characters. * Called with: * str: string to be output */ ListLine(str) char *str; { if (doListing) { if (lineCount >= LINES_PER_PAGE) Header(); fprintf(listing," %s\n",str); fflush(listing); ++lineCount; } } ^L /* Skip 'n' lines in the listing file. * Called with: * n: number of lines to skip */ NewLine(n) int n; { if (doListing) { if (n + lineCount >= LINES_PER_PAGE) Header(); else while (n--) { fputc('\n', listing); ++lineCount; } } } ^L /* Open the listing file. * Called with: * name: file or device pathname * Returns: * status (0 => success) */ int OpenList(name) char *name; { int status = 0; if (listing) fclose(listing); /* prior listing file open? */ if (!(listing = fopen(name, "w"))) { status = errno; sprintf(conmsg, "I can't open the listing file \"%s\", error %d.\n", name, status); TypeAndSpeak(conmsg); } else { DS2Str(listDate, "%02m/%02d/%02y %02h:%02n:%02s",now); lineCount = LINES_PER_PAGE; } return status; } SHAR_EOF if test 3040 -ne "`wc -c List.c`" then echo shar: error transmitting List.c '(should have been 3040 characters)' fi echo shar: extracting MRDates.c '(11553 characters)' cat << \SHAR_EOF > MRDates.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 him. * * History: (most recent change first) * * 12/30/87 -MRR- I experienced some problems with dates past 12/28/87 and * started investigating. After spending entirely too much * time on the problem, I stole the code from ShowDate in * Rob Peck's book and stuck it in UnpackDS. I've left my * buggy code intact, but surrounded by conditional compile * brackets which aren't turned on. The current algorithm * only supports dates back to 03/01/84 while the system * date format begins with 01/01/78. The current algorithm * is also quite unreadable - too many unexplained constants. * * 08/20/87 -MRR- Gack! I wrote this? In the interests of orthogonality, * I have replaced SetDateStamp with PackDS, the inverse * of UnpackDS. I have also renamed the package MRDates * to provide a unique name, hopefully relieving conflicts * with other packages providing date/time functions. The * UnpackedDS type is now defined in MRDates.h and can * be included by modules which require PackDS and UnpackDS. */ /* The following #define MUST be set to inhibit certain declarations in * the include file MRDates.h: */ #define MRDATES #include #include #include #include #include ":src/lib/MRDates.h" /* #define DEBUG */ char *daynames[] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }; USHORT monthDays[12] = { 0, /* JAN */ 31, /* FEB */ 59, /* MAR */ 90, /* APR */ 120, /* MAY */ 151, /* JUN */ 181, /* JUL */ 212, /* AUG */ 243, /* SEP */ 273, /* OCT */ 304, /* NOV */ 334 /* DEC */ }; 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; { UnpackedDS 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; UnpackedDS upd; /* unpacked DateStamp */ char *s; int values[3]; int value; 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? */ upd.hour = values[0]; upd.minute = values[1]; upd.second = values[2]; } else { /* getting date? */ /* It's OK to have a null date string, but it's not OK to specify only * 1 or 2 of the date components. */ if (count && count != 3) goto bad_value; upd.month = values[0]; upd.day = values[1]; upd.year = values[2]; } } /* end for */ PackDS(d,&upd); return 0; } /* Set a DateStamp structure, given the date/time components. * Called with: * d: pointer to DateStamp * upd: pointer to UnpackedDS */ PackDS(d,upd) struct DateStamp *d; UnpackedDS *upd; { USHORT leapyear; short year,month,day,hour,minute,second; year = upd->year; /* copy date components to locals */ month = upd->month; day = upd->day; hour = upd->hour; minute = upd->minute; second = upd->second; if (year > 1900) year = year - 1900; leapyear = (year % 4 ? 0 : 1); year = year - 78; if (month < 1 || month > 12) /* somebody goofed? */ month = 1; day = day - 1 + monthDays[month-1]; if (leapyear && (month > 2)) ++day; d->ds_Days = year * 365 + (year + 1) / 4 + day; d->ds_Minute = hour * 60 + minute; d->ds_Tick = second * TICKS_PER_SECOND; } /* Unpack a DateStamp structure into an UnpackedDS structure. * Called with: * ds: pointer to DateStamp structure * du: pointer to UnpackedDS structure */ UnpackDS(ds, du) struct DateStamp *ds; UnpackedDS *du; { #ifdef OLDCODE USHORT i, leap, leapYears, temp, testValue, year; /* Compute the year as an offset from 1978. This is an integer * approach to "year = days / 365.25" (since there are 365.25 days * in a year). */ year = ( ((ds->ds_Days + 1) * 100) / 36525); leapYears = (year + 1) / 4; du->year = year + 1978; #ifdef DEBUG printf("\nDays == %ld, Years == %d, Leapyears == %d\n", ds->ds_Days, year, leapYears); #endif /* Is current year a leapyear? */ leap = ( (year % 4) == 0); /* Get the days into the year. */ temp = (ds->ds_Days - (year * 365) - leapYears); /* Find the month. */ du->month = 0; du->day = 0; for (i = 11; i >= 0; --i) { testValue = monthDays[i]; if (i >= 2) testValue += leap; if (temp >= testValue) { du->month = i + 1; du->day = temp - testValue + 1; break; } } #else long n; int m,d,y; n = ds->ds_Days - 2251; y = (4 * n + 3) / 1461; n -= 1461 * (long) y / 4; y += 1984; m = (5 * n + 2) / 153; d = n - (153 * m + 2) / 5 + 1; m += 3; if (m > 12) { ++y; m -= 12; } du->year = y; du->month = m; du->day = d; #endif 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; UnpackedDS 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 if test 11553 -ne "`wc -c MRDates.c`" then echo shar: error transmitting MRDates.c '(should have been 11553 characters)' fi echo shar: extracting MiscRequest.c '(1733 characters)' cat << \SHAR_EOF > MiscRequest.c /* Miscellaneous requester support routines. */ #include #include #include #include #include #include #include struct IntuiText diskreq_body_text = { AUTOFRONTPEN, /* FrontPen */ AUTOBACKPEN, /* BackPen */ AUTODRAWMODE, /* DrawMode */ AUTOLEFTEDGE, /* LeftEdge */ AUTOTOPEDGE, /* TopEdge */ NULL, /* ITextFont Pointer */ (UBYTE *)"", /* IText */ NULL /* NextText */ }; struct IntuiText diskreq_pos_text = { AUTOFRONTPEN, /* FrontPen */ AUTOBACKPEN, /* BackPen */ AUTODRAWMODE, /* DrawMode */ AUTOLEFTEDGE, /* LeftEdge */ AUTOTOPEDGE, /* TopEdge */ NULL, /* ITextFont Pointer */ (UBYTE *)"OK", /* IText */ NULL /* NextText */ }; struct IntuiText diskreq_neg_text = { AUTOFRONTPEN, /* FrontPen */ AUTOBACKPEN, /* BackPen */ AUTODRAWMODE, /* DrawMode */ AUTOLEFTEDGE, /* LeftEdge */ AUTOTOPEDGE, /* TopEdge */ NULL, /* ITextFont Pointer */ (UBYTE *)"Cancel", /* IText */ NULL /* NextText */ }; /* Generate an autorequest for the insertion of a floppy disk. * Called with: * window: pointer to window for request * drivespec: the disk drive name */ int RequestDisk(window, drivespec, msg) struct Window *window; char *drivespec, *msg; { UBYTE prompt[71]; ULONG width; strncpy(prompt, msg, sizeof(prompt)-strlen(drivespec)-2); strncat(prompt,drivespec,(sizeof(prompt)-strlen(prompt)-2)); width = 8 * strlen(prompt) + 48; diskreq_body_text.IText = prompt; return AutoRequest( window, &diskreq_body_text, &diskreq_pos_text, &diskreq_neg_text, NULL, NULL, width, 50L); } SHAR_EOF if test 1733 -ne "`wc -c MiscRequest.c`" then echo shar: error transmitting MiscRequest.c '(should have been 1733 characters)' fi echo shar: extracting Restore.c '(9995 characters)' cat << \SHAR_EOF > Restore.c /* Filename: restore.c * Author: Mark R. Rinfret * Date: 08/02/87 * Description: Restore processing module for MRBackup * * History: (most recent change first) * * 12/18/87 -MRR- Restore was using function IsCompressed() to determine * candidates for decompression. Unfortunately, it also * tried to decompress .ARC and .ZOO files. * * Restore now requests the next disk to be restored from. * * 11/22/87 -MRR- Modifications for version 2.0. * * 09/19/87 -MRR- Added NewHomeDir() which creates subdirectories as * necessary when the initial backup path specifies a * subdirectory. */ #include "MRBackup.h" #include ":src/lib/DiskMisc.h" char fullBackPath[PATH_MAX+1], fullHomePath[PATH_MAX+1]; static BOOL bigFileSeqNbr; /* >0 => big file sequence number */ BOOL homeIsDevice; /* true => home is "DH:" */ ^L /* Create a new directory on the home device. * Called with: * name: directory pathname * Returns: * false => success * true => failure */ int NewHomeDir(name) char *name; { char c; struct Lock *dirLock; int dirLeng; int errnum; char dirname[256]; int nameindx = 0, nameleng; *dirname = '\0'; dirLeng = 0; nameleng = strlen(name); /* Parse the pathname, one directory node at a time, creating * directories as needed. */ while (nameindx < nameleng) { if (nameindx) /* 2nd - nth pass? */ dirname[dirLeng++] = '/'; /* directory separator */ while ((c = name[nameindx++]) && c != '/') dirname[dirLeng++] = c; dirname[dirLeng] = '\0'; /* terminate with null */ if (dirLock = (struct Lock *) Lock(dirname,SHARED_LOCK)) /* subdir exists? */ UnLock(dirLock); else { /* create subdirectory */ if ((dirLock = (struct Lock *) CreateDir(dirname))== NULL){ if ((errnum = IoErr())== ERROR_DIRECTORY_NOT_EMPTY){ sprintf(conmsg, "Directory %s already exists!\n",dirname); TypeAndSpeak(conmsg); } else { sprintf(conmsg, "ERROR %d: Unable to create directory %s\n", errnum,dirname); TypeAndSpeak(conmsg); return errnum; } } else UnLock(dirLock); } } /* endwhile */ return 0; } /* Restore files from floppy disk. */ int Restore() { int disks=0, status = 0; char volumeName[31]; Speak("And away we go!"); BreakPath(backPath, srcVol, srcPath); strcat(srcVol, ":"); homeIsDevice = (homePath[strlen(homePath)-1] == ':'); BreakPath(homePath, destVol, destPath); strcat(destVol, ":"); while ( !status ) { TypeAndSpeak("I am ready to read the next disk.\n"); if (!RequestDisk(mainWindow, srcVol, "Insert the next disk to be restored in ")) break; if (!IsDir(backPath)) { TypeAndSpeak( "Backup path must be a device or directory name!\n"); return ERR_ABORT; } GetVolumeName(srcVol, volumeName); SetCurVolumeGadget(volumeName); if ( (totalSize = TotalDiskBlocks(destVol)) < 0) status = -totalSize; else if ((bigFileSeqNbr = GetBigFileInfo(srcVol)) < 0) status = -bigFileSeqNbr; else { status = RestoreFile(srcPath); } if (bigFileSeqNbr) { /* we have a big file to restore? */ status = RestoreBigFile(); } /*!!! Need GetErrOpt right here... */ ++disks; } if (status == 0) { if (disks) TypeAndSpeak("Your restoration project is completed.\n"); else TypeAndSpeak("Maybe you will let me do it next time.\n"); } else { sprintf(conmsg,"Restore terminated with status %d.\n",status); TypeAndSpeak(conmsg); TypeAndSpeak( "Perhaps you should check things out and try it again.\n"); } SetCurVolumeGadget(""); return status; } ^L /* Restore all the files in a directory. * Called with: * lock: lock on the directory * fib: pointer to file info block * path: directory pathname (without volume) * Returns: * status (0 => success) */ int RestoreDir(lock, fib, path) struct Lock *lock; struct FileInfoBlock *fib; char *path; { struct Lock *dirLock = NULL, *filelock = NULL; char newpath[256]; int status = 0; strcpy(temp, homePath); if (*path) { if (!homeIsDevice) strcat(temp, "/"); strcat(temp, path); } #ifdef DEBUG sprintf(debugMsg,"Checking for directory %s\n",temp); DebugWrite(debugMsg); #endif if (!(dirLock = (struct Lock *) Lock(temp, SHARED_LOCK))) { if ((status = IoErr()) == ERROR_OBJECT_NOT_FOUND) { #ifdef DEBUG sprintf(debugMsg,"Creating directory %s\n",temp); DebugWrite(debugMsg); #endif if (status = NewHomeDir(temp)) return status; } else { sprintf(conmsg,"RestoreDir cannot lock %s: %d\n",temp, status); TypeAndSpeak(conmsg); return status; } } if (dirLock) UnLock(dirLock); while (ExNext(lock,fib)) { strcpy(newpath, path); if (*newpath) strcat(newpath, "/"); strcat(newpath, fib->fib_FileName); if (status = RestoreFile(newpath)) { /* filter out "permissable:" errors */ if (status == ERROR_OBJECT_IN_USE || status == ERROR_WRITE_PROTECTED) status = 0; else break; } } done: return status; } ^L /* Restore one or more files according to the calling pathname. * The path argument does not contain the backup volume name. */ int RestoreFile(path) char *path; { struct FileInfoBlock *fib = NULL, *fib2 = NULL; UBYTE exists = FALSE, ignore = FALSE; unsigned isCompressed; struct Lock *lock = NULL; USHORT nameLength; char *s; UBYTE savechar; int status = 0; if (status = CheckStop()) return status; /* Don't restore the big file here...it's done last. */ if (ThisIsBigFile(path)) return status; if (!(fib = (struct FileInfoBlock *) AllocMem((long) sizeof (struct FileInfoBlock), MEMF_PUBLIC | MEMF_CHIP))) { TypeAndSpeak("RestoreFile could not allocate FIB!\n"); return ERROR_NO_FREE_STORE; } sprintf(fullBackPath, "%s%s",srcVol,path); strcpy(fullHomePath, homePath); if (*path) { if (!homeIsDevice) strcat(fullHomePath, "/"); strcat(fullHomePath, path); } #ifdef DEBUG sprintf(conmsg,"fullBackPath = %s\n",fullBackPath); DebugWrite(conmsg); sprintf(conmsg,"fullHomePath = %s\n",fullHomePath); DebugWrite(conmsg); #endif if ((sizeLeft = DiskBlocksLeft(destVol)) < 0) { status = -sizeLeft; sprintf(conmsg, "Can't determine disk blocks left on %s; error %d.\n", destVol, status); TypeAndSpeak(conmsg); goto done; } SetGauge(sizeLeft, totalSize); do { status = 0; if (!(lock = (struct Lock *) Lock(fullBackPath, SHARED_LOCK))) { status = IoErr(); sprintf(conmsg, "RestoreFile can't lock %s; error %d\n", fullBackPath, status); TypeAndSpeak(conmsg); goto checkStatus; } if (!Examine(lock, fib)) { status = IoErr(); sprintf(conmsg, "RestoreFile can't examine %s; error %d\n", fullBackPath, status); TypeAndSpeak(conmsg); goto checkStatus; } if (fib->fib_DirEntryType > 0) { /* path is a directory */ status = RestoreDir(lock, fib, path); UnLock(lock); lock = NULL; } else { UnLock(lock); lock = NULL; /* Note: though we can use the function IsCompressed to test * for potentially compressed files in Backup(), ONLY files * compressed with LZW (ending in .z) are candidates for * decompression. The following test looks for these files * only. */ isCompressed = false; if (doCompress && (s = rindex(fullHomePath,'.'))) { /* look for ".z" ONLY! */ if (!strcmpc(s, ".z")) { isCompressed = true; /* truncate the destination pathname (remove ".z") */ nameLength = strlen(fullHomePath); fullHomePath[nameLength-2] = '\0'; } } /*#define NOCOPY*/ #ifndef NOCOPY /* If this file exists, then check its modification date. If * it's newer than the backup, don't replace it. */ if ((lock = (struct Lock *) Lock(fullHomePath, SHARED_LOCK))) { if (!(fib2 = (struct FileInfoBlock *) AllocMem((long) sizeof (struct FileInfoBlock), MEMF_PUBLIC | MEMF_CHIP))) { TypeAndSpeak("RestoreFile could not allocate FIB!\n"); status = ERROR_NO_FREE_STORE; goto done; } Examine(lock, fib2); UnLock(lock); lock = NULL; if (CompareDS(&fib2->fib_Date, &fib->fib_Date) >= 0) ignore = TRUE; } if (ignore) { sprintf(conmsg, "Skipping %s, since home file is current.\n", path); WriteConsole(conmsg); } else { if (! (doCompress && isCompressed) ) { copyfile: sprintf(conmsg,"Copying %s\n", fullBackPath); WriteConsole(conmsg); status = CopyFile(fullBackPath, fullHomePath); } else { sprintf(conmsg, "Decompressing %s\n", fullBackPath); WriteConsole(conmsg); if (status = decompress(fullBackPath, fullHomePath)) { sprintf(conmsg, "Decompression of %s failed; status is %d.\n", fullBackPath, status); TypeAndSpeak(conmsg); TypeAndSpeak( "I will try to copy the file, instead.\n"); /* restore ".z" to name */ fullHomePath[nameLength-2] = '.'; goto copyfile; } CopyFileDate(fullBackPath, fullHomePath); } } #endif } checkStatus: if (status && status != ERR_ABORT) { ++errorCount; SetErrorGadget(); if (status == ERROR_DISK_FULL) { TypeAndSpeak("The destination disk is full.\n"); /* The following test is pretty kludgy. It boils down to * "If the drive is a DF device, it's removable, therefore the * user can recover from this error by inserting a new diskette." */ if (toupper(destVol[0]) == 'D' && toupper(destVol[1]) == 'F') { TypeAndSpeak( "Put a new disk in the destination drive and try again.\n"); } else { TypeAndSpeak( "You may have to delete some files to continue."); } } status = GetErrOpt(ERR_ABORT|ERR_RETRY_FILE|ERR_IGNORE); if (status == ERR_IGNORE) status = 0; } } while (status == ERR_RETRY_FILE); done: if (lock) UnLock(lock); if (fib) FreeMem(fib, (long) sizeof(struct FileInfoBlock)); if (fib2) FreeMem(fib2, (long) sizeof(struct FileInfoBlock)); return status; } SHAR_EOF if test 9995 -ne "`wc -c Restore.c`" then echo shar: error transmitting Restore.c '(should have been 9995 characters)' fi echo shar: extracting Speech.c '(3297 characters)' cat << \SHAR_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() as often as the * application requires. * 3. Call SpeechOff to close libraries/ports/devices. */ #include #include #include #include #include #include #include /*#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 SHAR_EOF if test 3297 -ne "`wc -c Speech.c`" then echo shar: error transmitting Speech.c '(should have been 3297 characters)' fi echo shar: extracting Timer.c '(4175 characters)' cat << \SHAR_EOF > Timer.c /* Timer device support routines. * Filename: Timer.c * Author: Mark R. Rinfret * Date: 11/29/87 * */ #include ":src/lib/Timer.h" #include /* Allocate and prepare a timer request structure. * Called with: * vBlank: 1 => vertical blanking timer, microhertz timer otherwise * Returns: * pointer to timer request or NULL (failed) */ struct timerequest * CreateTimer(vBlank) BOOL vBlank; { int status = 0; struct MsgPort *timerPort = NULL; struct timerequest *timeRequest = NULL; ULONG timerType; timerType = (vBlank ? UNIT_VBLANK : UNIT_MICROHZ); if ( timerPort = CreatePort(0L, 0L) ) { if ( ! (timeRequest = (struct timerequest *) AllocMem((long) sizeof(struct timerequest), MEMF_CLEAR | MEMF_PUBLIC) ) ) { killport: DeletePort(timerPort); } else { timeRequest->tr_node.io_Message.mn_Node.ln_Type = NT_MESSAGE; timeRequest->tr_node.io_Message.mn_Node.ln_Pri = 0; timeRequest->tr_node.io_Message.mn_ReplyPort = timerPort; if (OpenDevice(TIMERNAME, timerType, timeRequest, 1L) ) { DeleteTimer(timeRequest); timeRequest = NULL; goto killport; } } } return timeRequest; } /* Delete a timer request created by CreateTimer(). * Called with: * timeRequest: pointer to timer request structure */ void DeleteTimer(timeRequest) struct timerequest *timeRequest; { struct MsgPort *msgPort; msgPort = timeRequest->tr_node.io_Message.mn_ReplyPort; if (timeRequest->tr_node.io_Device) { AbortIO(timeRequest); GetMsg(msgPort); CloseDevice(timeRequest); } FreeMem(timeRequest, (long) sizeof(timeRequest)); DeletePort(msgPort); } /* Start an asynchronous timer request. The user application detects * the expiration of the timer with Wait(timeRequest->ReplyPort->mp_SigBit) * or WaitIO(timeRequest). * Called with: * timeRequest: pointer to timer I/O request block * seconds: number of seconds in time interval * microSeconds: number of uSecs in time interval * * Caution: seconds, microSeconds are ULONG parameters! */ void StartTimer(timeRequest, seconds, microSeconds) struct timerequest *timeRequest; ULONG seconds, microSeconds; { timeRequest->tr_time.tv_secs = seconds; timeRequest->tr_time.tv_micro = microSeconds; timeRequest->tr_node.io_Command = TR_ADDREQUEST; timeRequest->tr_node.io_Flags = 0; timeRequest->tr_node.io_Error = 0; SendIO(timeRequest); /* start the timer */ } /* Stop an asynchronous timer request. * Called with: * timeRequest: pointer to timer I/O request block */ void StopTimer(timeRequest) struct timerequest *timeRequest; { AbortIO(timeRequest); WaitIO(timeRequest); } #ifdef DEBUG #define SHORTBIT (1L<tr_node.io_Message.mn_ReplyPort->mp_SigBit) #define LONGBIT (1L<tr_node.io_Message.mn_ReplyPort->mp_SigBit) main() { unsigned intervals; struct timerequest *shortTimer, *longTimer; ULONG signals; /* This simple program example sets up two timers of different * intervals and reports their expirations. */ puts("This example defines two timers. The first has an interval of"); puts("five seconds, while the second has an interval of 10 seconds."); puts("The expiration of each timer is reported to the screen until"); puts("10 intervals have been detected.\n"); if (! (shortTimer = CreateTimer(0) ) ) { puts("Failed to create short interval timer!"); exit(); } if (! (longTimer = CreateTimer(0) ) ) { puts("Failed to create long interval timer!"); DeleteTimer(shortTimer); exit(); } StartTimer(shortTimer, 5L, 0L); StartTimer(longTimer, 10L, 0L); for (intervals = 0; intervals < 10; ) { printf("Begin wait %2d ... ", intervals); signals = Wait(SHORTBIT | LONGBIT); puts("end wait."); if (signals & SHORTBIT) { GetMsg(shortTimer->tr_node.io_Message.mn_ReplyPort); ++intervals; puts(" Short interval timer expired."); StartTimer(shortTimer, 5L, 0L); } if (signals & LONGBIT) { GetMsg(longTimer->tr_node.io_Message.mn_ReplyPort); ++intervals; puts(" Long interval timer expired."); StartTimer(longTimer, 10L, 0L); } } DeleteTimer(shortTimer); DeleteTimer(longTimer); puts("\nEnd of timer demo.\n"); } #endif SHAR_EOF if test 4175 -ne "`wc -c Timer.c`" then echo shar: error transmitting Timer.c '(should have been 4175 characters)' fi echo shar: extracting UserPrefs.c '(5916 characters)' cat << \SHAR_EOF > UserPrefs.c /* MRBackup user preferences processing. * Filename: UserPrefs.c * Date: 08/23/87 * * History: (most recent change first) * * 12/20/87 -MRR- Added PutUserPrefs to allow saving new preferences. * 11/23/87 -MRR- Version 2.0. * */ #include "MRBackup.h" char *fgets(); extern struct Gadget backPathGadget; extern struct Gadget xcldPathGadget; extern struct Gadget homePathGadget; extern struct Gadget listPathGadget; extern struct Menu Menu1; #define KEYMAX 20 /* max length of a keyword */ #define NKEYWORD 9 /* number of keywords supported */ #define PREFERENCES_FILE "S:MRBackup.init" #define KW_HOME 0 #define KW_BACKUP 1 #define KW_LIST 2 #define KW_EXCLUDE 3 #define KW_COMPRESSION 4 #define KW_LISTING 5 #define KW_SPEECH 6 #define KW_FORMAT 7 #define KW_BIGFILES 8 static char *keywords[NKEYWORD] = { "home", "backup", "list", "exclude", "compression", "listing", "speech", "format","bigfiles" }; /* Process the user preferences file. */ GetUserPrefs() { char c; USHORT i; char keyword[KEYMAX+1]; short keyindex; USHORT keyleng; FILE *prefs; char s[81]; char *s1, *s2, *s3; if (!(prefs = fopen(PREFERENCES_FILE,"r"))) { WriteConsole("I couldn't get your preferences.\n"); return; } while (fgets(s, 80, prefs)) { if (*s == '#') continue; WriteConsole(s); s1 = s; keyleng = 0; while ((c = *s1++) && isalpha(c)) { if (keyleng < KEYMAX) keyword[keyleng++] = tolower(c); else { badkey: WriteConsole("Keyword error in preferences file.\n"); err: goto done; } } keyword[keyleng] = '\0'; for (keyindex = -1, i = 0; i < NKEYWORD; ++i) { if (!strcmp(keyword, keywords[i])) { keyindex = i; /* found it */ break; } } if (keyindex < 0) goto badkey; while (c == ' ' || c == '\t') c = *s1++; if (c != '=') { badsyn: WriteConsole("Syntax error in preferences file.\n"); goto done; } /* Get the parameter field, minus any leading or trailing * blanks. */ while ((c = *s1) == ' ' || c == '\t') ++s1; /* skip leading blanks */ /* Delete trailing blanks. */ s2 = s3 = s1; while (c && c != '\n') { if (c != ' ' && c != '\t') s2 = s3; /* record non-blank end */ c = *s3++; } *s2 = '\0'; /* truncate the string here */ SetUserPref(keyindex, s1); } done: fclose(prefs); } /* Output a boolean preference setting. * Called with: * f: preferences file descriptor * value: boolean value */ PutBoolPref(f, value) FILE *f; unsigned value; { char *s; s = (value ? "YES" : "NO"); fputs(s, f); } /* Save the current program settings in the user preferences file. */ PutUserPrefs() { char backupName[81]; /* backup path name */ unsigned keyIndex; FILE *prefs; strcpy(backupName, PREFERENCES_FILE); strcat(backupName, ".bak"); if ( CopyFile(PREFERENCES_FILE, backupName) ) TypeAndSpeak( "I couldn't back up the current preferences but I'll go on.\n"); if (!(prefs = fopen(PREFERENCES_FILE, "w") ) ) { sprintf(conmsg, "I couldn't open the preferences file, %s, for output;\n error %d\n", PREFERENCES_FILE, errno); return; } for (keyIndex = 0; keyIndex < NKEYWORD; ++keyIndex) { fprintf(prefs,"%s = \t\t", keywords[keyIndex]); switch (keyIndex) { case KW_HOME: fputs(homePath,prefs); break; case KW_BACKUP: fputs(backPath,prefs); break; case KW_LIST: fputs(listPath,prefs); break; case KW_EXCLUDE: fputs(excludePath,prefs); break; case KW_COMPRESSION: PutBoolPref(prefs, doFormat); break; case KW_LISTING: PutBoolPref(prefs, doListing); break; case KW_SPEECH: PutBoolPref(prefs, doSpeech); break; case KW_FORMAT: PutBoolPref(prefs, doFormat); break; case KW_BIGFILES: PutBoolPref(prefs, doBigFiles); break; default: sprintf(conmsg, "Program error in PutUserPrefs for keyword \"%s\". Please report this.\n", keywords[keyIndex]); TypeAndSpeak(conmsg); } fputs("\n", prefs); } fclose(prefs); } /* Set/Clear checkmarks according to the item being set. * Called with: * thisItem: menu item number * value: character string containing some form of YES or NO */ BOOL SetMenuItem(itemNumber, value) USHORT itemNumber; char *value; { BOOL boolean; LONG menu; struct MenuItem *item; short i; /* Get pointers and menu numbers for the affected items. */ menu = SHIFTITEM((long) itemNumber) | SHIFTMENU((long) MENU_FLAGS); item = ItemAddress(&Menu1, menu); if (item == NULL) { WriteConsole("Null menu item in SetMenuItem - call Mark!!\n"); return false; } boolean = ( tolower(*value) == 'y' ); if (boolean) { /* true? */ item->Flags |= CHECKED; } else { /* false */ item->Flags &= ~CHECKED; } return boolean; } void SetStringGadget(gadget, value) struct Gadget *gadget; char *value; { UBYTE *gs; /* pointer to gadget string */ RemoveGadget(pathWindow, gadget); gs = (UBYTE *) GadgetString(gadget); strcpy(gs, value); ResetStringInfo(gadget->SpecialInfo); AddGadget(pathWindow, gadget, -1L); DoGadget(pathWindow, GADGETUP, gadget); /* simulate GADGETUP */ } /* Set one user preference item. * Called with: * kw: keyword index * parm: parameter string */ SetUserPref(kw, parm) USHORT kw; char *parm; { switch (kw) { case KW_HOME: SetStringGadget(&homePathGadget, parm); break; case KW_BACKUP: SetStringGadget(&backPathGadget, parm); break; case KW_LIST: SetStringGadget(&listPathGadget, parm); break; case KW_LISTING: doListing = SetMenuItem(ITEM_LIST, parm); break; case KW_EXCLUDE: SetStringGadget(&xcldPathGadget, parm); break; case KW_COMPRESSION: doCompress = SetMenuItem(ITEM_COMPRESS, parm); break; case KW_SPEECH: doSpeech = SetMenuItem(ITEM_SPEECH, parm); break; case KW_FORMAT: doFormat = SetMenuItem(ITEM_FORMAT, parm); break; case KW_BIGFILES: doBigFiles = SetMenuItem(ITEM_BIGFILES, parm); break; default: break; } } SHAR_EOF if test 5916 -ne "`wc -c UserPrefs.c`" then echo shar: error transmitting UserPrefs.c '(should have been 5916 characters)' fi echo shar: extracting sendpkt.c '(1756 characters)' cat << \SHAR_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 #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 if test 1756 -ne "`wc -c sendpkt.c`" then echo shar: error transmitting sendpkt.c '(should have been 1756 characters)' fi echo shar: extracting unixwild.c '(2064 characters)' cat << \SHAR_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 SHAR_EOF if test 2064 -ne "`wc -c unixwild.c`" then echo shar: error transmitting unixwild.c '(should have been 2064 characters)' fi # End of shell archive exit 0