home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 9 Archive / 09-Archive.zip / unzip531.zip / amiga / filedate.c < prev    next >
C/C++ Source or Header  |  1997-05-30  |  23KB  |  672 lines

  1. /* Low-level Amiga routines shared between Zip and UnZip.
  2.  *
  3.  * Contains:  FileDate()
  4.  *            set_TZ()          [SAS/C only]
  5.  *            locale_TZ()
  6.  *            getenv()          [Aztec C only; replaces bad C library versions]
  7.  *            tzset()           [ditto]
  8.  *            gmtime()          [ditto]
  9.  *            localtime()       [ditto]
  10.  *            time()            [ditto]
  11.  *            mkgmtime()
  12.  *            sendpkt()
  13.  *            Agetch()
  14.  *
  15.  * The first five are used by all Info-ZIP programs except fUnZip.
  16.  * The last two are used by all except the non-CRYPT version of fUnZip.
  17.  * Probably some of the stuff in here is unused by ZipNote and ZipSplit too...
  18.  * sendpkt() is used by Agetch() and FileDate(), and by windowheight() in
  19.  * amiga/amiga.c (UnZip).  time() is used only by Zip.
  20.  */
  21.  
  22.  
  23. /* HISTORY/CHANGES
  24.  *  2 Sep 92, Greg Roelofs, Original coding.
  25.  *  6 Sep 92, John Bush, Incorporated into UnZip 5.1
  26.  *  6 Sep 92, John Bush, Interlude "FileDate()" defined, which calls or
  27.  *            redefines SetFileDate() depending upon AMIGADOS2 definition.
  28.  * 11 Oct 92, John Bush, Eliminated AMIGADOS2 switch by determining
  29.  *            revision via OpenLibrary() call.  Now only one version of
  30.  *            the program runs on both platforms (1.3.x vs. 2.x)
  31.  * 11 Oct 92, John Bush, Merged with Zip version and changed arg passing
  32.  *            to take time_t input instead of struct DateStamp.
  33.  *            Arg passing made to conform with utime().
  34.  * 22 Nov 92, Paul Kienitz, fixed includes for Aztec and cleaned up some
  35.  *            lint-ish errors; simplified test for AmigaDOS version.
  36.  * 11 Nov 95, Paul Kienitz, added Agetch() for crypt password input and
  37.  *            UnZip's "More" prompt -- simplifies crypt.h and avoids
  38.  *            use of library code redundant with sendpkt().  Made it
  39.  *            available to fUnZip, which does not use FileDate().
  40.  * 22 Nov 95, Paul Kienitz, created a new tzset() that gets the current
  41.  *            timezone from the Locale preferences.  These exist only under
  42.  *            AmigaDOS 2.1 and up, but it is probably correctly set on more
  43.  *            Amigas than the TZ environment variable is.  We check that
  44.  *            only if TZ is not validly set.  We do not parse daylight
  45.  *            savings syntax except to check for presence vs. absence of a
  46.  *            DST part; United States rules are assumed.  This is better
  47.  *            than the tzset()s in the Amiga compilers' libraries do.
  48.  * 15 Jan 96, Chr. Spieler, corrected the logic when to select low level
  49.  *            sendpkt() (when FileDate(), Agetch() or windowheight() is used),
  50.  *            and AMIGA's Agetch() (CRYPT, and UnZip(SFX)'s UzpMorePause()).
  51.  * 10 Feb 96, Paul Kienitz, re-fiddled that selection logic again, moved
  52.  *            stuff around for clarity.
  53.  * 16 Mar 96, Paul Kienitz, created a replacement localtime() to go with the
  54.  *            new tzset(), because Aztec's is hopelessly broken.  Also
  55.  *            gmtime(), which localtime() calls.
  56.  * 12 Apr 96, Paul Kienitz, daylight savings was being handled incorrectly.
  57.  * 21 Apr 96, Paul Kienitz, had to replace time() as well, Aztec's returns
  58.  *            local time instead of GMT.  That's why their localtime() was bad,
  59.  *            because it assumed time_t was already local, and gmtime() was
  60.  *            the one that checked TZ.
  61.  * 23 Apr 96, Chr. Spieler, deactivated time() replacement for UnZip stuff.
  62.  *            Currently, the UnZip sources do not make use of time() (and do
  63.  *            not supply the working mktime() replacement, either!).
  64.  * 29 Apr 96, Paul Kienitz, created a replacement getenv() out of code that
  65.  *            was previously embedded in tzset(), for reliable global test
  66.  *            of whether TZ is set or not.
  67.  * 19 Jun 96, Haidinger Walter, re-adapted for current SAS/C compiler.
  68.  *  7 Jul 96, Paul Kienitz, smoothed together compiler-related changes.
  69.  *  4 Feb 97, Haidinger Walter, added set_TZ() for SAS/C.
  70.  * 23 Apr 97, Paul Kienitz, corrected Unix->Amiga DST error by adding
  71.  *            mkgmtime() so localtime() could be used.
  72.  * 28 Apr 97, Christian Spieler, deactivated mkgmtime() definition for ZIP;
  73.  *            the Zip sources supply this function as part of util.c.
  74.  */
  75.  
  76. #include <ctype.h>
  77. #include <string.h>
  78. #include <time.h>
  79. #include <errno.h>
  80. #include <stdio.h>
  81.  
  82. #include <exec/types.h>
  83. #include <exec/execbase.h>
  84. #include <exec/memory.h>
  85.  
  86. #ifdef AZTEC_C
  87. #  include <libraries/dos.h>
  88. #  include <libraries/dosextens.h>
  89. #  include <clib/exec_protos.h>
  90. #  include <clib/dos_protos.h>
  91. #  include <clib/locale_protos.h>
  92. #  include <pragmas/exec_lib.h>
  93. #  include <pragmas/dos_lib.h>
  94. #  include <pragmas/locale_lib.h>
  95. #  define ESRCH  ENOENT
  96. #  define EOSERR EIO
  97. #endif
  98.  
  99. #ifdef __SASC
  100. #  include <stdlib.h>
  101. #  if (defined(_M68020) && (!defined(__USE_SYSBASE)))
  102.                             /* on 68020 or higher processors it is faster   */
  103. #    define __USE_SYSBASE   /* to use the pragma libcall instead of syscall */
  104. #  endif                    /* to access functions of the exec.library      */
  105. #  include <proto/exec.h>   /* see SAS/C manual:part 2,chapter 2,pages 6-7  */
  106. #  include <proto/dos.h>
  107. #  include <proto/locale.h>
  108. #  ifdef DEBUG
  109. #     include <sprof.h>
  110. #  endif
  111. #  ifdef MWDEBUG
  112. #    include <stdio.h>      /* include both before memwatch.h again just */
  113. #    include <stdlib.h>     /* to be safe */
  114. #    include "memwatch.h"
  115. #if 0                       /* remember_alloc currently unavailable */
  116. #    ifdef getenv
  117. #      undef getenv         /* remove previously preprocessor symbol */
  118. #    endif
  119. #    define getenv(name)    ((char *)remember_alloc((zvoid *)MWGetEnv(name, __FILE__, __LINE__)))
  120. #endif
  121. #  endif /* MWDEBUG */
  122. #endif
  123.  
  124. #ifndef OF
  125.    #define OF(x) x               /* so crypt.h prototypes compile okay */
  126. #endif
  127. #if defined(ZIP) || defined(FUNZIP)
  128.    void zipwarn  OF((char *, char *));   /* add zipwarn prototype from zip.h */
  129. #  define near                /* likewise */
  130.    typedef unsigned long ulg; /* likewise */
  131.    typedef size_t extent;     /* likewise */
  132.    typedef void zvoid;        /* likewise */
  133. #endif
  134. #include "crypt.h"            /* just so we can tell if CRYPT is supported */
  135.  
  136. int zone_is_set = FALSE;      /* set by tzset() */
  137.  
  138.  
  139. #ifndef FUNZIP
  140.  
  141. /***********************/
  142. /* Function filedate() */
  143. /***********************/
  144.  
  145. /*  FileDate() (originally utime.c), by Paul Wells.  Modified by John Bush
  146.  *  and others (see also sendpkt() comments, below); NewtWare SetFileDate()
  147.  *  clone cheaply ripped off from utime().
  148.  */
  149.  
  150. /* DESCRIPTION
  151.  * This routine chooses between 2 methods to set the file date on AMIGA.
  152.  * Since AmigaDOS 2.x came out, SetFileDate() was available in ROM (v.36
  153.  * and higher).  Under AmigaDOS 1.3.x (less than v.36 ROM), SetFileDate()
  154.  * must be accomplished by constructing a message packet and sending it
  155.  * to the file system handler of the file to be stamped.
  156.  *
  157.  * The system's ROM version is extracted from the external system Library
  158.  * base.
  159.  *
  160.  * NOTE:  although argument passing conforms with utime(), note the
  161.  *        following differences:
  162.  *          - Return value is boolean success/failure.
  163.  *          - If a structure or array is passed, only the first value
  164.  *            is used, which *may* correspond to date accessed and not
  165.  *            date modified.
  166.  */
  167.  
  168. #  ifndef SUCCESS
  169. #    define SUCCESS (-1L)
  170. #    define FAILURE 0L
  171. #  endif
  172.  
  173. #  define ReqVers 36L  /* required library version for SetFileDate() */
  174. #  define ENVSIZE 100  /* max space allowed for an environment var   */
  175.  
  176. extern struct ExecBase *SysBase;
  177.  
  178. #ifdef AZTEC_C                      /* should be pretty safe for reentrancy */
  179.    long timezone = 0;               /* already declared SAS/C external */
  180.    int daylight = 0;                /* likewise */
  181. #endif
  182.  
  183. /* prototypes */
  184. LONG FileDate (char *filename, time_t u[]);
  185. int locale_TZ(void);
  186. void tzset(void);
  187. char *getenv(const char *var);
  188. LONG sendpkt(struct MsgPort *pid, LONG action, LONG *args, LONG nargs);
  189. int Agetch(void);
  190. #ifdef AZTEC_C
  191.    struct tm *gmtime(const time_t *when);
  192.    struct tm *localtime(const time_t *when);
  193. #endif
  194. time_t mkgmtime(struct tm *tm);
  195.  
  196. #ifdef ZIP
  197. int is_zone_set(void);             /* used by HAS_VALID_TIMEZONE macro */
  198. time_t time(time_t *tp);
  199. #endif
  200.  
  201. #ifdef __SASC
  202. void set_TZ(char *TZstr);
  203. #endif
  204.  
  205. #if 0    /* not used YET */
  206. extern zvoid *remember_alloc   OF((zvoid *memptr));
  207. #endif
  208.  
  209. /* =============================================================== */
  210.  
  211.  
  212. LONG FileDate(filename, u)
  213.     char *filename;
  214.     time_t u[];
  215. {
  216.     LONG SetFileDate(UBYTE *filename, struct DateStamp *pDate);
  217.     LONG sendpkt(struct MsgPort *pid, LONG action, LONG *args, LONG nargs);
  218.     struct MsgPort *taskport;
  219.     BPTR dirlock, lock;
  220.     struct FileInfoBlock *fib;
  221.     LONG pktargs[4];
  222.     UBYTE *ptr;
  223.     long ret;
  224.  
  225.     struct DateStamp pDate;
  226.     time_t mtime;
  227.  
  228.     /* tzset(); */
  229.     /* mtime = u[0] - timezone; */
  230.     mtime = mkgmtime(localtime(&u[0]));
  231.  
  232. /* magic number = 2922 = 8 years + 2 leaps between 1970 - 1978 */
  233.     pDate.ds_Days = (mtime / 86400L) - 2922L;
  234.     mtime = mtime % 86400L;
  235.     pDate.ds_Minute = mtime / 60L;
  236.     mtime = mtime % 60L;
  237.     pDate.ds_Tick = mtime * TICKS_PER_SECOND;
  238.  
  239.     if (SysBase->LibNode.lib_Version >= ReqVers)
  240.     {
  241.         return (SetFileDate(filename,&pDate));  /* native routine at 2.0+ */
  242.     }
  243.     else  /* !(SysBase->lib_Version >=ReqVers) */
  244.     {
  245.         if( !(taskport = (struct MsgPort *)DeviceProc(filename)) )
  246.         {
  247.             errno = ESRCH;          /* no such process */
  248.             return FAILURE;
  249.         }
  250.  
  251.         if( !(lock = Lock(filename,SHARED_LOCK)) )
  252.         {
  253.             errno = ENOENT;         /* no such file */
  254.             return FAILURE;
  255.         }
  256.  
  257.         if( !(fib = (struct FileInfoBlock *)AllocMem(
  258.             (long)sizeof(struct FileInfoBlock),MEMF_PUBLIC|MEMF_CLEAR)) )
  259.         {
  260.             errno = ENOMEM;         /* insufficient memory */
  261.             UnLock(lock);
  262.             return FAILURE;
  263.         }
  264.  
  265.         if( Examine(lock,fib)==FAILURE )
  266.         {
  267.             errno = EOSERR;         /* operating system error */
  268.             UnLock(lock);
  269.             FreeMem(fib,(long)sizeof(*fib));
  270.             return FAILURE;
  271.         }
  272.  
  273.         dirlock = ParentDir(lock);
  274.         ptr = (UBYTE *)AllocMem(64L,MEMF_PUBLIC);
  275.         strcpy((ptr+1),fib->fib_FileName);
  276.         *ptr = strlen(fib->fib_FileName);
  277.         FreeMem(fib,(long)sizeof(*fib));
  278.         UnLock(lock);
  279.  
  280.         /* now fill in argument array */
  281.  
  282.         pktargs[0] = 0;
  283.         pktargs[1] = (LONG)dirlock;
  284.         pktargs[2] = (LONG)&ptr[0] >> 2;
  285.         pktargs[3] = (LONG)&pDate;
  286.  
  287.         errno = ret = sendpkt(taskport,ACTION_SET_DATE,pktargs,4L);
  288.  
  289.         FreeMem(ptr,64L);
  290.         UnLock(dirlock);
  291.  
  292.         return SUCCESS;
  293.     }  /* ?(SysBase->lib_Version >= ReqVers) */
  294. } /* FileDate() */
  295.  
  296.  
  297. #ifdef ZIP
  298. int is_zone_set(void)            /* used by HAS_VALID_TIMEZONE macro */
  299. {
  300.     tzset();                     /* sets global zone_is_set */
  301.     return zone_is_set;
  302. }
  303. #endif
  304.  
  305.  
  306. /* set timezone and daylight to settings found in locale.library */
  307. int locale_TZ(void)
  308. {
  309.     struct Library *LocaleBase;
  310.     struct Locale *ll;
  311.     struct Process *me = (void *) FindTask(NULL);
  312.     void *old_window = me->pr_WindowPtr;
  313.     BPTR eh;
  314.     int z, valid = FALSE;
  315.  
  316.     /* read timezone from locale.library if TZ envvar missing */
  317.     me->pr_WindowPtr = (void *) -1;   /* suppress any "Please insert" popups */
  318.     if (LocaleBase = OpenLibrary("locale.library", 0)) {
  319.         if (ll = OpenLocale(NULL)) {
  320.             z = ll->loc_GMTOffset;
  321.             if (z == -5) {
  322.                 if (eh = Lock("ENV:sys/locale.prefs", ACCESS_READ))
  323.                     UnLock(eh);
  324.                 else
  325.                     z = 5; /* bug: locale not initialized, default is bogus! */
  326.             } else
  327.                 zone_is_set = TRUE;
  328.             timezone = z * 60;
  329.             daylight = (z >= 4*60 && z <= 9*60);    /* apply in the Americas */
  330.             valid = TRUE;
  331.             CloseLocale(ll);
  332.         }
  333.         CloseLibrary(LocaleBase);
  334.     }
  335.     me->pr_WindowPtr = old_window;
  336.     return valid;
  337. }
  338.  
  339.  
  340. #ifdef __SASC
  341. /* Stores data from timezone and daylight to ENV:TZ.                  */
  342. /* Only set if TZ string is absent or empty                           */
  343. /* ENV:TZ is required to exist by some other SAS/C library functions, */
  344. /* e.g. stat(), that call tzset() again rather than using already set */
  345. /* timezone and daylight.                                             */
  346. void set_TZ(char *TZstr)
  347. {
  348.     char put_tz[13];  /* string for putenv: "TZ=aaabbbccc" */
  349.     int offset;
  350.     if ((TZstr == NULL) || (TZstr && (*TZstr == '\0'))) {
  351.         offset = timezone / 3600;
  352.         /* create TZ string and make sure hours range from 0-24 */
  353.         sprintf(put_tz,"TZ=UTC%+03dDST",abs(offset)>24 ? 0 : offset);
  354.         if (daylight == 0)
  355.            put_tz[9] = '\0';     /* truncate daylight savings part */
  356.         /* Now store TZ to ENV:TZ. Will match values from locale.library */
  357.         /* or "UTC+00" if no valid information was found at all.         */
  358.         putenv(put_tz);
  359.         __tzset();   /* initialize _TZ */
  360.     }
  361. }
  362. #endif /* __SASC */
  363.  
  364. void tzset(void) {
  365.     char *p,*TZstring;
  366.     int z,valid = FALSE;
  367.  
  368.     if (zone_is_set)
  369.         return;
  370.     timezone = 0;       /* default is GMT0 which means no offsets */
  371.     daylight = 0;       /* from local system time                 */
  372.     TZstring = getenv("TZ");              /* read TZ envvar */
  373.     if (TZstring && TZstring[0]) {        /* TZ exists and has contents? */
  374.         z = 3600;
  375.         for (p = TZstring; *p && !isdigit(*p) && *p != '-'; p++) ;
  376.         if (*p == '-')
  377.             z = -3600, p++;
  378.         if (*p) {
  379.             timezone = 0;
  380.             do {
  381.                 while (isdigit(*p))
  382.                     timezone = timezone * 10 + z * (*p++ - '0'), valid = TRUE;
  383.                 if (*p == ':') p++;
  384.             } while (isdigit(*p) && (z /= 60) > 0);
  385.         }
  386.         while (isspace(*p)) p++;                      /* probably not needed */
  387.         if (valid)
  388.             zone_is_set = TRUE, daylight = !!*p;   /* a DST name part exists */
  389.     }
  390.     if (!valid)
  391.         locale_TZ();               /* read locale.library */
  392. #ifdef __SASC
  393.     /* Some SAS/C library functions, e.g. stat(), call library  */
  394.     /* __tzset() themselves. So envvar TZ *must* exist in order */
  395.     /* to get the right offset from GMT.                        */
  396.     set_TZ(TZstring);
  397. #endif /* __SASC */
  398. }
  399.  
  400.  
  401. #ifdef AZTEC_C    /* SAS/C uses library getenv() */
  402. char *getenv(const char *var)         /* not reentrant! */
  403. {
  404.     static char space[ENVSIZE];
  405.     struct Process *me = (void *) FindTask(NULL);
  406.     void *old_window = me->pr_WindowPtr;
  407.     char *ret = NULL, **varp = &var;     /* <= NECESSARY to prevent "loss of" */
  408.                                          /*       const/volatile info" errors */
  409.     me->pr_WindowPtr = (void *) -1;   /* suppress any "Please insert" popups */
  410.     if (SysBase->LibNode.lib_Version >= ReqVers) {
  411.         if (GetVar(*varp, space, ENVSIZE - 1, /* GVF_GLOBAL_ONLY */ 0) > 0)
  412.             ret = space;
  413.     } else {                    /* early AmigaDOS, get env var the crude way */
  414.         BPTR hand, foot, spine;
  415.         int z = 0;
  416.         if (foot = Lock("ENV:", ACCESS_READ)) {
  417.             spine = CurrentDir(foot);
  418.             if (hand = Open(*varp, MODE_OLDFILE)) {
  419.                 z = Read(hand, space, ENVSIZE - 1);
  420.                 Close(hand);
  421.             }
  422.             UnLock(CurrentDir(spine));
  423.         }
  424.         if (z > 0) {
  425.             space[z] = '\0';
  426.             ret = space;
  427.         }
  428.     }
  429.     me->pr_WindowPtr = old_window;
  430.     return ret;
  431. }
  432. #endif /* AZTEC_C */
  433.  
  434.  
  435. #if (!defined(ZIP) || !defined(NO_MKTIME))
  436. /* this mkgmtime() code is a simplified version taken from Zip's mktime.c */
  437.  
  438. /* Return the equivalent in seconds past 12:00:00 a.m. Jan 1, 1970 GMT
  439.    of the Greenwich Mean time and date in the exploded time structure `tm',
  440.    and set `tm->tm_yday' and `tm->tm_wday', but not `tm->tm_isdst'.
  441.    Return -1 if any of the other fields in `tm' has an invalid value. */
  442.  
  443. /* Nonzero if `y' is a leap year, else zero. */
  444. #define leap(y) (((y) % 4 == 0 && (y) % 100 != 0) || (y) % 400 == 0)
  445.  
  446. /* Number of leap years from 1970 to `y' (not including `y' itself). */
  447. #define nleap(y) (((y) - 1969) / 4 - ((y) - 1901) / 100 + ((y) - 1601) / 400)
  448.  
  449. /* Accumulated number of days from 01-Jan up to start of current month. */
  450. extern const ush ydays[];  /* in fileio.c */
  451.  
  452.  
  453. time_t mkgmtime(struct tm *tm)
  454. {
  455.   int years, months, days, hours, minutes, seconds;
  456.  
  457.   years = tm->tm_year + 1900;   /* year - 1900 -> year */
  458.   months = tm->tm_mon;          /* 0..11 */
  459.   days = tm->tm_mday - 1;       /* 1..31 -> 0..30 */
  460.   hours = tm->tm_hour;          /* 0..23 */
  461.   minutes = tm->tm_min;         /* 0..59 */
  462.   seconds = tm->tm_sec;         /* 0..61 in ANSI C. */
  463.  
  464.   if (years < 1970
  465.       || months < 0 || months > 11
  466.       || days < 0
  467.       || days >= (months == 11? 365 : ydays[months + 1]) - ydays[months]
  468.            + (months == 1 && leap(years))
  469.       || hours < 0 || hours > 23
  470.       || minutes < 0 || minutes > 59
  471.       || seconds < 0 || seconds > 61)
  472.   return -1;
  473.  
  474.   /* Set `days' to the number of days into the year. */
  475.   days += ydays[months] + (months > 1 && leap(years));
  476.   tm->tm_yday = days;
  477.  
  478.   /* Now set `days' to the number of days since Jan 1, 1970. */
  479.   days += 365 * (years - 1970) + nleap(years);
  480.   tm->tm_wday = (days + 4) % 7; /* Jan 1, 1970 was Thursday. */
  481. /*  tm->tm_isdst = 0; */
  482.  
  483.   return (time_t)(86400L * (unsigned long)days + 3600L * (unsigned long)hours +
  484.                   (unsigned long)(60 * minutes + seconds));
  485. }
  486.  
  487. #endif /* !ZIP || !NO_MKTIME */
  488.  
  489.  
  490. #ifdef AZTEC_C    /* SAS/C uses library gmtime() */
  491. struct tm *gmtime(const time_t *when)
  492. {
  493.     static struct tm tbuf;   /* this function is intrinsically non-reentrant */
  494.     static short smods[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  495.     long days = *when / 86400;
  496.     long secs = *when % 86400;
  497.     short yell, yday;
  498.  
  499.     tbuf.tm_wday = (days + 4) % 7;                   /* 1/1/70 is a Thursday */
  500.     tbuf.tm_year = 70 + 4 * (days / 1461);
  501.     yday = days % 1461;
  502.     while (yday >= (yell = (tbuf.tm_year & 3 ? 365 : 366)))
  503.         yday -= yell, tbuf.tm_year++;
  504.     smods[1] = (tbuf.tm_year & 3 ? 28 : 29);
  505.     tbuf.tm_mon = 0;
  506.     tbuf.tm_yday = yday;
  507.     while (yday >= smods[tbuf.tm_mon])
  508.         yday -= smods[tbuf.tm_mon++];
  509.     tbuf.tm_mday = yday + 1;
  510.     tbuf.tm_isdst = 0;
  511.     tbuf.tm_sec = secs % 60;
  512.     tbuf.tm_min = (secs / 60) % 60;
  513.     tbuf.tm_hour = secs / 3600;
  514. #ifdef AZTEC_C
  515.     tbuf.tm_hsec = 0;
  516. #endif
  517.     return &tbuf;
  518. }
  519. #endif /* AZTEC_C */
  520.  
  521.  
  522. #ifdef AZTEC_C    /* SAS/C uses library localtime() */
  523. struct tm *localtime(const time_t *when)
  524. {
  525.     struct tm *t;
  526.     time_t localwhen;
  527.     int dst = FALSE, sundays, lastweekday;
  528.  
  529.     tzset();
  530.     localwhen = *when - timezone;
  531.     t = gmtime(&localwhen);
  532.     /* So far we support daylight savings correction by the USA rule only: */
  533.     if (daylight && t->tm_mon >= 3 && t->tm_mon <= 9) {
  534.         if (t->tm_mon > 3 && t->tm_mon < 9)      /* May Jun Jul Aug Sep: yes */
  535.             dst = TRUE;
  536.         else {
  537.             sundays = (t->tm_mday + 6 - t->tm_wday) / 7;
  538.             if (t->tm_wday == 0 && t->tm_hour < 2 && sundays)
  539.                 sundays--;           /* a Sunday does not count until 2:00am */
  540.             if (t->tm_mon == 3 && sundays > 0)      /* first sunday in April */
  541.                 dst = TRUE;
  542.             else if (t->tm_mon == 9) {
  543.                 lastweekday = (t->tm_wday + 31 - t->tm_mday) % 7;
  544.                 if (sundays < (37 - lastweekday) / 7)
  545.                     dst = TRUE;                    /* last sunday in October */
  546.             }
  547.         }
  548.         if (dst) {
  549.             localwhen += 3600;
  550.             t = gmtime(&localwhen);                   /* crude but effective */
  551.             t->tm_isdst = 1;
  552.         }
  553.     }
  554.     return t;
  555. }
  556. #endif /* AZTEC_C */
  557.  
  558.  
  559. #ifdef AZTEC_C    /* SAS/C uses library gmtime() */
  560. #ifdef ZIP
  561. time_t time(time_t *tp)
  562. {
  563.     time_t t;
  564.     struct DateStamp ds;
  565.     DateStamp(&ds);
  566.     t = ds.ds_Tick / TICKS_PER_SECOND + ds.ds_Minute * 60
  567.                                       + (ds.ds_Days + 2922) * 86400;
  568.     t = mktime(gmtime(&t));
  569.     /* gmtime leaves ds in the local timezone, mktime converts it to GMT */
  570.     if (tp) *tp = t;
  571.     return t;
  572. }
  573. #endif /* ZIP */
  574. #endif /* AZTEC_C */
  575.  
  576. #endif /* !FUNZIP */
  577.  
  578.  
  579. #if CRYPT || !defined(FUNZIP)
  580.  
  581. /*  sendpkt.c
  582.  *  by A. Finkel, P. Lindsay, C. Sheppner
  583.  *  returns Res1 of the reply packet
  584.  */
  585. /*
  586. #include <exec/types.h>
  587. #include <exec/memory.h>
  588. #include <libraries/dos.h>
  589. #include <libraries/dosextens.h>
  590. #include <proto/exec.h>
  591. #include <proto/dos.h>
  592. */
  593.  
  594. LONG sendpkt(struct MsgPort *pid, LONG action, LONG *args, LONG nargs);
  595.  
  596. LONG sendpkt(pid,action,args,nargs)
  597. struct MsgPort *pid;           /* process identifier (handler message port) */
  598. LONG action,                   /* packet type (desired action)              */
  599.      *args,                    /* a pointer to argument list                */
  600.      nargs;                    /* number of arguments in list               */
  601. {
  602.  
  603.     struct MsgPort *replyport, *CreatePort(UBYTE *, long);
  604.     void DeletePort(struct MsgPort *);
  605.     struct StandardPacket *packet;
  606.     LONG count, *pargs, res1;
  607.  
  608.     replyport = CreatePort(NULL,0L);
  609.     if( !replyport ) return(0);
  610.  
  611.     packet = (struct StandardPacket *)AllocMem(
  612.             (long)sizeof(struct StandardPacket),MEMF_PUBLIC|MEMF_CLEAR);
  613.     if( !packet )
  614.     {
  615.         DeletePort(replyport);
  616.         return(0);
  617.     }
  618.  
  619.     packet->sp_Msg.mn_Node.ln_Name  = (char *)&(packet->sp_Pkt);
  620.     packet->sp_Pkt.dp_Link          = &(packet->sp_Msg);
  621.     packet->sp_Pkt.dp_Port          = replyport;
  622.     packet->sp_Pkt.dp_Type          = action;
  623.  
  624.     /* copy the args into the packet */
  625.     pargs = &(packet->sp_Pkt.dp_Arg1);      /* address of 1st argument */
  626.     for( count=0; count<nargs; count++ )
  627.         pargs[count] = args[count];
  628.  
  629.     PutMsg(pid,(struct Message *)packet);   /* send packet */
  630.  
  631.     WaitPort(replyport);
  632.     GetMsg(replyport);
  633.  
  634.     res1 = packet->sp_Pkt.dp_Res1;
  635.  
  636.     FreeMem((char *)packet,(long)sizeof(*packet));
  637.     DeletePort(replyport);
  638.  
  639.     return(res1);
  640.  
  641. } /* sendpkt() */
  642.  
  643. #endif /* CRYPT || !FUNZIP */
  644.  
  645.  
  646. #if CRYPT || (defined(UNZIP) && !defined(FUNZIP))
  647.  
  648. /* Agetch() reads one raw keystroke -- uses sendpkt() */
  649.  
  650. int Agetch(void)
  651. {
  652.     LONG sendpkt(struct MsgPort *pid, LONG action, LONG *args, LONG nargs);
  653.     struct Task *me = FindTask(NULL);
  654.     struct CommandLineInterface *cli = BADDR(((struct Process *) me)->pr_CLI);
  655.     BPTR fh = cli->cli_StandardInput;   /* this is immune to < redirection */
  656.     void *conp = ((struct FileHandle *) BADDR(fh))->fh_Type;
  657.     char longspace[8];
  658.     long *flag = (long *) ((ULONG) &longspace[4] & ~3); /* LONGWORD ALIGNED! */
  659.     UBYTE c;
  660.  
  661.     *flag = 1;
  662.     sendpkt(conp, ACTION_SCREEN_MODE, flag, 1);         /* assume success */
  663.     Read(fh, &c, 1);
  664.     *flag = 0;
  665.     sendpkt(conp, ACTION_SCREEN_MODE, flag, 1);
  666.     if (c == 3)                                         /* ^C in input */
  667.         Signal(me, SIGBREAKF_CTRL_C);
  668.     return c;
  669. }
  670.  
  671. #endif /* CRYPT || (UNZIP && !FUNZIP) */
  672.