Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.   Copyright (c) 1990-2002 Info-ZIP.  All rights reserved.
  3.  
  4.   See the accompanying file LICENSE, version 2000-Apr-09 or later
  5.   (the contents of which are also included in zip.h) for terms of use.
  6.   If, for some reason, all these files are missing, the Info-ZIP license
  7.   also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
  8. */
  9. /* Low-level Amiga routines shared between Zip and UnZip.
  10.  *
  11.  * Contains:  FileDate()
  12.  *            getenv()          [replaces inadequate standard library version]
  13.  *            setenv()          [SAS/C only, replaces standard library version]
  14.  *            set_TZ()          [SAS/C only]
  15.  *            GetPlatformLocalTimezone() [callback from timezone.c tzset()]
  16.  *            time()
  17.  *            sendpkt()
  18.  *            Agetch()
  19.  *
  20.  * The first five are used by most Info-ZIP programs except fUnZip.
  21.  * The last two are used by all except the non-CRYPT version of fUnZip.
  22.  * Probably some of the stuff in here is unused by ZipNote and ZipSplit too...
  23.  * sendpkt() is used by Agetch() and FileDate(), and by screensize() in
  24.  * amiga/amiga.c (UnZip); time() is used only by Zip.
  25.  */
  26.  
  27.  
  28. /* HISTORY/CHANGES
  29.  *  2 Sep 92, Greg Roelofs, Original coding.
  30.  *  6 Sep 92, John Bush, Incorporated into UnZip 5.1
  31.  *  6 Sep 92, John Bush, Interlude "FileDate()" defined, which calls or
  32.  *            redefines SetFileDate() depending upon AMIGADOS2 definition.
  33.  * 11 Oct 92, John Bush, Eliminated AMIGADOS2 switch by determining
  34.  *            revision via OpenLibrary() call.  Now only one version of
  35.  *            the program runs on both platforms (1.3.x vs. 2.x)
  36.  * 11 Oct 92, John Bush, Merged with Zip version and changed arg passing
  37.  *            to take time_t input instead of struct DateStamp.
  38.  *            Arg passing made to conform with utime().
  39.  * 22 Nov 92, Paul Kienitz, fixed includes for Aztec and cleaned up some
  40.  *            lint-ish errors; simplified test for AmigaDOS version.
  41.  * 11 Nov 95, Paul Kienitz, added Agetch() for crypt password input and
  42.  *            UnZip's "More" prompt -- simplifies crypt.h and avoids
  43.  *            use of library code redundant with sendpkt().  Made it
  44.  *            available to fUnZip, which does not use FileDate().
  45.  * 22 Nov 95, Paul Kienitz, created a new tzset() that gets the current
  46.  *            timezone from the Locale preferences.  These exist only under
  47.  *            AmigaDOS 2.1 and up, but it is probably correctly set on more
  48.  *            Amigas than the TZ environment variable is.  We check that
  49.  *            only if TZ is not validly set.  We do not parse daylight
  50.  *            savings syntax except to check for presence vs. absence of a
  51.  *            DST part; United States rules are assumed.  This is better
  52.  *            than the tzset()s in the Amiga compilers' libraries do.
  53.  * 15 Jan 96, Chr. Spieler, corrected the logic when to select low level
  54.  *            sendpkt() (when FileDate(), Agetch() or windowheight() is used),
  55.  *            and AMIGA's Agetch() (CRYPT, and UnZip(SFX)'s UzpMorePause()).
  56.  * 10 Feb 96, Paul Kienitz, re-fiddled that selection logic again, moved
  57.  *            stuff around for clarity.
  58.  * 16 Mar 96, Paul Kienitz, created a replacement localtime() to go with the
  59.  *            new tzset(), because Aztec's is hopelessly broken.  Also
  60.  *            gmtime(), which localtime() calls.
  61.  * 12 Apr 96, Paul Kienitz, daylight savings was being handled incorrectly.
  62.  * 21 Apr 96, Paul Kienitz, had to replace time() as well, Aztec's returns
  63.  *            local time instead of GMT.  That's why their localtime() was bad,
  64.  *            because it assumed time_t was already local, and gmtime() was
  65.  *            the one that checked TZ.
  66.  * 23 Apr 96, Chr. Spieler, deactivated time() replacement for UnZip stuff.
  67.  *            Currently, the UnZip sources do not make use of time() (and do
  68.  *            not supply the working mktime() replacement, either!).
  69.  * 29 Apr 96, Paul Kienitz, created a replacement getenv() out of code that
  70.  *            was previously embedded in tzset(), for reliable global test
  71.  *            of whether TZ is set or not.
  72.  * 19 Jun 96, Haidinger Walter, re-adapted for current SAS/C compiler.
  73.  *  7 Jul 96, Paul Kienitz, smoothed together compiler-related changes.
  74.  *  4 Feb 97, Haidinger Walter, added set_TZ() for SAS/C.
  75.  * 23 Apr 97, Paul Kienitz, corrected Unix->Amiga DST error by adding
  76.  *            mkgmtime() so localtime() could be used.
  77.  * 28 Apr 97, Christian Spieler, deactivated mkgmtime() definition for ZIP;
  78.  *            the Zip sources supply this function as part of util.c.
  79.  * 24 May 97, Haidinger Walter, added time_lib support for SAS/C and moved
  80.  *            set_TZ() to time_lib.c.
  81.  * 12 Jul 97, Paul Kienitz, adapted time_lib stuff for Aztec.
  82.  * 26 Jul 97, Chr. Spieler, old mkgmtime() fixed (ydays[] def, sign vs unsign).
  83.  * 30 Dec 97, Haidinger Walter, adaptation for SAS/C using z-stat.h functions.
  84.  * 19 Feb 98, Haidinger Walter, removed alloc_remember, more SAS.C fixes.
  85.  * 23 Apr 98, Chr. Spieler, removed mkgmtime(), changed FileDate to convert to
  86.  *            Amiga file-time directly.
  87.  * 24 Apr 98, Paul Kienitz, clip Unix dates earlier than 1978 in FileDate().
  88.  * 02 Sep 98, Paul Kienitz, C. Spieler, always include zip.h to get a defined
  89.  *            header inclusion sequence that resolves all header dependencies.
  90.  * 06 Jun 00, Paul Kienitz, removed time_lib.c due to its incompatible license,
  91.  *            moved set_TZ() back here, replaced minimal tzset() and localtime()
  92.  *            with new versions derived from GNU glibc source.  Gave locale_TZ()
  93.  *            reasonable European defaults for daylight savings.
  94.  * 17 Jun 00, Paul Kienitz, threw out GNU code because of objections to the GPL
  95.  *            virus, replaced with similar functions based on the public domain
  96.  *            timezone code at ftp://elsie.nci.nih.gov/pub.  As with the GNU
  97.  *            stuff, support for timezone files and leap seconds was removed.
  98.  * 23 Aug 00, Paul Kienitz, moved timezone code out from here into separate
  99.  *            platform-independent module 'timezone.c'.
  100.  * 31 Dec 00, Christian Spieler, moved system-specific timezone help funcions
  101.  *            back in here, from 'timezone.c'.
  102.  * 07 Jan 01, Paul Kienitz, Chr. Spieler, added missing #include "timezone.h"
  103.  *            and "symbolic" preprocessor constants for time calculations.
  104.  * 15 Jan 02, Paul Kienitz, excluded all time handling code from compilation
  105.  *            for Zip utilities (when "defined(UTIL)")
  106.  */
  107.  
  108. #ifndef __amiga_filedate_c
  109. #define __amiga_filedate_c
  110.  
  111.  
  112. #include "zip.h"
  113. #include <ctype.h>
  114. #include <errno.h>
  115.  
  116. #include <exec/types.h>
  117. #include <exec/execbase.h>
  118. #include <exec/memory.h>
  119. #include <dos/dosextens.h>
  120.  
  121. #ifdef AZTEC_C
  122. #  include <libraries/dos.h>
  123. #  include <libraries/dosextens.h>
  124. #  include <clib/exec_protos.h>
  125. #  include <clib/dos_protos.h>
  126. #  include <clib/locale_protos.h>
  127. #  include <pragmas/exec_lib.h>
  128. #  include <pragmas/dos_lib.h>
  129. #  include <pragmas/locale_lib.h>
  130. #  define ESRCH  ENOENT
  131. #  define EOSERR EIO
  132. #endif
  133.  
  134. #ifdef __SASC
  135. #  include <stdlib.h>
  136. #  if (defined(_M68020) && (!defined(__USE_SYSBASE)))
  137.                             /* on 68020 or higher processors it is faster   */
  138. #    define __USE_SYSBASE   /* to use the pragma libcall instead of syscall */
  139. #  endif                    /* to access functions of the exec.library      */
  140. #  include <proto/exec.h>   /* see SAS/C manual:part 2,chapter 2,pages 6-7  */
  141. #  include <proto/dos.h>
  142. #  include <proto/locale.h>
  143. #  ifdef DEBUG
  144. #     include <sprof.h>
  145. #  endif
  146. #  ifdef MWDEBUG
  147. #    include <stdio.h>      /* include both before memwatch.h again just */
  148. #    include <stdlib.h>     /* to be safe */
  149. #    include "memwatch.h"
  150. #  endif /* MWDEBUG */
  151. #endif /* __SASC */
  152.  
  153. #include "crypt.h"            /* just so we can tell if CRYPT is supported */
  154.  
  155.  
  156. #if (!defined(FUNZIP) && !defined(UTIL))
  157.  
  158. #include "timezone.h"         /* for AMIGA-specific timezone callbacks */
  159.  
  160. #ifndef SUCCESS
  161. #  define SUCCESS (-1L)
  162. #  define FAILURE 0L
  163. #endif
  164.  
  165. #define ReqVers 36L        /* required library version for SetFileDate() */
  166. #define ENVSIZE 100        /* max space allowed for an environment var   */
  167.  
  168. extern struct ExecBase *SysBase;
  169.  
  170. #ifndef min
  171. #  define min(a, b)  ((a) < (b) ? (a) : (b))
  172. #  define max(a, b)  ((a) < (b) ? (b) : (a))
  173. #endif
  174.  
  175. #if defined(ZIP) || defined(HAVE_MKTIME)
  176. static const unsigned short ydays[] =
  177.     { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
  178. #else
  179. extern const unsigned short ydays[];  /* in unzip's fileio.c */
  180. #endif
  181.  
  182. #define LEAP(y)     (((y) % 4 == 0 && (y) % 100 != 0) || (y) % 400 == 0)
  183. #define YDAYS(m, y) (ydays[m] + (m > 1 && LEAP(y)))
  184. /* Number of leap years from 1978 to `y' (not including `y' itself). */
  185. #define ANLEAP(y)   (((y) - 1977) / 4 - ((y) - 1901) / 100 + ((y) - 1601) / 400)
  186. #define SECSPERMIN  60
  187. #define MINSPERHOUR 60
  188. #define SECSPERHOUR (SECSPERMIN * MINSPERHOUR)
  189. #define SECSPERDAY  86400L
  190.  
  191. /* prototypes */
  192. char *getenv(const char *var);
  193. #ifdef __SASC
  194. /*  XXX !!  We have really got to find a way to operate without these. */
  195. int setenv(const char *var, const char *value, int overwrite);
  196. void set_TZ(long time_zone, int day_light);
  197. #endif
  198.  
  199. LONG FileDate(char *filename, time_t u[]);
  200. LONG sendpkt(struct MsgPort *pid, LONG action, LONG *args, LONG nargs);
  201. int Agetch(void);
  202.  
  203. /* =============================================================== */
  204.  
  205. /***********************/
  206. /* Function filedate() */
  207. /***********************/
  208.  
  209. /*  FileDate() (originally utime.c), by Paul Wells.  Modified by John Bush
  210.  *  and others (see also sendpkt() comments, below); NewtWare SetFileDate()
  211.  *  clone cheaply ripped off from utime().
  212.  */
  213.  
  214. /* DESCRIPTION
  215.  * This routine chooses between 2 methods to set the file date on AMIGA.
  216.  * Since AmigaDOS 2.x came out, SetFileDate() was available in ROM (v.36
  217.  * and higher).  Under AmigaDOS 1.3.x (less than v.36 ROM), SetFileDate()
  218.  * must be accomplished by constructing a message packet and sending it
  219.  * to the file system handler of the file to be stamped.
  220.  *
  221.  * The system's ROM version is extracted from the external system Library
  222.  * base.
  223.  *
  224.  * NOTE:  although argument passing conforms with utime(), note the
  225.  *        following differences:
  226.  *          - Return value is boolean success/failure.
  227.  *          - If a structure or array is passed, only the first value
  228.  *            is used, which *may* correspond to date accessed and not
  229.  *            date modified.
  230.  */
  231.  
  232. LONG FileDate(filename, u)
  233.     char *filename;
  234.     time_t u[];
  235. {
  236.     LONG SetFileDate(UBYTE *filename, struct DateStamp *pDate);
  237.     LONG sendpkt(struct MsgPort *pid, LONG action, LONG *args, LONG nargs);
  238.     struct MsgPort *taskport;
  239.     BPTR dirlock, lock;
  240.     struct FileInfoBlock *fib;
  241.     LONG pktargs[4];
  242.     UBYTE *ptr;
  243.     long ret;
  244.  
  245.     struct DateStamp pDate;
  246.     struct tm *ltm;
  247.     int years;
  248.  
  249.     tzset();
  250.     /* Amiga file date is based on 01-Jan-1978 00:00:00 (local time):
  251.      * 8 years and 2 leapdays difference from Unix time.
  252.      */
  253.     ltm = localtime(&u[0]);
  254.     years = ltm->tm_year + 1900;
  255.     if (years < 1978)
  256.         pDate.ds_Days = pDate.ds_Minute = pDate.ds_Tick = 0;
  257.     else {
  258.         pDate.ds_Days = (years - 1978) * 365L + (ANLEAP(years)) +
  259.                         YDAYS(ltm->tm_mon, years) + (ltm->tm_mday - 1);
  260.         pDate.ds_Minute = ltm->tm_hour * 60 + ltm->tm_min;
  261.         pDate.ds_Tick = ltm->tm_sec * TICKS_PER_SECOND;
  262.     }
  263.  
  264.     if (SysBase->LibNode.lib_Version >= ReqVers)
  265.     {
  266.         return (SetFileDate(filename,&pDate));  /* native routine at 2.0+ */
  267.     }
  268.     else  /* !(SysBase->lib_Version >=ReqVers) */
  269.     {
  270.         if( !(taskport = (struct MsgPort *)DeviceProc(filename)) )
  271.         {
  272.             errno = ESRCH;          /* no such process */
  273.             return FAILURE;
  274.         }
  275.  
  276.         if( !(lock = Lock(filename,SHARED_LOCK)) )
  277.         {
  278.             errno = ENOENT;         /* no such file */
  279.             return FAILURE;
  280.         }
  281.  
  282.         if( !(fib = (struct FileInfoBlock *)AllocMem(
  283.             (long)sizeof(struct FileInfoBlock),MEMF_PUBLIC|MEMF_CLEAR)) )
  284.         {
  285.             errno = ENOMEM;         /* insufficient memory */
  286.             UnLock(lock);
  287.             return FAILURE;
  288.         }
  289.  
  290.         if( Examine(lock,fib)==FAILURE )
  291.         {
  292.             errno = EOSERR;         /* operating system error */
  293.             UnLock(lock);
  294.             FreeMem(fib,(long)sizeof(*fib));
  295.             return FAILURE;
  296.         }
  297.  
  298.         dirlock = ParentDir(lock);
  299.         ptr = (UBYTE *)AllocMem(64L,MEMF_PUBLIC);
  300.         strcpy((ptr+1),fib->fib_FileName);
  301.         *ptr = strlen(fib->fib_FileName);
  302.         FreeMem(fib,(long)sizeof(*fib));
  303.         UnLock(lock);
  304.  
  305.         /* now fill in argument array */
  306.  
  307.         pktargs[0] = 0;
  308.         pktargs[1] = (LONG)dirlock;
  309.         pktargs[2] = (LONG)&ptr[0] >> 2;
  310.         pktargs[3] = (LONG)&pDate;
  311.  
  312.         errno = ret = sendpkt(taskport,ACTION_SET_DATE,pktargs,4L);
  313.  
  314.         FreeMem(ptr,64L);
  315.         UnLock(dirlock);
  316.  
  317.         return SUCCESS;
  318.     }  /* ?(SysBase->lib_Version >= ReqVers) */
  319. } /* FileDate() */
  320.  
  321.  
  322. char *getenv(const char *var)         /* not reentrant! */
  323. {
  324.     static char space[ENVSIZE];
  325.     struct Process *me = (void *) FindTask(NULL);
  326.     void *old_window = me->pr_WindowPtr;
  327.     char *ret = NULL;
  328.  
  329.     me->pr_WindowPtr = (void *) -1;   /* suppress any "Please insert" popups */
  330.     if (SysBase->LibNode.lib_Version >= ReqVers) {
  331.         if (GetVar((char *) var, space, ENVSIZE - 1, /*GVF_GLOBAL_ONLY*/ 0) > 0)
  332.             ret = space;
  333.     } else {                    /* early AmigaDOS, get env var the crude way */
  334.         BPTR hand, foot, spine;
  335.         int z = 0;
  336.         if (foot = Lock("ENV:", ACCESS_READ)) {
  337.             spine = CurrentDir(foot);
  338.             if (hand = Open((char *) var, MODE_OLDFILE)) {
  339.                 z = Read(hand, space, ENVSIZE - 1);
  340.                 Close(hand);
  341.             }
  342.             UnLock(CurrentDir(spine));
  343.         }
  344.         if (z > 0) {
  345.             space[z] = '\0';
  346.             ret = space;
  347.         }
  348.     }
  349.     me->pr_WindowPtr = old_window;
  350.     return ret;
  351. }
  352.  
  353. #ifdef __SASC
  354. int setenv(const char *var, const char *value, int overwrite)
  355. {
  356.     struct Process *me = (void *) FindTask(NULL);
  357.     void *old_window = me->pr_WindowPtr;
  358.     int ret = -1;
  359.  
  360.     me->pr_WindowPtr = (void *) -1;   /* suppress any "Please insert" popups */
  361.     if (SysBase->LibNode.lib_Version >= ReqVers)
  362.         ret = !SetVar((char *)var, (char *)value, -1, GVF_GLOBAL_ONLY | LV_VAR);
  363.     else {
  364.         BPTR hand, foot, spine;
  365.         long len = value ? strlen(value) : 0;
  366.         if (foot = Lock("ENV:", ACCESS_READ)) {
  367.             spine = CurrentDir(foot);
  368.             if (len) {
  369.                 if (hand = Open((char *) var, MODE_NEWFILE)) {
  370.                     ret = Write(hand, (char *) value, len + 1) >= len;
  371.                     Close(hand);
  372.                 }
  373.             } else
  374.                 ret = DeleteFile((char *) var);
  375.             UnLock(CurrentDir(spine));
  376.         }
  377.     }
  378.     me->pr_WindowPtr = old_window;
  379.     return ret;
  380. }
  381.  
  382. /* Stores data from timezone and daylight to ENV:TZ.                  */
  383. /* ENV:TZ is required to exist by some other SAS/C library functions, */
  384. /* like stat() or fstat().                                            */
  385. void set_TZ(long time_zone, int day_light)
  386. {
  387.     char put_tz[MAXTIMEZONELEN];  /* string for putenv: "TZ=aaabbb:bb:bbccc" */
  388.     int offset;
  389.     void *exists;     /* dummy ptr to see if global envvar TZ already exists */
  390.     exists = (void *)getenv(TZ_ENVVAR);
  391.     /* see if there is already an envvar TZ_ENVVAR. If not, create it */
  392.     if (exists == NULL) {
  393.         /* create TZ string by pieces: */
  394.         sprintf(put_tz, "GMT%+ld", time_zone / 3600L);
  395.         if (time_zone % 3600L) {
  396.             offset = (int) labs(time_zone % 3600L);
  397.             sprintf(put_tz + strlen(put_tz), ":%02d", offset / 60);
  398.             if (offset % 60)
  399.                 sprintf(put_tz + strlen(put_tz), ":%02d", offset % 60);
  400.         }
  401.         if (day_light)
  402.             strcat(put_tz,"DST");
  403.         setenv(TZ_ENVVAR, put_tz, 1);
  404.     }
  405. }
  406. #endif /* __SASC */
  407.  
  408. /* set state as well as possible from settings found in locale.library */
  409. int GetPlatformLocalTimezone(sp, fill_tzstate_from_rules)
  410.      register struct state * ZCONST sp;
  411.      void (*fill_tzstate_from_rules)(struct state * ZCONST sp_res,
  412.                                      ZCONST struct rule * ZCONST start,
  413.                                      ZCONST struct rule * ZCONST end);
  414. {
  415.     struct Library *LocaleBase;
  416.     struct Locale *ll;
  417.     struct Process *me = (void *) FindTask(NULL);
  418.     void *old_window = me->pr_WindowPtr;
  419.     BPTR eh;
  420.     int z, valid = FALSE;
  421.  
  422.     /* read timezone from locale.library if TZ envvar missing */
  423.     me->pr_WindowPtr = (void *) -1;   /* suppress any "Please insert" popups */
  424.     if (LocaleBase = OpenLibrary("locale.library", 0)) {
  425.         if (ll = OpenLocale(NULL)) {
  426.             z = ll->loc_GMTOffset;    /* in minutes */
  427.             if (z == -300) {
  428.                 if (eh = Lock("ENV:sys/locale.prefs", ACCESS_READ)) {
  429.                     UnLock(eh);
  430.                     valid = TRUE;
  431.                 } else
  432.                     z = 300; /* bug: locale not initialized, default bogus! */
  433.             } else
  434.                 valid = TRUE;
  435.             if (valid) {
  436.                 struct rule startrule, stoprule;
  437.  
  438.                 sp->timecnt = 0;
  439.                 sp->typecnt = 1;
  440.                 sp->charcnt = 2;
  441.                 sp->chars[0] = sp->chars[1] = '\0';
  442.                 sp->ttis[0].tt_abbrind = 0;
  443.                 sp->ttis[1].tt_abbrind = 1;
  444.                 sp->ttis[0].tt_gmtoff = -z * MINSPERHOUR;
  445.                 sp->ttis[1].tt_gmtoff = -z * MINSPERHOUR + SECSPERHOUR;
  446.                 sp->ttis[0].tt_isdst = 0;
  447.                 sp->ttis[1].tt_isdst = 1;
  448.                 stoprule.r_type = MONTH_NTH_DAY_OF_WEEK;
  449.                 stoprule.r_day = 0;
  450.                 stoprule.r_week = 5;
  451.                 stoprule.r_mon = 10;
  452.                 stoprule.r_time = 2 * SECSPERHOUR;
  453.                 startrule = stoprule;
  454.                 startrule.r_mon = 4;
  455.                 startrule.r_week = 1;
  456.                 if (z >= -180 && z < 150) {
  457.                     /* At this point we make a really gratuitous assumption: */
  458.                     /* if the time zone could be Europe, we use the European */
  459.                     /* Union rules without checking what country we're in.   */
  460.                     /* The AmigaDOS locale country codes do not, at least in */
  461.                     /* 2.x versions of the OS, recognize very many countries */
  462.                     /* outside of Europe and North America.                  */
  463.                     sp->typecnt = 2;
  464.                     startrule.r_mon = 3;   /* one week earlier than US DST */
  465.                     startrule.r_week = 5;
  466.                 } else if (z >= 150 && z <= 480 &&
  467.                            /* no DST in alaska, hawaii */
  468.                            (ll->loc_CountryCode == 0x55534100 /*"USA"*/ ||
  469.                             ll->loc_CountryCode == 0x43414E00 /*"CAN"*/))
  470.                     sp->typecnt = 2;
  471.                     /* We check the country code for U.S. or Canada because */
  472.                     /* most of Latin America has no DST.  Even in these two */
  473.                     /* countries there are some exceptions...               */
  474.                 /* else if...  Feel free to add more cases here! */
  475.  
  476.                 if (sp->typecnt > 1)
  477.                     (*fill_tzstate_from_rules)(sp, &startrule, &stoprule);
  478.             }
  479.             CloseLocale(ll);
  480.         }
  481.         CloseLibrary(LocaleBase);
  482.     }
  483.     me->pr_WindowPtr = old_window;
  484.     return valid;
  485. }
  486.  
  487. #ifdef ZIP
  488. time_t time(time_t *tp)
  489. {
  490.     time_t t;
  491.     struct DateStamp ds;
  492.     DateStamp(&ds);
  493.     t = ds.ds_Tick / TICKS_PER_SECOND + ds.ds_Minute * 60
  494.                                       + (ds.ds_Days + 2922) * SECSPERDAY;
  495.     t = mktime(gmtime(&t));
  496.     /* gmtime leaves ds in the local timezone, mktime converts it to GMT */
  497.     if (tp) *tp = t;
  498.     return t;
  499. }
  500. #endif /* ZIP */
  501.  
  502. #endif /* !FUNZIP && !UTIL */
  503.  
  504.  
  505. #if CRYPT || !defined(FUNZIP)
  506.  
  507. /*  sendpkt.c
  508.  *  by A. Finkel, P. Lindsay, C. Sheppner
  509.  *  returns Res1 of the reply packet
  510.  */
  511. /*
  512. #include <exec/types.h>
  513. #include <exec/memory.h>
  514. #include <libraries/dos.h>
  515. #include <libraries/dosextens.h>
  516. #include <proto/exec.h>
  517. #include <proto/dos.h>
  518. */
  519.  
  520. LONG sendpkt(struct MsgPort *pid, LONG action, LONG *args, LONG nargs);
  521.  
  522. LONG sendpkt(pid,action,args,nargs)
  523. struct MsgPort *pid;           /* process identifier (handler message port) */
  524. LONG action,                   /* packet type (desired action)              */
  525.      *args,                    /* a pointer to argument list                */
  526.      nargs;                    /* number of arguments in list               */
  527. {
  528.  
  529.     struct MsgPort *replyport, *CreatePort(UBYTE *, long);
  530.     void DeletePort(struct MsgPort *);
  531.     struct StandardPacket *packet;
  532.     LONG count, *pargs, res1;
  533.  
  534.     replyport = CreatePort(NULL,0L);
  535.     if( !replyport ) return(0);
  536.  
  537.     packet = (struct StandardPacket *)AllocMem(
  538.             (long)sizeof(struct StandardPacket),MEMF_PUBLIC|MEMF_CLEAR);
  539.     if( !packet )
  540.     {
  541.         DeletePort(replyport);
  542.         return(0);
  543.     }
  544.  
  545.     packet->sp_Msg.mn_Node.ln_Name  = (char *)&(packet->sp_Pkt);
  546.     packet->sp_Pkt.dp_Link          = &(packet->sp_Msg);
  547.     packet->sp_Pkt.dp_Port          = replyport;
  548.     packet->sp_Pkt.dp_Type          = action;
  549.  
  550.     /* copy the args into the packet */
  551.     pargs = &(packet->sp_Pkt.dp_Arg1);      /* address of 1st argument */
  552.     for( count=0; count<nargs; count++ )
  553.         pargs[count] = args[count];
  554.  
  555.     PutMsg(pid,(struct Message *)packet);   /* send packet */
  556.  
  557.     WaitPort(replyport);
  558.     GetMsg(replyport);
  559.  
  560.     res1 = packet->sp_Pkt.dp_Res1;
  561.  
  562.     FreeMem((char *)packet,(long)sizeof(*packet));
  563.     DeletePort(replyport);
  564.  
  565.     return(res1);
  566.  
  567. } /* sendpkt() */
  568.  
  569. #endif /* CRYPT || !FUNZIP */
  570.  
  571.  
  572. #if CRYPT || (defined(UNZIP) && !defined(FUNZIP))
  573.  
  574. /* Agetch() reads one raw keystroke -- uses sendpkt() */
  575.  
  576. int Agetch(void)
  577. {
  578.     LONG sendpkt(struct MsgPort *pid, LONG action, LONG *args, LONG nargs);
  579.     struct Task *me = FindTask(NULL);
  580.     struct CommandLineInterface *cli = BADDR(((struct Process *) me)->pr_CLI);
  581.     BPTR fh = cli->cli_StandardInput;   /* this is immune to < redirection */
  582.     void *conp = ((struct FileHandle *) BADDR(fh))->fh_Type;
  583.     char longspace[8];
  584.     long *flag = (long *) ((ULONG) &longspace[4] & ~3); /* LONGWORD ALIGNED! */
  585.     UBYTE c;
  586.  
  587.     *flag = 1;
  588.     sendpkt(conp, ACTION_SCREEN_MODE, flag, 1);         /* assume success */
  589.     Read(fh, &c, 1);
  590.     *flag = 0;
  591.     sendpkt(conp, ACTION_SCREEN_MODE, flag, 1);
  592.     if (c == 3)                                         /* ^C in input */
  593.         Signal(me, SIGBREAKF_CTRL_C);
  594.     return c;
  595. }
  596.  
  597. #endif /* CRYPT || (UNZIP && !FUNZIP) */
  598.  
  599. #endif /* __amiga_filedate_c*/
  600.