summaryrefslogtreecommitdiff
path: root/amiga/filedate.c
diff options
context:
space:
mode:
Diffstat (limited to 'amiga/filedate.c')
-rw-r--r--amiga/filedate.c636
1 files changed, 636 insertions, 0 deletions
diff --git a/amiga/filedate.c b/amiga/filedate.c
new file mode 100644
index 0000000..84c7bed
--- /dev/null
+++ b/amiga/filedate.c
@@ -0,0 +1,636 @@
+/*
+ Copyright (c) 1990-2005 Info-ZIP. All rights reserved.
+
+ See the accompanying file LICENSE, version 2004-May-22 or later
+ (the contents of which are also included in zip.h) for terms of use.
+ If, for some reason, both of these files are missing, the Info-ZIP license
+ also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/* Low-level Amiga routines shared between Zip and UnZip.
+ *
+ * Contains: FileDate()
+ * locale_TZ()
+ * getenv() [Aztec C only; replaces bad C library versions]
+ * setenv() [ditto]
+ * tzset() [ditto]
+ * gmtime() [ditto]
+ * localtime() [ditto]
+ * time() [ditto]
+ * sendpkt()
+ * Agetch()
+ *
+ * The first nine are used by all Info-ZIP programs except fUnZip.
+ * The last two are used by all except the non-CRYPT version of fUnZip.
+ * Probably some of the stuff in here is unused by ZipNote and ZipSplit too...
+ * sendpkt() is used by Agetch() and FileDate(), and by windowheight() in
+ * amiga/amiga.c (UnZip). time() is used only by Zip.
+ */
+
+
+/* HISTORY/CHANGES
+ * 2 Sep 92, Greg Roelofs, Original coding.
+ * 6 Sep 92, John Bush, Incorporated into UnZip 5.1
+ * 6 Sep 92, John Bush, Interlude "FileDate()" defined, which calls or
+ * redefines SetFileDate() depending upon AMIGADOS2 definition.
+ * 11 Oct 92, John Bush, Eliminated AMIGADOS2 switch by determining
+ * revision via OpenLibrary() call. Now only one version of
+ * the program runs on both platforms (1.3.x vs. 2.x)
+ * 11 Oct 92, John Bush, Merged with Zip version and changed arg passing
+ * to take time_t input instead of struct DateStamp.
+ * Arg passing made to conform with utime().
+ * 22 Nov 92, Paul Kienitz, fixed includes for Aztec and cleaned up some
+ * lint-ish errors; simplified test for AmigaDOS version.
+ * 11 Nov 95, Paul Kienitz, added Agetch() for crypt password input and
+ * UnZip's "More" prompt -- simplifies crypt.h and avoids
+ * use of library code redundant with sendpkt(). Made it
+ * available to fUnZip, which does not use FileDate().
+ * 22 Nov 95, Paul Kienitz, created a new tzset() that gets the current
+ * timezone from the Locale preferences. These exist only under
+ * AmigaDOS 2.1 and up, but it is probably correctly set on more
+ * Amigas than the TZ environment variable is. We check that
+ * only if TZ is not validly set. We do not parse daylight
+ * savings syntax except to check for presence vs. absence of a
+ * DST part; United States rules are assumed. This is better
+ * than the tzset()s in the Amiga compilers' libraries do.
+ * 15 Jan 96, Chr. Spieler, corrected the logic when to select low level
+ * sendpkt() (when FileDate(), Agetch() or windowheight() is used),
+ * and AMIGA's Agetch() (CRYPT, and UnZip(SFX)'s UzpMorePause()).
+ * 10 Feb 96, Paul Kienitz, re-fiddled that selection logic again, moved
+ * stuff around for clarity.
+ * 16 Mar 96, Paul Kienitz, created a replacement localtime() to go with the
+ * new tzset(), because Aztec's is hopelessly broken. Also
+ * gmtime(), which localtime() calls.
+ * 12 Apr 96, Paul Kienitz, daylight savings was being handled incorrectly.
+ * 21 Apr 96, Paul Kienitz, had to replace time() as well, Aztec's returns
+ * local time instead of GMT. That's why their localtime() was bad,
+ * because it assumed time_t was already local, and gmtime() was
+ * the one that checked TZ.
+ * 23 Apr 96, Chr. Spieler, deactivated time() replacement for UnZip stuff.
+ * Currently, the UnZip sources do not make use of time() (and do
+ * not supply the working mktime() replacement, either!).
+ * 29 Apr 96, Paul Kienitz, created a replacement getenv() out of code that
+ * was previously embedded in tzset(), for reliable global test
+ * of whether TZ is set or not.
+ * 19 Jun 96, Haidinger Walter, re-adapted for current SAS/C compiler.
+ * 7 Jul 96, Paul Kienitz, smoothed together compiler-related changes.
+ * 4 Feb 97, Haidinger Walter, added set_TZ() for SAS/C.
+ * 23 Apr 97, Paul Kienitz, corrected Unix->Amiga DST error by adding
+ * mkgmtime() so localtime() could be used.
+ * 28 Apr 97, Christian Spieler, deactivated mkgmtime() definition for ZIP;
+ * the Zip sources supply this function as part of util.c.
+ * 24 May 97, Haidinger Walter, added time_lib support for SAS/C and moved
+ * set_TZ() to time_lib.c.
+ * 12 Jul 97, Paul Kienitz, adapted time_lib stuff for Aztec.
+ * 26 Jul 97, Chr. Spieler, old mkgmtime() fixed (ydays[] def, sign vs unsign).
+ * 30 Dec 97, Haidinger Walter, adaptation for SAS/C using z-stat.h functions.
+ * 19 Feb 98, Haidinger Walter, removed alloc_remember, more SAS.C fixes.
+ * 23 Apr 98, Chr. Spieler, removed mkgmtime(), changed FileDate to convert to
+ * Amiga file-time directly.
+ * 24 Apr 98, Paul Kienitz, clip Unix dates earlier than 1978 in FileDate().
+ * 02 Sep 98, Paul Kienitz, C. Spieler, always include zip.h to get a defined
+ * header inclusion sequence that resolves all header dependencies.
+ */
+
+#ifndef __amiga_filedate_c
+#define __amiga_filedate_c
+
+
+#include "zip.h"
+#include <ctype.h>
+#include <errno.h>
+
+#include <exec/types.h>
+#include <exec/execbase.h>
+#include <exec/memory.h>
+
+#ifdef AZTEC_C
+# include <libraries/dos.h>
+# include <libraries/dosextens.h>
+# include <clib/exec_protos.h>
+# include <clib/dos_protos.h>
+# include <clib/locale_protos.h>
+# include <pragmas/exec_lib.h>
+# include <pragmas/dos_lib.h>
+# include <pragmas/locale_lib.h>
+# define ESRCH ENOENT
+# define EOSERR EIO
+#endif
+
+#ifdef __SASC
+# include <stdlib.h>
+# if (defined(_M68020) && (!defined(__USE_SYSBASE)))
+ /* on 68020 or higher processors it is faster */
+# define __USE_SYSBASE /* to use the pragma libcall instead of syscall */
+# endif /* to access functions of the exec.library */
+# include <proto/exec.h> /* see SAS/C manual:part 2,chapter 2,pages 6-7 */
+# include <proto/dos.h>
+# include <proto/locale.h>
+# ifdef DEBUG
+# include <sprof.h>
+# endif
+# ifdef MWDEBUG
+# include <stdio.h> /* include both before memwatch.h again just */
+# include <stdlib.h> /* to be safe */
+# include "memwatch.h"
+# endif /* MWDEBUG */
+#endif /* __SASC */
+
+#include "crypt.h" /* just so we can tell if CRYPT is supported */
+
+
+
+#ifndef FUNZIP
+
+#ifndef SUCCESS
+# define SUCCESS (-1L)
+# define FAILURE 0L
+#endif
+
+#define ReqVers 36L /* required library version for SetFileDate() */
+#define ENVSIZE 100 /* max space allowed for an environment var */
+
+extern struct ExecBase *SysBase;
+
+#ifndef USE_TIME_LIB
+#ifdef AZTEC_C /* should be pretty safe for reentrancy */
+ long timezone = 0; /* already declared SAS/C external */
+ int daylight = 0; /* likewise */
+#endif
+int real_timezone_is_set = FALSE; /* set by tzset() */
+#endif /* !USE_TIME_LIB */
+
+/* prototypes */
+char *getenv(const char *var);
+#ifdef __SASC
+int setenv(const char *var, const char *value, int overwrite);
+/* !!!! We have really got to find a way to operate without this. */
+#endif
+
+LONG FileDate (char *filename, time_t u[]);
+LONG sendpkt(struct MsgPort *pid, LONG action, LONG *args, LONG nargs);
+int Agetch(void);
+
+/* prototypes for time replacement functions */
+#ifndef USE_TIME_LIB
+ void tzset(void);
+ int locale_TZ(void);
+ struct tm *gmtime(const time_t *when);
+ struct tm *localtime(const time_t *when);
+# ifdef __SASC
+ extern void set_TZ(long time_zone, int day_light); /* in time_lib.c */
+# endif
+# ifdef ZIP
+ time_t time(time_t *tp);
+# endif
+#endif /* !USE_TIME_LIB */
+
+/* =============================================================== */
+
+/***********************/
+/* Function filedate() */
+/***********************/
+
+/* FileDate() (originally utime.c), by Paul Wells. Modified by John Bush
+ * and others (see also sendpkt() comments, below); NewtWare SetFileDate()
+ * clone cheaply ripped off from utime().
+ */
+
+/* DESCRIPTION
+ * This routine chooses between 2 methods to set the file date on AMIGA.
+ * Since AmigaDOS 2.x came out, SetFileDate() was available in ROM (v.36
+ * and higher). Under AmigaDOS 1.3.x (less than v.36 ROM), SetFileDate()
+ * must be accomplished by constructing a message packet and sending it
+ * to the file system handler of the file to be stamped.
+ *
+ * The system's ROM version is extracted from the external system Library
+ * base.
+ *
+ * NOTE: although argument passing conforms with utime(), note the
+ * following differences:
+ * - Return value is boolean success/failure.
+ * - If a structure or array is passed, only the first value
+ * is used, which *may* correspond to date accessed and not
+ * date modified.
+ */
+
+/* Nonzero if `y' is a leap year, else zero. */
+#define leap(y) (((y) % 4 == 0 && (y) % 100 != 0) || (y) % 400 == 0)
+
+/* Number of leap years from 1970 to `y' (not including `y' itself). */
+#define nleap(y) (((y) - 1969) / 4 - ((y) - 1901) / 100 + ((y) - 1601) / 400)
+
+/* Accumulated number of days from 01-Jan up to start of current month. */
+#ifdef ZIP
+static const unsigned short ydays[] =
+{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
+#else
+extern const unsigned short ydays[]; /* in unzip's fileio.c */
+#endif
+
+LONG FileDate(filename, u)
+ char *filename;
+ time_t u[];
+{
+ LONG SetFileDate(UBYTE *filename, struct DateStamp *pDate);
+ LONG sendpkt(struct MsgPort *pid, LONG action, LONG *args, LONG nargs);
+ struct MsgPort *taskport;
+ BPTR dirlock, lock;
+ struct FileInfoBlock *fib;
+ LONG pktargs[4];
+ UBYTE *ptr;
+ long ret;
+
+ struct DateStamp pDate;
+ struct tm *ltm;
+ int years;
+
+ /* tzset(); */
+ /* Amiga file date is based on 01-Jan-1978 00:00:00 (local time):
+ * 8 years and 2 leapdays difference from Unix time.
+ */
+ ltm = localtime(&u[0]);
+ years = ltm->tm_year + 1900;
+ if (years < 1978)
+ pDate.ds_Days = pDate.ds_Minute = pDate.ds_Tick = 0;
+ else {
+ pDate.ds_Days = (years - 1978) * 365L + (nleap(years) - 2) +
+ ((ltm->tm_mon > 1 && leap(years)) ? 1 : 0) +
+ ydays[ltm->tm_mon] + (ltm->tm_mday - 1);
+ pDate.ds_Minute = ltm->tm_hour * 60 + ltm->tm_min;
+ pDate.ds_Tick = ltm->tm_sec * TICKS_PER_SECOND;
+ }
+
+ if (SysBase->LibNode.lib_Version >= ReqVers)
+ {
+ return (SetFileDate(filename,&pDate)); /* native routine at 2.0+ */
+ }
+ else /* !(SysBase->lib_Version >=ReqVers) */
+ {
+ if( !(taskport = (struct MsgPort *)DeviceProc(filename)) )
+ {
+ errno = ESRCH; /* no such process */
+ return FAILURE;
+ }
+
+ if( !(lock = Lock(filename,SHARED_LOCK)) )
+ {
+ errno = ENOENT; /* no such file */
+ return FAILURE;
+ }
+
+ if( !(fib = (struct FileInfoBlock *)AllocMem(
+ (long)sizeof(struct FileInfoBlock),MEMF_PUBLIC|MEMF_CLEAR)) )
+ {
+ errno = ENOMEM; /* insufficient memory */
+ UnLock(lock);
+ return FAILURE;
+ }
+
+ if( Examine(lock,fib)==FAILURE )
+ {
+ errno = EOSERR; /* operating system error */
+ UnLock(lock);
+ FreeMem(fib,(long)sizeof(*fib));
+ return FAILURE;
+ }
+
+ dirlock = ParentDir(lock);
+ ptr = (UBYTE *)AllocMem(64L,MEMF_PUBLIC);
+ strcpy((ptr+1),fib->fib_FileName);
+ *ptr = strlen(fib->fib_FileName);
+ FreeMem(fib,(long)sizeof(*fib));
+ UnLock(lock);
+
+ /* now fill in argument array */
+
+ pktargs[0] = 0;
+ pktargs[1] = (LONG)dirlock;
+ pktargs[2] = (LONG)&ptr[0] >> 2;
+ pktargs[3] = (LONG)&pDate;
+
+ errno = ret = sendpkt(taskport,ACTION_SET_DATE,pktargs,4L);
+
+ FreeMem(ptr,64L);
+ UnLock(dirlock);
+
+ return SUCCESS;
+ } /* ?(SysBase->lib_Version >= ReqVers) */
+} /* FileDate() */
+
+
+char *getenv(const char *var) /* not reentrant! */
+{
+ static char space[ENVSIZE];
+ struct Process *me = (void *) FindTask(NULL);
+ void *old_window = me->pr_WindowPtr;
+ char *ret = NULL;
+
+ me->pr_WindowPtr = (void *) -1; /* suppress any "Please insert" popups */
+ if (SysBase->LibNode.lib_Version >= ReqVers) {
+ if (GetVar((char *) var, space, ENVSIZE - 1, /* GVF_GLOBAL_ONLY */ 0) > 0)
+ ret = space;
+ } else { /* early AmigaDOS, get env var the crude way */
+ BPTR hand, foot, spine;
+ int z = 0;
+ if (foot = Lock("ENV:", ACCESS_READ)) {
+ spine = CurrentDir(foot);
+ if (hand = Open((char *) var, MODE_OLDFILE)) {
+ z = Read(hand, space, ENVSIZE - 1);
+ Close(hand);
+ }
+ UnLock(CurrentDir(spine));
+ }
+ if (z > 0) {
+ space[z] = '\0';
+ ret = space;
+ }
+ }
+ me->pr_WindowPtr = old_window;
+ return ret;
+}
+
+#ifdef __SASC
+int setenv(const char *var, const char *value, int overwrite)
+{
+ struct Process *me = (void *) FindTask(NULL);
+ void *old_window = me->pr_WindowPtr;
+ int ret = -1;
+
+ me->pr_WindowPtr = (void *) -1; /* suppress any "Please insert" popups */
+ if (SysBase->LibNode.lib_Version >= ReqVers)
+ ret = !SetVar((char *) var, (char *) value, -1, GVF_GLOBAL_ONLY | LV_VAR);
+ else {
+ BPTR hand, foot, spine;
+ long len = value ? strlen(value) : 0;
+ if (foot = Lock("ENV:", ACCESS_READ)) {
+ spine = CurrentDir(foot);
+ if (len) {
+ if (hand = Open((char *) var, MODE_NEWFILE)) {
+ ret = Write(hand, (char *) value, len + 1) >= len;
+ Close(hand);
+ }
+ } else
+ ret = DeleteFile((char *) var);
+ UnLock(CurrentDir(spine));
+ }
+ }
+ me->pr_WindowPtr = old_window;
+ return ret;
+}
+#endif /* __SASC */
+
+
+#ifndef USE_TIME_LIB
+
+/* set timezone and daylight to settings found in locale.library */
+int locale_TZ(void)
+{
+ struct Library *LocaleBase;
+ struct Locale *ll;
+ struct Process *me = (void *) FindTask(NULL);
+ void *old_window = me->pr_WindowPtr;
+ BPTR eh;
+ int z, valid = FALSE;
+
+ /* read timezone from locale.library if TZ envvar missing */
+ me->pr_WindowPtr = (void *) -1; /* suppress any "Please insert" popups */
+ if (LocaleBase = OpenLibrary("locale.library", 0)) {
+ if (ll = OpenLocale(NULL)) {
+ z = ll->loc_GMTOffset;
+ if (z == -300) {
+ if (eh = Lock("ENV:sys/locale.prefs", ACCESS_READ))
+ UnLock(eh);
+ else
+ z = 300; /* bug: locale not initialized, default is bogus! */
+ } else
+ real_timezone_is_set = TRUE;
+ timezone = z * 60;
+ daylight = (z >= 4*60 && z <= 9*60); /* apply in the Americas */
+ valid = TRUE;
+ CloseLocale(ll);
+ }
+ CloseLibrary(LocaleBase);
+ }
+ me->pr_WindowPtr = old_window;
+ return valid;
+}
+
+void tzset(void)
+{
+ char *p,*TZstring;
+ int z,valid = FALSE;
+
+ if (real_timezone_is_set)
+ return;
+ timezone = 0; /* default is GMT0 which means no offsets */
+ daylight = 0; /* from local system time */
+ TZstring = getenv("TZ"); /* read TZ envvar */
+ if (TZstring && TZstring[0]) { /* TZ exists and has contents? */
+ z = 3600;
+ for (p = TZstring; *p && !isdigit(*p) && *p != '-'; p++) ;
+ if (*p == '-')
+ z = -3600, p++;
+ if (*p) {
+ timezone = 0;
+ do {
+ while (isdigit(*p))
+ timezone = timezone * 10 + z * (*p++ - '0'), valid = TRUE;
+ if (*p == ':') p++;
+ } while (isdigit(*p) && (z /= 60) > 0);
+ }
+ while (isspace(*p)) p++; /* probably not needed */
+ if (valid) {
+ real_timezone_is_set = TRUE;
+ daylight = !!*p; /* a DST name part exists */
+ }
+ }
+ if (!valid)
+ locale_TZ(); /* read locale.library */
+#ifdef __SASC
+ /* Some SAS/C library functions, e.g. stat(), call library */
+ /* __tzset() themselves. So envvar TZ *must* exist in order to */
+ /* to get the right offset from GMT. XXX WE SHOULD TRY HARD */
+ /* find and replace any remaining functions that need this! */
+ set_TZ(timezone, daylight);
+#endif /* __SASC */
+}
+
+
+struct tm *gmtime(const time_t *when)
+{
+ static struct tm tbuf; /* this function is intrinsically non-reentrant */
+ static short smods[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+ long days = *when / 86400;
+ long secs = *when % 86400;
+ short yell, yday;
+
+ tbuf.tm_wday = (days + 4) % 7; /* 1/1/70 is a Thursday */
+ tbuf.tm_year = 70 + 4 * (days / 1461);
+ yday = days % 1461;
+ while (yday >= (yell = (tbuf.tm_year & 3 ? 365 : 366)))
+ yday -= yell, tbuf.tm_year++;
+ smods[1] = (tbuf.tm_year & 3 ? 28 : 29);
+ tbuf.tm_mon = 0;
+ tbuf.tm_yday = yday;
+ while (yday >= smods[tbuf.tm_mon])
+ yday -= smods[tbuf.tm_mon++];
+ tbuf.tm_mday = yday + 1;
+ tbuf.tm_isdst = 0;
+ tbuf.tm_sec = secs % 60;
+ tbuf.tm_min = (secs / 60) % 60;
+ tbuf.tm_hour = secs / 3600;
+#ifdef AZTEC_C
+ tbuf.tm_hsec = 0; /* this field exists for Aztec only */
+#endif
+ return &tbuf;
+}
+
+struct tm *localtime(const time_t *when)
+{
+ struct tm *t;
+ time_t localwhen;
+ int dst = FALSE, sundays, lastweekday;
+
+ tzset();
+ localwhen = *when - timezone;
+ t = gmtime(&localwhen);
+ /* So far we support daylight savings correction by the USA rule only: */
+ if (daylight && t->tm_mon >= 3 && t->tm_mon <= 9) {
+ if (t->tm_mon > 3 && t->tm_mon < 9) /* May Jun Jul Aug Sep: yes */
+ dst = TRUE;
+ else {
+ sundays = (t->tm_mday + 6 - t->tm_wday) / 7;
+ if (t->tm_wday == 0 && t->tm_hour < 2 && sundays)
+ sundays--; /* a Sunday does not count until 2:00am */
+ if (t->tm_mon == 3 && sundays > 0) /* first sunday in April */
+ dst = TRUE;
+ else if (t->tm_mon == 9) {
+ lastweekday = (t->tm_wday + 31 - t->tm_mday) % 7;
+ if (sundays < (37 - lastweekday) / 7)
+ dst = TRUE; /* last sunday in October */
+ }
+ }
+ if (dst) {
+ localwhen += 3600;
+ t = gmtime(&localwhen); /* crude but effective */
+ t->tm_isdst = 1;
+ }
+ }
+ return t;
+}
+
+
+# ifdef ZIP
+time_t time(time_t *tp)
+{
+ time_t t;
+ struct DateStamp ds;
+ DateStamp(&ds);
+ t = ds.ds_Tick / TICKS_PER_SECOND + ds.ds_Minute * 60
+ + (ds.ds_Days + 2922) * 86400;
+ t = mktime(gmtime(&t));
+ /* gmtime leaves ds in the local timezone, mktime converts it to GMT */
+ if (tp) *tp = t;
+ return t;
+}
+# endif /* ZIP */
+#endif /* !USE_TIME_LIB */
+
+#endif /* !FUNZIP */
+
+
+#if CRYPT || !defined(FUNZIP)
+
+/* sendpkt.c
+ * by A. Finkel, P. Lindsay, C. Sheppner
+ * returns Res1 of the reply packet
+ */
+/*
+#include <exec/types.h>
+#include <exec/memory.h>
+#include <libraries/dos.h>
+#include <libraries/dosextens.h>
+#include <proto/exec.h>
+#include <proto/dos.h>
+*/
+
+LONG sendpkt(struct MsgPort *pid, LONG action, LONG *args, LONG nargs);
+
+LONG sendpkt(pid,action,args,nargs)
+struct MsgPort *pid; /* process identifier (handler message port) */
+LONG action, /* packet type (desired action) */
+ *args, /* a pointer to argument list */
+ nargs; /* number of arguments in list */
+{
+
+ struct MsgPort *replyport, *CreatePort(UBYTE *, long);
+ void DeletePort(struct MsgPort *);
+ struct StandardPacket *packet;
+ LONG count, *pargs, res1;
+
+ replyport = CreatePort(NULL,0L);
+ if( !replyport ) return(0);
+
+ packet = (struct StandardPacket *)AllocMem(
+ (long)sizeof(struct StandardPacket),MEMF_PUBLIC|MEMF_CLEAR);
+ if( !packet )
+ {
+ DeletePort(replyport);
+ return(0);
+ }
+
+ packet->sp_Msg.mn_Node.ln_Name = (char *)&(packet->sp_Pkt);
+ packet->sp_Pkt.dp_Link = &(packet->sp_Msg);
+ packet->sp_Pkt.dp_Port = replyport;
+ packet->sp_Pkt.dp_Type = action;
+
+ /* copy the args into the packet */
+ pargs = &(packet->sp_Pkt.dp_Arg1); /* address of 1st argument */
+ for( count=0; count<nargs; count++ )
+ pargs[count] = args[count];
+
+ PutMsg(pid,(struct Message *)packet); /* send packet */
+
+ WaitPort(replyport);
+ GetMsg(replyport);
+
+ res1 = packet->sp_Pkt.dp_Res1;
+
+ FreeMem((char *)packet,(long)sizeof(*packet));
+ DeletePort(replyport);
+
+ return(res1);
+
+} /* sendpkt() */
+
+#endif /* CRYPT || !FUNZIP */
+
+
+#if CRYPT || (defined(UNZIP) && !defined(FUNZIP))
+
+/* Agetch() reads one raw keystroke -- uses sendpkt() */
+
+int Agetch(void)
+{
+ LONG sendpkt(struct MsgPort *pid, LONG action, LONG *args, LONG nargs);
+ struct Task *me = FindTask(NULL);
+ struct CommandLineInterface *cli = BADDR(((struct Process *) me)->pr_CLI);
+ BPTR fh = cli->cli_StandardInput; /* this is immune to < redirection */
+ void *conp = ((struct FileHandle *) BADDR(fh))->fh_Type;
+ char longspace[8];
+ long *flag = (long *) ((ULONG) &longspace[4] & ~3); /* LONGWORD ALIGNED! */
+ UBYTE c;
+
+ *flag = 1;
+ sendpkt(conp, ACTION_SCREEN_MODE, flag, 1); /* assume success */
+ Read(fh, &c, 1);
+ *flag = 0;
+ sendpkt(conp, ACTION_SCREEN_MODE, flag, 1);
+ if (c == 3) /* ^C in input */
+ Signal(me, SIGBREAKF_CTRL_C);
+ return c;
+}
+
+#endif /* CRYPT || (UNZIP && !FUNZIP) */
+
+#endif /* __amiga_filedate_c*/