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 
FileDate(filename,u)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 
getenv(const char * var)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
setenv(const char * var,const char * value,int overwrite)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().                                            */
set_TZ(long time_zone,int day_light)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 */
GetPlatformLocalTimezone(sp,fill_tzstate_from_rules)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
time(time_t * tp)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 
sendpkt(pid,action,args,nargs)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 
Agetch(void)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